PyQt5:创建具有不透明子对象的半透明窗口



我想创建一个具有半透明背景但完全可见的子窗口(某种覆盖效果)的全屏窗口。

到目前为止,我拥有的是:

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
app = QApplication(sys.argv)
# Create the main window
window = QMainWindow()
window.setWindowOpacity(0.3)
window.setAttribute(Qt.WA_NoSystemBackground, True)
window.setWindowFlags(Qt.FramelessWindowHint)
# Create the button
pushButton = QPushButton(window)
pushButton.setGeometry(QRect(240, 190, 90, 31))
pushButton.setText("Finished")
pushButton.clicked.connect(app.quit)
# Center the button
qr = pushButton.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
pushButton.move(qr.topLeft())
# Run the application
window.showFullScreen()
sys.exit(app.exec_())

这将创建半透明效果,但即使是按钮也是半透明的。

我还试着用替代

window.setWindowOpacity(0.3)

通过这个调用

window.setAttribute(Qt.WA_TranslucentBackground, True)

但没有效果,在这种情况下,背景是完全透明的(而按钮正确地完全可见)。

解决方案:(根据Aaron的建议实施)

诀窍在于实现主窗口的自定义paintEvent。

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class CustomWindow(QMainWindow):
    def paintEvent(self, event=None):
        painter = QPainter(self)
        painter.setOpacity(0.7)
        painter.setBrush(Qt.white)
        painter.setPen(QPen(Qt.white))   
        painter.drawRect(self.rect())

app = QApplication(sys.argv)
# Create the main window
window = CustomWindow()
window.setWindowFlags(Qt.FramelessWindowHint)
window.setAttribute(Qt.WA_NoSystemBackground, True)
window.setAttribute(Qt.WA_TranslucentBackground, True)
# Create the button
pushButton = QPushButton(window)
pushButton.setGeometry(QRect(240, 190, 90, 31))
pushButton.setText("Finished")
pushButton.clicked.connect(app.quit)
# Center the button
qr = pushButton.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
pushButton.move(qr.topLeft())
# Run the application
window.showFullScreen()
sys.exit(app.exec_())

好的,虽然它似乎不适用于可用的标志,但您仍然可以使用Qt.WA_TranslucentBackground,因为可以在该透明度上绘制半透明矩形。

从QMainWindow派生主窗口,然后使用该类。

self.setAttribute(Qt.WA_TranslucentBackground, True)应用于该类

像这样实现主窗口类的paintEvent(类似,可能包含错误,但原理应该有效):

QPixmap canvas(rect())
canvas.fill(Qt.transparent) # fill transparent (makes alpha channel available)
QPainter p(canvas)           # draw on the canvas
p.setOpacity(0.3)
p.setBrush(QBrush(Qt.white)) # use the color you like
p.setPen(QPen(Qt.transparen))
p.drawRect(rect()) # draws the canvas with desired opacity
p.start(self)      # now draw on the window itself
p.drawPixmap(rect(), canvas)

我只是想提供另一个解决方案,以防其他人遇到这个问题。我解决问题的方法是这样的。

首先将背景设置为完全透明。这只适用于窗口的背景,而不适用于子对象。

self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)

如果需要,可以删除边框。

self.setWindowFlags(QtCore.Qt.FramelessWindowHint)

现在,如果你希望仍然有一些背景色,请将QFrame应用于你的窗口,并将所有子对象放置在其中。使用你的样式表,设置框架的颜色和你想要的不透明度,如下所示。最后一个值是不透明度百分比。

self.main_frame.setStyleSheet("background-color: rgba(0, 120, 185, 60)")

最新更新