Qt 半透明QWidget优于QGLWidget:奇怪的结果

Qt 半透明QWidget优于QGLWidget:奇怪的结果,qt,opengl,overlay,transparency,Qt,Opengl,Overlay,Transparency,我有一个全尺寸的QGLWidget,它使用QPaint绘制应用程序背景(将来可能会更改为原生openGL命令) 在这个QGLWidget之上,我使用QWidget(非GL)作为用户界面元素。例如,这些是QLineEdits和QpushButton。我把它们放进一个定制的QWidget中,它使用半透明的背景画。QLineEdit和QPushButton的paintEvents会被覆盖,并使用半透明背景 整个UI应该如下所示(这是一个屏幕截图,我禁用了OpenGL,并使用QWidget而不是QGLW

我有一个全尺寸的QGLWidget,它使用QPaint绘制应用程序背景(将来可能会更改为原生openGL命令)

在这个QGLWidget之上,我使用QWidget(非GL)作为用户界面元素。例如,这些是QLineEdits和QpushButton。我把它们放进一个定制的QWidget中,它使用半透明的背景画。QLineEdit和QPushButton的paintEvents会被覆盖,并使用半透明背景

整个UI应该如下所示(这是一个屏幕截图,我禁用了OpenGL,并使用QWidget而不是QGLWidget作为背景。请注意半透明的顶部栏,它还绘制了一个阴影(在自己的区域内)):

当QLineEdit具有焦点时,它应该具有更高的不透明度,但仍然不是完全不透明:

所以现在,启用了OpenGL(当时的背景是QGLWidget),上面的半透明小部件不会在背景上绘制,而是在(似乎是)未初始化的数据上绘制。通过顶部栏闪烁的图像有时是整个窗口本身,有时是我桌面上的其他窗口

当前看起来如下所示(在此屏幕截图中,绘制半透明绘制操作的数据似乎是小部件本身的图像,具有偏移量):

当我将文本写入行编辑(这里是:“这是以前存在过的一些文本!”)时,将其删除,并将焦点设置回背景小部件(因此会显示放大镜图标和占位符文本),以前绘制的内容仍然会亮起(请注意,可见边框不应再可见,但仍会发光):

所以问题是:半透明的小部件不是绘制在底层小部件之上,而是绘制在旧结果之上,最初类似于“未初始化内存”

为什么会发生这种情况?我如何解决问题?

在回答之前,您应该知道的事情:

  • 背景场景是由屏幕外渲染的瓷砖组成的。因此,可以非常快速地绘制背景,并且覆盖层的每一个微小变化都可以重新绘制背景
  • 顶栏是一个定制的QWidget,手动绘制和排列包含的两个Widget(按钮和行编辑)
  • 这两个小部件覆盖了paintEvent,只有当它们有焦点时才绘制它们自己的(半透明)背景,并且不使用Qt已经提供的帧。因此,第二个屏幕截图中的白色边框是在我的自定义paintEvent中绘制的
  • 我希望后台和覆盖窗口小部件的组成可以单独实现。后台是一个
    抽象地图视图
    ,它有一些具体的地图视图类。整个窗口是一个
    抽象视图
    (也有多个具体视图),其中既包含具体的地图视图,也包含覆盖小部件,其组成方式由自身决定。因此,我不希望覆盖小部件的逻辑成为基础地图视图的一部分。(我希望您理解这一点,因为它有点复杂。)

这听起来像是一个GL内容(即您的背景,又称QGLWidget)不在Qt上下文中的问题。虽然我不是Qt的GL绘制专家,但您可能想看看关于GL绘制和QLabel的讨论,以获得一些方向/潜在提示

简言之,我们在办公室使用OpenGL绘制和地图的屏幕外渲染,确保Qt了解像素非常重要,这样您的前景小部件可以将半透明度应用于其背景


我们使用的特定产品还以平铺形式呈现地图,并支持在缓冲区中提供GL输出(即,它被称为快照并作为位图提供)此时,我们使用常规QWidget的paintEvent绘制缓冲区,以便绘制的像素位于Qt上下文中。

您可以使用Qt::SplashScreen标志定义Qframe作为搜索框并设置其不透明度。将您的小部件(如搜索文本框)放入其中,并将其放置在主窗口上应该显示的位置。它也将在主窗口被移动或调整大小时覆盖其移动事件,重新定位它是一个好主意。

感谢您指出问题并提供链接。但是,建议的解决方案(使用图形场景)听起来太重了。您说:“确保Qt知道像素非常重要,这样前景小部件就可以将半透明度应用于其背景"。你是如何做到这一点的?没有图形场景有没有可能的解决方案?另外请注意,我想画小部件,而不仅仅是图形项目。@Leems与我们的绘画专家交谈,更新了我的答案,为你提供了更多信息,简言之,让GL输出在缓冲区中可用,并使用Qt的工具将其绘制到屏幕上。非常感谢。我仍然看到一个缺点:渲染的贴图将被复制到RAM中(到我的进程中)。我说的对吗?正如你所说的,Qt需要“知道”这些像素这是一个必要的步骤。因此没有比这更好的了吗?@leems从我的理解是的,渲染的贴图/输出将被复制到RAM中,并成为您的过程的一部分。不幸的是,我不知道有任何其他方法来实现图形输出(例如像素)在不使用Qt的绘画工具的情况下进入Qt上下文。也就是说,我们在几个程序上使用这种方法,许多程序都有实时要求,而且效果非常好。设置
Qt::SplashScreen
标志似乎对OP的问题没有任何影响。