1

I am fairly new to PyQt and I found a piece of code that I used to help close a progressbar window when main program closes.

I understand most of what is going on, but I do not get why the installEventFilter/removeEventFilter methods are even called, because I looked them up using python and the functions show that they don't do anything because of pass

    def installEventFilter(self, QObject): # real signature unknown; restored from __doc__
        """ installEventFilter(self, QObject) """
        pass

    def removeEventFilter(self, QObject): # real signature unknown; restored from __doc__
        """ removeEventFilter(self, QObject) """
        pass

I tested it out by removing those lines of code, and it works just as expected. My question is how exactly does event filters work in this case?


from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from PyQt5.QtWidgets import QApplication,QProgressBar,QMainWindow,QDialog,QLabel

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(477, 240)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
        MainWindow.setSizePolicy(sizePolicy)
        MainWindow.setMinimumSize(QtCore.QSize(477, 240))
        MainWindow.setMaximumSize(QtCore.QSize(477, 240))
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(160, 100, 141, 23))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
        self.pushButton.setSizePolicy(sizePolicy)
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 477, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "Show Progress Bar"))

class MCVE(QMainWindow,Ui_MainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.pushButton.clicked.connect(self.showProgressBar)

    def showProgressBar(self):
        self.prog_win = QDialog(self)
        self.prog_win.resize(400, 100)
        self.prog_win.setFixedSize(self.prog_win.size())
        self.prog_win.setWindowTitle("Loading")
        EventWatcher(self.prog_win)
        self.lbl = QLabel(self.prog_win)
        self.lbl.setText("Please Wait...")
        self.lbl.move(15, 18)
        self.progressBar = QProgressBar(self.prog_win)
        self.progressBar.resize(410, 25)
        self.progressBar.move(15, 40)
        self.progressBar.setRange(0, 1)
        self.prog_win.show()
        self.progressBar.setRange(0, 0)


class EventWatcher(QtCore.QObject):
    def __init__(self, parent):
        super().__init__(parent)
        parent.installEventFilter(self)

    def eventFilter(self, source, event):
        if source is self.parent():
            if event.type() == QtCore.QEvent.Show:
                target = source.parent()
                while target.parent() is not None:
                    target = target.parent()
                source.removeEventFilter(self)
                target.installEventFilter(self)
        elif event.type() == QtCore.QEvent.Close:
            source.closeEvent(event)
            if event.isAccepted():
                self.parent().close()
            return True
        return QtCore.QObject.eventFilter(self, source, event)

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

Drees
  • 688
  • 1
  • 6
  • 21
  • I do not understand, you want me to explain what?: 1) Do you want me to explain the code that uses `pass`? or 2) Do you want me to explain what is the purpose of eventFilter? or 3) Do you want me to explain why the last code works if you comment some lines? – eyllanesc May 16 '19 at 20:13
  • @eyllanesc I'd like to know the purpose of installEventFilter,removeEventFilter in the provided class, since it works without it. – Drees May 16 '19 at 20:18
  • Okay, but to do an analysis I need you to provide a [mcve], with the code that shows is impossible to answer – eyllanesc May 16 '19 at 20:20
  • @eyllanesc I updated code with example – Drees May 16 '19 at 20:32
  • Where did you get that code? – eyllanesc May 16 '19 at 20:35
  • @eyllanesc https://stackoverflow.com/questions/45787575/floating-qdockwidget-does-not-close-when-parentwidget-closes?rq=1 – Drees May 16 '19 at 20:36
  • 1
    The problem is that this method is useful for the other question because in that scenario the expected behavior is not, that is, the floating QDockWidget does not close even when the parent closes. But in your case you do not have that problem so it is not necessary to use that code since the normal thing is that if the parent closes the son will also do the same. – eyllanesc May 16 '19 at 20:39
  • 1
    Conclusion: in the other question the QDockWidget does not behave as expected, so a workaround is necessary but in your current case it is not necessary since it works as expected. – eyllanesc May 16 '19 at 20:40
  • @eyllanesc In the other case, how does removeEventFilter/installEventFilter work since the methods have pass in them? – Drees May 16 '19 at 20:41
  • Let's say you want to listen some event, such as when you click on a QLineEdit, then there are 2 solutions: 1) I create a class that inherits from QLineEdit and I override the mousePressEvent method, this method needs the inheritance necessarily but in many cases the developer he does not want to do that since it involves modifying a lot of code. 2) install an eventFilter so that the QLineEdit events are heard by the window, so you can find out when the QLineEdit is pressed without needing the inheritance of the previous solution – eyllanesc May 16 '19 at 20:45
  • @Drees I assume you override those methods on the class `MCVE`. If so, then the overriden `installEventFilter` will only get called by the line `target.installEventFilter(self)` inside `eventFilter`. All the other calls of `removeEventFilter/installEventFilter` are on `prog_win` (which doesn't have any overrides). – ekhumoro May 17 '19 at 00:05

0 Answers0