如何在对象中包装 QFileDialog 和 QPushButton

How to wrap a QFileDialog and QPushButton in an object

这是我的代码:

from PyQt5.QtCore import (
    QDir
)
from PyQt5.QtWidgets import(
    QApplication,QDialog,
    QVBoxLayout,QGridLayout,QPushButton,QFileDialog
)

class DicAsk(object):
    def __init__(self):
        super(DicAsk, self).__init__()
        self.button = QPushButton("ButtonB")
        self.button.clicked.connect(self.browse)
        # self.button.clicked.connect(lambda:QFileDialog.getExistingDirectory(None, "Find Files",
        #     QDir.currentPath()))
    def browse(self):
        directory = QFileDialog.getExistingDirectory(None, "Find Files",
            QDir.currentPath())

class Window(QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        buttonA = QPushButton("ButtonA")
        buttonA.clicked.connect(self.browse)

        dicAsk = DicAsk()

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(buttonA)
        mainLayout.addWidget(dicAsk.button)
        self.setLayout(mainLayout)

    def browse(self):
        directory = QFileDialog.getExistingDirectory(None, "Find Files",
            QDir.currentPath())

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

window中有两个按钮:"buttonA"和"button B"。 按钮A正常,可以成功打开QFileDialog.

按钮 B 在 class 中定义,应该像按钮 A 一样工作,但它不会打开 QFileDialog。如果将 browse 方法更改为 lambda 函数,它会起作用。为什么 browse 方法不起作用?

问题是 DicAsk 没有定义为 PyQt 对象。它只是定义为一个基本的python class,所以它的方法不能是插槽。 DicAsk.browse 在您单击按钮 B 时永远不会被调用。

真正的问题是您没有保留对 dicAsk 的引用。它在Window.__init__中本地定义,然后被销毁。您仍然可以使用 dicAsk.buttton,因为它已添加到布局中(window 成为 dicAsk.button 的父级,因此保留对按钮的引用)

要解决此问题,您可以使用 self.dicAsk=DicAsk() 保留参考,或修改 class 以拥有父级:

class DicAsk(QtCore.Qobject):
    def __init__(self,parent):
        super(DicAsk, self).__init__(parent)

#in Window
dicAsk=DicAsk(self)

另一种解决问题的方法是 subclass QPushButton:

class MyButton(QPushButton):
    def __init__(self,parent=None):
        super(MyButton, self).__init__(parent)
        self.setText("ButtonB")
        self.clicked.connect(self.browse)

    def browse(self):
        print("browse")

这更有意义,因为您想要的是自定义按钮。