Skip to main content
 首页 » 编程设计

python之PySide/PyQt 覆盖小部件

2025年05月04日12虾米姐

我正在尝试在 PySide 中实现这样的目标:https://codepen.io/imprakash/pen/GgNMXO 我想要做的是创建一个无框架的子窗口,下面有一个黑色覆盖层。

我没有成功创建一个无框架的子窗口和覆盖...

这是复制 HTML 的基本代码:

from PySide import QtCore, QtGui 
import sys 
 
class MainWindow(QtGui.QWidget): 
    def __init__(self): 
        QtGui.QWidget.__init__(self) 
        self.resize(800, 500) 
 
        self.button = QtGui.QPushButton("Click Me") 
 
        self.setLayout(QtGui.QVBoxLayout()) 
        self.layout().addWidget(self.button) 
 
        # Connections 
        self.button.clicked.connect(self.displayOverlay) 
 
 
    def displayOverlay(self): 
        popup = QtGui.QDialog(self) 
        popup.setWindowFlags(QtCore.Qt.FramelessWindowHint) 
        popup.setLayout(QtGui.QHBoxLayout()) 
        popup.layout().addWidget(QtGui.QLabel("HI")) 
        popup.show() 
        print "clicked" 
 
if __name__ == "__main__": 
    app = QtGui.QApplication(sys.argv) 
    window = MainWindow() 
    window.show() 
    sys.exit(app.exec_()) 

如果您用 FramelessWindowHint 注释该行,则窗口出现,否则什么也不会发生...

我真的希望有人能帮助我。感谢您花时间阅读我的问题。

请您参考如下方法:

我将使用 PyQt5对于这个解释。它可能与 PySide(我不确定它是否仍在维护)和 PyQt4 有一些不同,但它应该不会太难转换。

下面的例子有一个包含几个按钮的父部件。其中之一(最明显的)要求弹出窗口。我已经准备好示例来处理父调整大小,但没有编写任何关于拖动弹出窗口的鼠标事件的代码(请参阅 mouseMoveEvent 和 mouseReleaseEvent)。

代码如下:

import sys 
from PyQt5 import QtWidgets, QtCore, QtGui 
 
class TranslucentWidgetSignals(QtCore.QObject): 
    # SIGNALS 
    CLOSE = QtCore.pyqtSignal() 
 
class TranslucentWidget(QtWidgets.QWidget): 
    def __init__(self, parent=None): 
        super(TranslucentWidget, self).__init__(parent) 
 
        # make the window frameless 
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint) 
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground) 
 
        self.fillColor = QtGui.QColor(30, 30, 30, 120) 
        self.penColor = QtGui.QColor("#333333") 
 
        self.popup_fillColor = QtGui.QColor(240, 240, 240, 255) 
        self.popup_penColor = QtGui.QColor(200, 200, 200, 255) 
 
        self.close_btn = QtWidgets.QPushButton(self) 
        self.close_btn.setText("x") 
        font = QtGui.QFont() 
        font.setPixelSize(18) 
        font.setBold(True) 
        self.close_btn.setFont(font) 
        self.close_btn.setStyleSheet("background-color: rgb(0, 0, 0, 0)") 
        self.close_btn.setFixedSize(30, 30) 
        self.close_btn.clicked.connect(self._onclose) 
 
        self.SIGNALS = TranslucentWidgetSignals() 
 
    def resizeEvent(self, event): 
        s = self.size() 
        popup_width = 300 
        popup_height = 120 
        ow = int(s.width() / 2 - popup_width / 2) 
        oh = int(s.height() / 2 - popup_height / 2) 
        self.close_btn.move(ow + 265, oh + 5) 
 
    def paintEvent(self, event): 
        # This method is, in practice, drawing the contents of 
        # your window. 
 
        # get current window size 
        s = self.size() 
        qp = QtGui.QPainter() 
        qp.begin(self) 
        qp.setRenderHint(QtGui.QPainter.Antialiasing, True) 
        qp.setPen(self.penColor) 
        qp.setBrush(self.fillColor) 
        qp.drawRect(0, 0, s.width(), s.height()) 
 
        # drawpopup 
        qp.setPen(self.popup_penColor) 
        qp.setBrush(self.popup_fillColor) 
        popup_width = 300 
        popup_height = 120 
        ow = int(s.width()/2-popup_width/2) 
        oh = int(s.height()/2-popup_height/2) 
        qp.drawRoundedRect(ow, oh, popup_width, popup_height, 5, 5) 
 
        font = QtGui.QFont() 
        font.setPixelSize(18) 
        font.setBold(True) 
        qp.setFont(font) 
        qp.setPen(QtGui.QColor(70, 70, 70)) 
        tolw, tolh = 80, -5 
        qp.drawText(ow + int(popup_width/2) - tolw, oh + int(popup_height/2) - tolh, "Yep, I'm a pop up.") 
 
        qp.end() 
 
    def _onclose(self): 
        print("Close") 
        self.SIGNALS.CLOSE.emit() 
 
 
class ParentWidget(QtWidgets.QWidget): 
    def __init__(self, parent=None): 
        super(ParentWidget, self).__init__(parent) 
 
        self._popup = QtWidgets.QPushButton("Gimme Popup!!!") 
        self._popup.setFixedSize(150, 40) 
        self._popup.clicked.connect(self._onpopup) 
 
        self._other1 = QtWidgets.QPushButton("A button") 
        self._other2 = QtWidgets.QPushButton("A button") 
        self._other3 = QtWidgets.QPushButton("A button") 
        self._other4 = QtWidgets.QPushButton("A button") 
 
        hbox = QtWidgets.QHBoxLayout() 
        hbox.addWidget(self._popup) 
        hbox.addWidget(self._other1) 
        hbox.addWidget(self._other2) 
        hbox.addWidget(self._other3) 
        hbox.addWidget(self._other4) 
        self.setLayout(hbox) 
 
        self._popframe = None 
        self._popflag = False 
 
    def resizeEvent(self, event): 
        if self._popflag: 
            self._popframe.move(0, 0) 
            self._popframe.resize(self.width(), self.height()) 
 
    def _onpopup(self): 
        self._popframe = TranslucentWidget(self) 
        self._popframe.move(0, 0) 
        self._popframe.resize(self.width(), self.height()) 
        self._popframe.SIGNALS.CLOSE.connect(self._closepopup) 
        self._popflag = True 
        self._popframe.show() 
 
    def _closepopup(self): 
        self._popframe.close() 
        self._popflag = False 
 
 
if __name__ == '__main__': 
    import sys 
    app = QtWidgets.QApplication(sys.argv) 
    main = ParentWidget() 
    main.resize(500, 500) 
    main.show() 
    sys.exit(app.exec_()) 

结果如下:

逻辑如下。您创建一个空的 Widget 并手动绘制背景和弹出窗口 (paintEvent)。您添加一个用于关闭弹出窗口的按钮。为此,您构建一个 Signal 并让父窗口小部件执行关闭操作。这很重要,因为您需要让父控件控制弹出窗口的一些重要元素(例如关闭、调整大小等)。您可以添加更多的复杂性,但希望该示例足以满足初学者的需求。