Полупрозрачный QWidget над QGLWidget: странные результаты

у меня есть полноразмерный QGLWidget, который рисует фон приложения с помощью QPainter (может измениться на собственные команды openGL в будущем).

поверх этого QGLWidget я использую QWidgets (non-GL) для элементов пользовательского интерфейса. Это, например, QLineEdits и QPushButtons. Я поместил их в пользовательский окрашенный QWidget, который использует полупрозрачную фоновую живопись. PaintEvents QLineEdit и QPushButton перезаписываются и используют полупрозрачные фоны, тоже.

весь интерфейс должен выглядеть следующим образом (это скриншот, где я отключил OpenGL и использовал QWidget вместо qglwidget для фона. Обратите внимание на полупрозрачную верхнюю панель, которая также рисует тень (в пределах своего региона)):

Screenshot

когда QLineEdit имеет фокус, он должен иметь более высокую непрозрачность, но все еще не полностью непрозрачен:

Screenshot

Итак, теперь с включенным OpenGL (фон затем это QGLWidget), полупрозрачные виджеты выше не рисуют поверх фона, но (похоже) неинициализированные данные. Изображение, сияющее через верхнюю панель, иногда является самим окном, а иногда и другими окнами, находящимися на моем рабочем столе.

в настоящее время это выглядит следующим образом (на этом скриншоте данные, на которых нарисованы полупрозрачные операции рисования, кажутся изображением самого виджета, имеющего сдвиг.):

Screenshot

когда я написал текст в строку edit (здесь: "это какой-то текст, который был там раньше!"), удалил его и установил фокус обратно в фоновый виджет (так появляется значок лупы и текст заполнителя), ранее окрашенные вещи все еще просвечивают (обратите внимание, что видимая граница должна не быть видимым больше, но также все еще светит через):

Screenshot

Итак, проблема: вместо будучи окрашенным поверх базовых виджетов, полупрозрачный виджет окрашивается поверх старые результаты, изначально будучи чем-то вроде "неинициализированной памяти".

почему это происходит? Как я могу решить эту проблему?

вещей, которые вы должны знать прежде, чем ответить:

  • фоновая сцена представляет собой композицию плиток, которые отображаются за пределами экрана. Так его можно покрасить очень быстро и перекрасить фон для каждого небольшого изменения наложения не является проблематичным.
  • верхняя панель-это пользовательский QWidget с ручной росписью и расположением двух виджетов (кнопка и строка редактирования).
  • два виджета перезаписывают paintEvent, рисуют только свой собственный (полупрозрачный) фон, когда они имеют фокус и не используют кадры, уже предоставленные Qt. Таким образом, белая граница на втором скриншоте нарисована в моем пользовательском paintEvent.
  • я хочу фон и состав виджетов наложения должны быть отдельно реализуемыми. Фон является AbstractMapView который имеет некоторые конкретные классы представления карты. Все окно-это AbstractView (есть несколько конкретных видов, тоже), который содержит как конкретный вид карты и виджеты наложения, составленные таким образом, сам решает. Поэтому я не хочу, чтобы логика виджетов наложения была частью базового представления карты. (Надеюсь, вы это поняли, так как это немного сложный.)

2 ответов


Это звучит как проблема, когда содержимое GL (т. е. ваш фон, он же QGLWidget) не находится в контексте Qt. Хотя я не профессионал в GL-живописи с Qt, вы можете посмотреть на это обсуждение относительно GL-живописи и QLabel для некоторых намеков на направление/потенциал.

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

короче говоря, мы здесь, в офисе, используем OpenGL живопись и закадровый рендеринг карт и очень важно убедиться, что Qt знает о пикселях, чтобы ваши виджеты переднего плана могли иметь полупрозрачность, применяемую к их фонам.

конкретный продукт, который мы используем, также отображает карту в плитках и поддерживает предоставление вывода GL в буфере (т. е. он вызывает снимок и предоставляется как растровое изображение), в этот момент мы используем paintEvent обычного QWidget для рисования буфера так, чтобы окрашенные пиксели находились в контексте Qt.


вы можете определить Qframe с флагом Qt:: SplashScreen как поле поиска и установить его непрозрачность. Поместите свои виджеты внутри него, такие как текстовое поле поиска и поместите его там, где он должен появиться на главном окне. Также будет хорошей идеей переместить его, поскольку основное окно перемещается или изменяется, переопределяя его moveEvent.