半透明的QWidget覆盖在QGLWidget上:奇怪的结果

8
我有一个全尺寸的QGLWidget,使用QPainter绘制应用程序背景(可能将来会改用本机openGL命令)。
在这个QGLWidget上面,我使用QWidgets(非GL)作为用户界面元素。例如,这些是QLineEdits和QPushButtons。我将它们放入自定义绘制的QWidget中,该QWidget使用半透明背景绘制。 QLineEdit和QPushButton的paintEvents被覆盖,并且也使用半透明背景。
整个UI应该看起来像下面的样子(这是一张截图,我禁用了OpenGL并使用QWidget替换了QGLWidget作为背景。请注意半透明的顶部栏,它还绘制了阴影(在其自己的区域内)):
当QLineEdit具有焦点时,它应该具有更高的不透明度,但仍然不是完全不透明的:
所以现在,启用OpenGL(背景是QGLWidget),上面的半透明小部件不会绘制在背景上,而是绘制在(似乎是)未初始化的数据上。穿过顶部栏的图像有时是整个窗口本身,有时是当前在我的桌面上的其他窗口。
目前看起来像下面这样(在此屏幕截图中,半透明绘制操作所绘制的数据似乎是小部件本身的图像,具有偏移量。):
当我在行编辑器中写入文本(这里是“这是之前存在的一些文本!”),将其删除并将焦点设置回背景小部件时(因此放大镜图标和占位符文本出现),以前绘制的内容仍然会显现出来(请注意,可见边框应该不再可见,但也仍然显现出来):
问题是:半透明小部件不是绘制在底层小部件的上方,而是绘制在旧结果的上方,最初是类似“未初始化内存”的东西。
为什么会发生这种情况?我如何解决这个问题?
回答前应该知道的事情:
  • 背景场景是由瓷砖组成的,这些瓷砖被离屏渲染。因此,可以非常快速地绘制,并且对于覆盖层的每一个小变化重新绘制背景不会有问题。
  • 顶部栏是一个自定义的QWidget,具有手动绘制和排列所包含的两个小部件(按钮和行编辑器)。
  • 这两个小部件重写了paintEvent,只在它们获得焦点时绘制自己的(半透明)背景,并且不使用Qt已提供的框架。因此,第二个截图中的白色边框是在我的自定义paintEvent中绘制的。
  • 我希望能够分别实现背景和叠加小部件的组合。背景是一个AbstractMapView,其中包含一些具体的地图视图类。整个窗口是一个AbstractView(也有多个具体视图),它包含一个具体的地图视图和叠加小部件,以一种自身决定的方式组合。因此,我不希望叠加小部件的逻辑成为底层地图视图的一部分。(希望您理解这一点,因为它有点复杂。)
2个回答

3
这似乎是GL内容(即您的背景,也称为QGLWidget)不在Qt上下文中的问题。虽然我不是Qt中GL绘图的专家,但您可能需要查看关于GL绘图和QLabel的讨论,以获取一些方向/潜在提示。

http://www.qtcentre.org/threads/40335-QLabel-on-top-of-a-QGLWidget-background-issue

简而言之,我们在办公室使用OpenGL绘制和离屏渲染地图,确保Qt知道像素非常重要,这样您的前景小部件可以应用半透明度到其背景上。
我们使用的特定产品还将地图呈现为瓷砖,并支持在缓冲区中提供GL输出(即作为位图提供快照),此时我们使用常规QWidget的paintEvent来绘制缓冲区,以便绘制的像素处于Qt上下文中。

感谢您指出这个问题并提供链接。然而,建议的解决方案(使用图形场景)听起来太过繁重。您说:“非常重要的是确保Qt知道像素,这样前景小部件就可以将半透明应用于它们的背景。” 您是如何做到这一点的?是否有可能在没有图形场景的情况下找到解决方案?还请注意,我想绘制小部件,而不仅仅是图形项。 - leemes
@leemes 我和我们的绘画专家交流了一下,更新了我的答案以提供更多信息。简而言之,将GL输出放入缓冲区并使用Qt的工具在屏幕上进行绘制。 - Matthew
非常感谢。我仍然看到一个缺点:渲染的地图将被复制到RAM中(进入我的进程)。我是正确的吗?正如你所说,由于Qt需要“知道”这些像素,这是必要的步骤。所以这不能更好了吗? - leemes
据我理解,渲染的地图/输出将被复制到RAM中,并成为您的进程的一部分。不幸的是,我不知道任何其他方法可以将图形输出(例如像素)带入Qt上下文而不使用Qt的绘画工具。话虽如此,我们在工作中使用这种方法来运行多个程序,其中许多具有实时要求,效果非常好。 - Matthew

-1

您可以使用Qt::SplashScreen标志定义一个QFrame作为搜索框,并设置其不透明度。将您的小部件放置在其中,例如搜索文本框,并将其定位到主窗口上应该出现的位置。当主窗口移动或调整大小时,重写其moveEvent以重新定位它也是一个好主意。


设置Qt::SplashScreen标志似乎对于OP的问题没有任何影响。 - Jason R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接