Прозрачность дочернего виджета в Qt5

Я использую Nvidia Jetson Nano с Linux для Tegra (Ubuntu 18, оконная система X11), Python 3.6 и PyQt5. Я хочу разместить прозрачный виджет (или с прозрачным фоном) поверх основного виджета.

Когда эти виджеты создаются как независимые, все отображается корректно. Прозрачность работает, даже если видеопоток gstreamer отображается в основном виджете.

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class MainWindow(QWidget):   
    def __init__(self):
        QWidget.__init__(self)
        self.setGeometry(50,50,320,240)
        self.setWindowTitle("Main Window")
        self.setStyleSheet("background-color:yellow;")
        self.label = QLabel(self)
        self.label.setText("Main Widget")
        self.menu = MenuWidget()
    
class MenuWidget(QWidget):
    def __init__(self): 
        QWidget.__init__(self)
        self.setWindowFlags(Qt.Tool)
        self.setGeometry(100,100,100,50)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setStyleSheet("background-color:gray;")
        self.setWindowOpacity(0.5)
        self.label = QLabel(self)
        self.label.setText("Menu Widget")

app = QApplication([])
window = MainWindow()
window.show()
window.menu.show()
sys.exit(app.exec_())

[введите здесь описание изображениявведите здесь описание изображения

Когда я пытаюсь создать виджет в качестве дочернего элемента основного виджета, прозрачность не работает. Если отображается видео, в главном окне виджета появляется дыра.

class MainWindow(QWidget):   
    def __init__(self):
        QWidget.__init__(self)
        self.setGeometry(50,50,320,240)
        self.setWindowTitle("Main Window")
        self.setStyleSheet("background-color:yellow;")
        self.label = QLabel(self)
        self.label.setText("Main Widget")
        self.menu = MenuWidget(parent=self)
        print('main window created')
    
class MenuWidget(QWidget):
    def __init__(self, parent): 
        QWidget.__init__(self, parent)
        self.setWindowFlags(Qt.Tool)
        self.setGeometry(100,100,100,50)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setStyleSheet("background-color:gray;")
        self.setWindowOpacity(0.5)
        self.label = QLabel(self)
        self.label.setText("Menu Widget")

app = QApplication([])
window = MainWindow()
window.show()
sys.exit(app.exec_())

введите здесь описание изображения введите здесь описание изображения

Также, если я устанавливаю атрибут self.setAttribute(Qt.WA_TranslucentBackground) для дочернего виджета, в главном окне появляется дыра (если в этом окне воспроизводится видео).

введите здесь описание изображения

Как установить прозрачность для дочернего виджета? Заранее спасибо за ваши ответы!


person lich.mk    schedule 04.11.2020    source источник


Ответы (2)


Как следует из названия, windowOpacity относится к непрозрачности окна.

Если вы хотите установить прозрачность дочернего виджета, вам нужно использовать QGraphicsOpacityEffect:

class MenuWidget(QWidget):
    def __init__(self, parent): 
        QWidget.__init__(self, parent)
        # ...
        self.setGraphicsEffect(QGraphicsOpacityEffect(opacity=.5))
person musicamante    schedule 04.11.2020
comment
Спасибо за совет! Этот метод работает с обычным окном, но не работает с видео. Виджет затемнен, но не прозрачен. - person lich.mk; 05.11.2020
comment
Ммм, наложение видео усложняет задачу. Вы можете попытаться установить цвет фона с помощью альфы в таблице стилей (self.setStyleSheet("background-color: rgba(128, 128, 128, 128);"), но, даже если предположить, что это правильно работает с видео, это сделает фон только полупрозрачным. - person musicamante; 06.11.2020

Насколько я понял, прозрачность (прозрачность фона) виджета можно создать только с помощью десктопного компоновщика. Qt не может использовать компоновщик рабочего стола для рендеринга дочерних виджетов. Единственное решение — использовать независимые окна/виджеты. Единственное решение — использовать независимые окна/виджеты.

person lich.mk    schedule 10.11.2020