【问题标题】:Semi-transparent QWidget over QGLWidget: Strange resultsQGLWidget 上的半透明 QWidget:奇怪的结果
【发布时间】:2012-07-21 04:32:04
【问题描述】:

我有一个全尺寸的 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(也有多个具体视​​图),它包含一个具体的地图视图和覆盖小部件,它们以自己决定的方式组成。因此,我不希望覆盖小部件的逻辑成为底层地图视图的一部分。 (我希望你明白这一点,因为它有点复杂。)

【问题讨论】:

    标签: qt opengl overlay transparency


    【解决方案1】:

    这听起来像是 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 了解像素非常重要,这样您的前景小部件可以将半透明应用于其背景”。你是怎么做到的?没有图形场景是否有可能的解决方案?另请注意,我想绘制小部件,而不仅仅是图形项。
    • 非常感谢。我仍然看到一个缺点:渲染的地图将被复制到 RAM 中(到我的进程中)。我对么?正如您所说,由于 Qt 需要“了解”这些像素,这是一个必要的步骤。所以没有比这更好的了吗?
    • @leemes 据我了解,是的,渲染的地图/输出将被复制到 RAM 中并成为您流程的一部分。不幸的是,我不知道在不使用 Qt 的绘画工具的情况下将图形输出(例如像素)带入 Qt 上下文的任何其他方法。也就是说,我们在这里在几个具有实时要求的程序上使用了这种方法,并且效果很好。
    【解决方案2】:

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

    【讨论】:

    • 设置 Qt::SplashScreen 标志似乎对 OP 的问题没有任何影响。
    猜你喜欢
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2017-06-18
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    相关资源
    最近更新 更多