closeEvent not working
-
@SGaist , my code was a workaround to another problem.
If you do what you suggested (it was my first choice), the windows will be empty, no widgets will appear.
It works if you define the widgets one by one inside the code, but if you are loading them with QtUiTools is not working.
A mistery for me.Thats why i changed the code. I can put the call to show() in the main but calling "ui": form.ui.show().
THis is working but closeEvent is not reachable.I'm attaching two pictures where you can see both codes and results.
One is showing the widgets but closeEvent is not working, the other is not showing the widgets but closeEvent is working.Thank for your help
-
Because your not using QUiloader correctly. See the documentation of the class. The example code shows that once the ui file has been loaded, the resulting widget is put in a layout that is applied to the "container widget".
-
@SGaist
mmmhhhh.... welll... interesting... it means that the real problem of my code is in another place.
I was able to write a running code but I would like to clarify better...class Form(QtWidgets.QMainWindow): def __init__(self, ui_file, parent=None): super(Form, self).__init__(parent) self.ui=QtUiTools.QUiLoader().load(ui_file) layout = QtWidgets.QVBoxLayout() layout.addWidget(self.ui) self.setLayout(layout)
This code "seems" equal to the one of the documentation (translating from C++ to python) and is not working.
It's not working because in the class declaration I'm inheriting from QMainWindow as I was doing in PyQt5.
If I change the code from QMainWindow to QWidget it's working but I'm loosing all the setting I did in Designer releted to the main window.Maybe there is something that I don't understand yet!
Thank you
-
You should have an error printed.
QMainWindow already has a layout that does all the neat things like handling of toolbars and dock widgets. Therefore you would need to set your loaded widget as central widget.
By the way, why use QUiLoader rather than
pyuic
? -
@SGaist
I investigate further...
first of all sorry for the misunderstanding on pyuic. Yes it present in PySide2 but I would prefer to load directly the ui from file.Now my code is the following:
class Form(QtWidgets.QMainWindow): def __init__(self, ui_file, parent=None): super(Form, self).__init__(parent) self.ui=QtUiTools.QUiLoader().load(ui_file) self.setCentralWidget(self.ui)
...and surprising it seems to work. as far as I was able to test. It seems that only window size is lost with this workaround.
I'm speaking of workaround because I'm just substituting the central widget... so menubar, statusbar,... they should not work if my understanding of the following picture is correct:
but instead they are present!
So maybe my problem is not completely solve but I think we are not far from a solution -
But why are you using a QMainWindow as "holder" widget ?
From a quick look, there should be something like a
pyside2-uic
command somewhere. -
Because I don't know what to do.
In PyQt5 I was doing something like that:Ui_MainWindow = uic.loadUiType("mainwindow.ui")[0]
and then
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self)
But this is not working with PySide2.
If you can share a PySyde2 working code it would be really appreciated.
Thank you -
@ZioLupo
Well, I get any PyQt support I need via pyqt@riverbankcomputing.com mailing list.Again OOI, for my reference, how much work are you finding you need to do to convert PyQt(5) to PySide? (Sorry if I'm hijacking thread, I won't ask another question...!)
-
It was done in a snapshot.
Honestly speaking I ported a couple of very small app in a snapshot. Search & Replace is your friend.
The only problem I had was with UI files.
But the Pyside2 loader is returning an istance, not a class... so I believeI have to think differently.
Moreover it's not my job, I'm an old C programmer shocked by the beauty of python... so maybe I don't have to loose time and keep everythink in PyQt5 ;-) -
@ZioLupo said in closeEvent not working:
As far as I know pyuic is not included in PySide2.
its pyside2uic!
I dofrom pyside2uic import compileUi
, compile my ui-files whenever changed. and do:self.ui = compiled_ui.Ui_Form() self.ui.setupUi(self.some_main_widget)
-
I was porting my code of a working program from PyQt5 to PySide2 and found the same issue:
def closeEvent(self, event): """Write window size and position to config file""" ini_options.setValue("menu_size", self.ui.size()) ini_options.setValue("menu_position", self.ui.pos()) event.accept() def eventFilter(self, target, event): print(event.type())
I am using two Tabs and this was the result of me playing with the tabs. These are the only events printed:
PySide2.QtCore.QEvent.Type.PolishRequest PySide2.QtCore.QEvent.Type.Move PySide2.QtCore.QEvent.Type.Resize PySide2.QtCore.QEvent.Type.Show PySide2.QtCore.QEvent.Type.ShowToParent PySide2.QtCore.QEvent.Type.UpdateLater PySide2.QtCore.QEvent.Type.Paint PySide2.QtCore.QEvent.Type.WindowDeactivate PySide2.QtCore.QEvent.Type.Hide
closeEvent is never printed when I close the window. Shouldn't be somewhere after WindowDeactivate and before Hide?
If I just open the software and close it without playing with the tabs, them the events are:
PySide2.QtCore.QEvent.Type.PolishRequest PySide2.QtCore.QEvent.Type.Destroy
I don't get why Destroy doesn't appears if I just switch to one tab to another (on the same MainWindow widget). Is the eventFilter bugged and it doesn't receives all the events?
-
@ewerybody
As I wrote some message after, yes there is -of course - pyside2-uic!
But I don't like to use it.
Using it solve all of my problems because it produce a class and with the class I can do what I want (inheriting from it, for example).But I would like to avoid to use it
-
@Saelyth
I think that we really have the same issue.
AN issue that can be a wrong interpretation of how QtUiTools.QUiLoader().load works.
It is returning an instance, not a class as.
In this way we have two QMainWindow nested one in the other.
With this workaround it worked:def __init__(self, ui_file, parent=None): super(Form, self).__init__(parent) self.ui=QtUiTools.QUiLoader().load(ui_file) self.setCentralWidget(self.ui)
But you loose the geometry of the QMainWindow designed with Designer (and maybe something more but I don't have the skill for investigating further)
We should find a way to modify the inner closeEvent method but I don't know how to do it.
Moreover I don't like to have two QMainWindow.Of course if someone has a real working sample code of a QMainWindow designed in Designer and then correctly loaded and used as a class... it would be really appreciated
-
Then remove your Form class as it's not useful in your case.
You can then create a custom event filter object that should handle the close event and whatever you want to do in it.
-
With the original @ZioLupo code the override of eventFilter would works just fine, but closeEvent wouldn't (that was the issue).
class Form(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.ui = QUiLoader().load("myfile.ui") self.ui.buttonLoad.clicked.connect(self.load_something) def eventFilter(self, target, event): print("this works") return False def closeEvent(self, event): print("this doesn't works")
But that creates two QWidgets (one for the Form class and one for self.ui). if I understood you right, @Sgaist, you suggest to make the Form class a non-QWidget, as the Qwidget will be load into self.ui, right? But then, if the Form class is not a QWidget, I don't get how to set the closeEvent or eventFilter methods for the self.ui QWidget.
I tried to do what you suggest with my next code. The windows open just fine but no override works and no events get to my handlers.
class Form(object): def __init__(self): super().__init__() self.ui = QUiLoader().load("myfile.ui") self.ui.eventFilter = self.eventFilter self.ui.closeEvent = self.closeEvent def eventFilter(self, target, event): print("doesn't works") return False def closeEvent(self, event): print("doesn't works")
I think the issue here is that we were waiting for PySide2 while we were working temporary on PyQt5, and assumed that PySide2 would behave like PyQt5, where we would port our Qt Designer UI to .py with pyuic command. But when PySide2 was released, we saw an alternative way to do things (load the .ui file directly) and now we are trying to skip one of the step (it seems unnecesary to convert the .ui file to .py in PySide2 if we can directly load the .ui file). However, while trying to do that, we got lost in the process as we lost something which we were familiar with: the abbility to override the UI events.
A working example on how to load a .ui file with PySide2 where closeEvent works would help us a lot.