问题 NSTextField超过NSOpenGLView


我创建了一个带有NSOpenGLView的窗口,我正在将OpenGL内容渲染到其中。

我想在视图中添加一些按钮和文本字段:我可以使用界面构建器(或代码)添加NSTextFields和NSButton,但它们不会出现。

NSOpenGLView被记录为无法拥有子视图,因此我通过直接从NSView派生并实现代码来创建和使用NSOpenGLContext来创建我自己的CustomGLView。但是子视图仍然没有出现: - OpenGL上下文描绘了它们。

在Windows上,这个问题不存在: - 用于托管OpenGL的Windows必须拥有 WS_CLIPCHILDREN 和 WS_CHIPSIBLINGS 样式集确保OpenGL表面不会遮挡任何对等或子子(视图)。

如何在使用OpenGL绘制的NSView上显示子视图?


1773
2018-02-08 12:16


起源



答案:


你有2个选择:

  1. 为文本字段创建一个窗口。添加为托管OpenGL视图的窗口的子窗口。主要的缺点是,如果移动Open GL视图,您必须正确管理它的定位。

  2. 像这样设置视图层次结构:

    • 层-已备份 视图
      • 层-托管 查看其图层包含OpenGL图层
      • 文本域

6
2018-02-09 12:54



我不太清楚图层支持的视图是什么意思。 developer.apple.com/mac/library/samplecode/... 并不意味着托管视图会发生很多特殊需求。也许它隐含在缓冲选中。你需要做的就是: [openGLView setWantsLayer:YES] - Chris Becke
完全 - 选择#2然后去 CAOpenGLLayer 并忘记这个过时的,错误的和笨拙的课程 NSOpenGLView。这不值得(现在)。 - Jay


答案:


你有2个选择:

  1. 为文本字段创建一个窗口。添加为托管OpenGL视图的窗口的子窗口。主要的缺点是,如果移动Open GL视图,您必须正确管理它的定位。

  2. 像这样设置视图层次结构:

    • 层-已备份 视图
      • 层-托管 查看其图层包含OpenGL图层
      • 文本域

6
2018-02-09 12:54



我不太清楚图层支持的视图是什么意思。 developer.apple.com/mac/library/samplecode/... 并不意味着托管视图会发生很多特殊需求。也许它隐含在缓冲选中。你需要做的就是: [openGLView setWantsLayer:YES] - Chris Becke
完全 - 选择#2然后去 CAOpenGLLayer 并忘记这个过时的,错误的和笨拙的课程 NSOpenGLView。这不值得(现在)。 - Jay


只需致电 -setWantsLayer:YES 在NSOpenGLView的子视图上。


5
2018-05-04 11:46



谢啦!这对我有所帮助! - SAKrisT
如果您这样做,请确保您的代码配置文件。为NSOpenGLView添加CA层可能会导致巨大的性能损失。额外的内存和渲染时间与NSOpenGLView的大小成正比。对于我的项目(游戏),帧速率减半。 - Womble


我还没有深入研究OpenGL,但我的理解是你可以完成视觉效果 影响 Quartz Extreme的子视图使用图层支持的视图;然而,那些可能是 问题。由于不直接支持子视图,因此任何解决方案都可能成为黑客。

实际上,该链接中的解决方案实际上会破坏第二个窗口显示在您的OpenGL显示上,第二个窗口显示您想要的Cocoa视图。

下面的代码(来自上面的链接)是我没有测试的东西(再次不是OpenGL的人 - 但是)看起来像一个相当聪明的方法:

// This is the GL Window and view you already have
glWindow = [[GLWindow alloc] initWithContentRect:windowRect];
glView = [[[GLView alloc] initWithFrame:NSMakeRect(0, 0, windowRect.size.width, windowRect.size.height)] autorelease];
[glView translateOriginToPoint:NSMakePoint(glView.bounds.size.width/2, glView.bounds.size.height/2)];
[glWindow setContentView:glView];

// And here's your transparent UI window
uiWindow = [[TransparentWindow alloc] initWithContentRect:windowRect];
uiView = [[[NSView alloc] initWithFrame:NSMakeRect(0, 0, windowRect.size.width, windowRect.size.height)] autorelease];
[uiView translateOriginToPoint:NSMakePoint(uiView.bounds.size.width/2, uiView.bounds.size.height/2)];
uiView.wantsLayer = YES;

[uiWindow setContentView:uiView];
[glWindow addChildWindow:uiWindow ordered:NSWindowAbove];

同样,我没有对此进行过测试,但看起来它会为您带来您想要的视觉效果。


1
2018-02-08 12:29



请参阅下面的评论,了解以这种方式使用图层对性能的影响。 - Womble


文本可以渲染成纹理 - 我只是将它用于项目,做了很多寻找示例代码,最终找到了Apple的GLString演示代码,这是一个绝对的方法:

http://developer.apple.com/library/mac/#samplecode/CocoaGL/Listings/GLString_m.html

我没有尝试过添加按钮,但你可以自己绘制并将点击事件的位置与按钮的位置进行比较......


1
2018-03-07 01:28





这是我的解决方案:

1)创建父NSView(让我们称之为 parentView)。

2)添加NSOpenGLView子项 parentView

3)添加一个额外的NSView子项 parentView (确保这是在层次结构中的OpenGLView之后)。您可以向此视图添加其他TextField等。

4)在父控件的ViewController中确保调用[parentView setWantsLayer:TRUE];我这样做了 - (void)viewWillAppear


1
2018-05-22 13:57





1)NSOpenGLView 能够 有一个子视图。它甚至可以充足。

2)原因 一些 视图,控件和其他元素被NSOpenGLView欺负是由于应用程序启动时的加载过程。即如果添加滑块或文本字段 以上 并且在NSOpenGLView所在的窗口的内容视图中,在Application-Launch上,文本字段很可能会在NSOpenGLView下面结束。

这是Apple Bug。他们知道这件事。

即使不向NSOpenGLView添加子视图,您也可以轻松解决它...

在Interface Builder中,将CustomView拖动到画布中(不是视图)。并使用滑块,文本和不需要的方式设置它。然后在视图控制器中创建一个插座(称之为topView)。然后你的代码中的某个地方......也许(applicationDidFinishLaunching)添加这一行......

[_window.contentView addSubview:_topView]; (做你的定位和布局) 这将完全相同,就像您在IB内部将其拖入contentView一样。只有它会在正确的Z位置画出令人讨厌的东西。

你以这种方式放松IB的约束并且必须手动操作

也可以只是子类化和CAOpenGLLayer,并将其用作常规NSView内部的后备层。它也被正确绘制了......

这是Apple希望这样做的方式。 CALayers是天赐之物;)

在搜索中输入以下字符串** NSOpenGLLayer **并按Enter键以到达它所在的位置... NSOpenGLLayer

希望这可以帮助....


1
2018-01-30 23:19





NSOpenGLView 根据文档不能有子视图。即使你是NSOpenGLView的子类,也不会改变任何东西。

你可以做的是创建一个NSView,它将同时包含NSOpenGLView和NSTextField。然后,您按正确的顺序重叠它们,以便在另一个上面进行一次绘制。


0
2018-02-08 12:28



我没有NSOpenGGView的子类 - 我创建了一个全新的NSView子类,然后我添加了代码来获取NSOpenGLContext。 - Chris Becke
我在Interface Builder中尝试过:创建了一个通用内容NSView,并给它一个NSOpenGLView和一个NSButton。我定位它们的方式并不重要,NSOpenGLView总是在NSButton / NSTextField上绘制。 - Chris Becke