我有一个在Qt应用程序内渲染OpenGL场景的QGLWidget
。我想添加一些其他半透明的Qt小部件,覆盖在QGLWidget
之上。这比使用标准小部件要困难得多,因为Qt的painter类不知道OpenGL绘图上下文。所以,如果我只是做显而易见的事情,并在QGLWidget
的顶部放置一个透明的工具栏,工具栏的透明部分反而呈现黑色(它在绘画时无法访问OpenGL帧缓冲区)。
似乎建议处理这种事情的方法是在绘制OpenGL场景后覆盖2D内容。链接的例子看起来很简单,只要你只是画简单的形状。相反,我想做的是推迟一些子QWidget
对象的绘制,以便在QGLWidget
的paint事件中完成。
所以,我的问题归结为:
- 防止覆盖
QWidget
s在正常的2D环境中绘制。 - 在
QGLWidget
的paint事件处理程序中,在绘制构成背景的3D场景后绘制叠加。
这个列表中的第二项似乎很简单:我可以在QGLWidget
的paint事件中使用QWidget::render()
在视窗顶部绘制所需的小部件。
第一项更棘手:我需要一种方法来防止小部件在正常事件过程中绘制,并且只在QGLWidget
的绘制处理程序中绘制它们。一个明显的方法是使用QWidget::hide()
隐藏叠加。这确实允许我在OpenGL场景上画出我想要的小部件。但是,由于小部件是隐藏的,因此它们不会响应鼠标或键盘事件。作为一个例子,我使用一个QToolBar
上面有几个按钮,工具栏是正确绘制的,但没有功能(没有按钮响应点击)。所以,如果沿着这条路走下去,我似乎需要一种方法来强制小部件仍然响应事件,即使它是隐藏的。
我尝试过的另一种方法是使用事件过滤器拦截QToolBar
的油漆事件,目的是防止工具栏油漆自己。但是,工具栏仍然呈现;我假设这是因为工具栏上的各种按钮是仍然绘制的子部件,即使我拦截父部件的绘制事件。
我不完全理解你的问题,但我会尽力回答标题中提出的问题。您应该使用事件过滤器。使用widget->installEventFilter(object)
安装一个事件过滤器,其中widget
是您想要阻止绘画的小部件,object
是任何qobject派生类的对象。重新实现这个类的eventFilter
:
bool MyClass::eventFilter(QObject* object, QEvent* event) {
if (event->type() == QEvent::Paint) { return true; }
return false;
}
当你从eventFilter返回true时,事件被过滤,paint不会发生。
您也可以尝试使用widget->setUpdatesEnabled(false)
暂时禁用绘画。完成后不要忘记重新启用它。