【问题标题】:PyQt5: Create semi-transparent window with non-transparent childrenPyQt5:创建具有非透明子项的半透明窗口
【发布时间】:2016-03-03 02:51:00
【问题描述】:

我想创建一个具有半透明背景但完全可见的子小部件(一种叠加效果)的全屏窗口。

这是我目前所拥有的:

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_())

【问题讨论】:

    标签: python qt pyqt qt5 pyqt5


    【解决方案1】:

    好的,虽然它似乎不适用于可用的标志,但您仍然可以使用 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)
    

    【讨论】:

    • 按钮仍然是半透明的,背景被设置为系统定义的颜色(而不是黑色,现在是白色的)。我不确定 setWindowOpacity 是否适用于非窗口小部件。
    • 编辑了我的答案。我有时会这样做,它总是按您的需要工作。
    • 好的,我试着把这个 QT 伪代码转换成 PyQT,看看效果如何。
    • 好的,我来自 C++ .. 我的 rect() 对你来说是 self.rect(),如果它适合你,请接受答案。抱歉,我已经有一段时间没有使用 PyQt 了..
    • 实际上,在您上面的“解决方案”部分中,您永远不会在画布上绘画。如果您与我的伪代码进行比较,画家首先在画布上绘画,然后将画布转移到自己。但对你来说,画自我似乎就足够了('painter = QPainter(self)')。所以看起来你可以删除你的绘画事件的第一行和最后一行。 (对我来说,从未直接在 self/(c++ 中的 this)上工作过。但如果它对你有用,那就太好了)。
    【解决方案2】:

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

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

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

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

    self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
    

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

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

    【讨论】:

      猜你喜欢
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-18
      • 2018-08-12
      • 2011-10-12
      • 2010-10-21
      相关资源
      最近更新 更多