通过QGLWidget进行半透明的QWidget:奇怪的结果 [英] Semi-transparent QWidget over QGLWidget: Strange results

查看:554
本文介绍了通过QGLWidget进行半透明的QWidget:奇怪的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个完整的QGLWidget,它使用QPainter绘制了应用程序的背景(将来可能会更改为本机的openGL命令).

在此QGLWidget之上,我使用QWidgets(非GL)作为用户界面元素.例如,这些是QLineEdits和QPushButtons.我将它们放入使用半透明背景绘画的自定义绘画QWidget中. QLineEdit和QPushButton的paintEvents被覆盖并使用半透明背景.

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

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

因此,现在,在启用OpenGL(背景为QGLWidget)的情况下,上方的半透明窗口小部件不会在背景之上绘制,而会在(似乎是)未初始化的数据之上绘制.通过顶部栏发光的图像有时是整个窗口本身,有时是桌面上当前存在的其他窗口.

当前看起来类似于以下内容(在此屏幕截图中,在其上进行半透明绘制操作的数据似乎是窗口小部件本身的图像,具有偏移量.):

当我将文本写到行编辑中时(这里:这是一些以前存在过的文本!"),将其删除并将焦点设置回背景小部件(这样会出现放大镜图标和占位符文本) ,以前涂过的东西仍然会发光(请注意,可见的边框应该不再可见,但仍然会发光):

所以问题是:半透明的小部件不是被涂在基础小部件的顶部,而是被涂在旧结果的顶部,最初是未初始化的内存"之类的东西. /p>

为什么会这样?我该如何解决这个问题?

在回答之前您应该了解的事项:

  • 背景场景是在屏幕外渲染的图块的组成.因此可以非常快速地进行绘制,并且对于覆盖层的每个微小更改都可以重新绘制背景.
  • 顶部的栏是一个自定义QWidget,具有手动绘制和排列包含的两个小部件(按钮和行编辑)的功能.
  • 这两个小部件将覆盖paintEvent,仅在它们具有焦点且不使用Qt已提供的框架时才绘制自己的(半透明)背景.因此,第二个屏幕截图中的白色边框是在我的自定义paintEvent中绘制的.
  • 我希望覆盖小部件的背景和组成可以单独实现.背景是AbstractMapView,其中包含一些具体的地图视图类.整个窗口是一个AbstractView(也有多个具体视​​图),其中包含一个具体的地图视图和覆盖小部件,它们以自己决定的方式组成.因此,我不希望覆盖小部件的逻辑成为基础地图视图的一部分. (我希望您理解这一点,因为它有点复杂.)

解决方案

这听起来像一个问题,其中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上下文中.

I have a full size QGLWidget which paints the application background using QPainter (might change to native openGL commands in the future).

On top of this QGLWidget I use QWidgets (non-GL) for the user interface elements. These are, for example, QLineEdits and QPushButtons. I put them into a custom painted QWidget which uses semi-transparent background painting. The paintEvents of the QLineEdit and QPushButton are overwritten and use semi-transparent backgrounds, too.

The whole UI should look like the following (This is a screenshot where I disabled OpenGL and used QWidget instead of QGLWidget for the background. Note the semi-transparent top bar which also draws a shadow (within its own region)):

When the QLineEdit has the focus, it should have a higher opacity but still not fully opaque:

So now, with OpenGL enabled (The background then is a QGLWidget), the semi-transparent widgets above don't paint on top of the background but on (it seems to be) uninitialized data. The image shining through the top bar is sometimes the whole window itself and sometimes other windows currently being on my desktop.

This currently looks like the following (In this screenshot, the data on which the semi-transparent painting operations are painted on seems to be an image of the widget itself, having an offset.):

When I wrote text into the line edit (here: "This is some text which has been there before!"), removed it and set the focus back to the background widget (so the magnifier icon and the placeholder text appear), the previously painted things still shine through (Note that the visible border should not be visible anymore, but also still shines through):

So the problem is: Instead of being painted on top of the underlying widgets, the semi-transparent widget is painted on top of the old results, initially being something like "uninitialized memory".

Why does this happen? How can I solve the problem?

Things you should know before answering:

  • The background scene is a composition of tiles which are rendered off-screen. So it can be painted very fast and repainting of the background for every little change of the overlay isn't problematic.
  • The top bar is a custom QWidget with manual painting and arrangement of the contained two widgets (the button and line edit).
  • The two widgets overwrite the paintEvent, only draw their own (semi-transparent) background when they have focus and don't use frames already provided by Qt. So the white border in the second screenshot is drawn in my custom paintEvent.
  • I want the background and the composition of overlay widgets to be separately implementable. The background is an AbstractMapView which has some concrete map view classes. The whole window is an AbstractView (there are multiple concrete views, too), which contains both a concrete map view and the overlay widgets, composed in a way itself decides. Therefore, I don't want the logic of the overlay widgets to be part of the underlying map view. (I hope you understood this, as it is a bit complicated.)

解决方案

This sounds like an issue where the GL content (i.e. your background aka the QGLWidget) is not in the Qt context. While I'm not a pro on GL painting with Qt, you may want to look at this discussion regarding GL painting and a QLabel for some direction/potential hints.

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

In short, we here at the office use OpenGL painting and offscreen rendering of maps and it's very important to make sure Qt is aware of the pixels so your foreground widgets can have the semi-transparency applied to their backgrounds.

The particular product we use also renders the map in tiles and supports providing the GL output in a buffer (i.e. it's call a snapshot and is provided as a bitmap) at which point we use the paintEvent of a regular QWidget to paint the buffer so that the painted pixels are in Qt context.

这篇关于通过QGLWidget进行半透明的QWidget:奇怪的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆