user1021531
user1021531

Reputation: 477

How to wrap a QFileDialog and QPushButton in an object

Here is my code:

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

There are two buttons in the window: "buttonA" and "button B". Button A works fine, it can successfully open a QFileDialog.

Button B is defined in a class and should work like button A, but it doesn't open a QFileDialog. It works if the browse method is changed into a lambda function. Why doesn't the browse method work?

Upvotes: 0

Views: 356

Answers (1)

Mel
Mel

Reputation: 6075

The problem is that DicAsk is not define as a PyQt object. It's only define as a basic python class, so its methods can't be slots. DicAsk.browse is never called when you click button B.

The real problem is that you don't keep a reference to dicAsk. It is defined locally in Window.__init__, and then destroyed. You can still use dicAsk.buttton because it was added to the layout (window becomes the parent of dicAsk.button, and so keeps a reference to the button)

To fix the issue you can keep a reference with self.dicAsk=DicAsk(), or modify the class to have a parent:

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

#in Window
dicAsk=DicAsk(self)

Another way to solve your issue is to 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")

It makes more sense since what you want is a customized button.

Upvotes: 2

Related Questions