Issue
How does one properly capture the close event coming out of a PySide QtUiTools.QUiLoader() setup?
I can get the instanced class to connect to widgets and everything else, but I am not sure how to intercept the signals in this setup.
Ideally, I want all close calls to pass through my closeEvent (obviously) so that I can ensure that it's safe to close the window. But since my self.closeEvent() is tied to my View(QtWidgets.QMainWindow) and not the self._qt.closeEvent(), I don't know how to get to the self._qt.closeEvent() method to override it in this case.
Or is there a better way to set this up to capture those window events?
# Compatible enough with Pyside 2
from PySide import QtGui as QtWidgets
from PySide import QtUiTools
from PySide import QtCore
class View(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(View, self).__init__(parent=parent)
self.setup()
def closeEvent(self, event):
# Do things
event.accept()
def setup(self):
loader = QtUiTools.QUiLoader()
fy = QtCore.QFile('example.ui')
fy.open(QtCore.QFile.ReadOnly)
self._qt = loader.load(fy, self)
fy.close()
self._qt.pCanceled.clicked(self._qt.close)
Doesn't apply:
PySide / PyQt detect if user trying to close window
Close, but PySide doesn't use PyQt's uic and appears to run differently (and didn't work):
PyQt: clicking X doesn't trigger closeEvent
Solution
closeEvent
is not a signal, it is a method that is called when the QCloseEvent
event is sent. A signal and an event are different things. Going to the problem, in Qt there are 2 ways to listen to events, the first one is overwriting the fooEvent()
methods and the second one using an event filter as I show below:
from PySide import QtGui as QtWidgets
from PySide import QtUiTools
from PySide import QtCore
class View(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(View, self).__init__(parent=parent)
self._qt = None
self.setup()
def closeEvent(self, event):
self.do_things()
super(View, self).closeEvent(event)
def do_things(self):
print("do_things")
def setup(self):
loader = QtUiTools.QUiLoader()
fy = QtCore.QFile('example.ui')
fy.open(QtCore.QFile.ReadOnly)
self._qt = loader.load(fy, self)
fy.close()
self._qt.pCanceled.clicked.connect(self._qt.close)
self._qt.installEventFilter(self)
def eventFilter(self, watched, event):
if watched is self._qt and event.type() == QtCore.QEvent.Close:
self.do_things()
return super(View, self).eventFilter(watched, event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = View()
w.show()
sys.exit(app.exec_())
Update:
Normally in the eventFilter
it is enough to return True for the event to be ignored but in the case of QCloseEvent
you must ignore the event and return True as shown below:
def eventFilter(self, watched, event):
if watched is self._qt and event.type() == QtCore.QEvent.Close:
self.do_things()
event.ignore()
return True
return super(View, self).eventFilter(watched, event)
Answered By - eyllanesc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.