Solved Signals blocked from widget in QMdiSubwindow but not in QDilaog
-
I have created a widget with a QPushbutton. I connect to the clicked signal. If I host the widget in a QDialog the signal is sent and received by the handler just fine, but if it is used in a QMdiSubwinow, I press the button and nothing happens. I have poked at the thing a bunch of different times trying to set up parent / child relationships more explicitly, but there is no joy. I am not sure how to really debug this behavior. Is there a way I can watch the signal fire and see who receives it? It would seem to be something with the way the QMdiSubwindow takes ownership, but can't tell. Any advice on this issue is helpful. I am dead in the water.
Not sure if this is relevant, but the widget is created in the Qt Creator and I am loading it with the QUiLoader.
-
Well shoot, I created the simplest case which had what i thought were all the variables, but I was unable to replicate the issue. Obviously the real code is more complex, so I must have missed something. Still would be happy to entertain any thoughts.
import sys from PySide2 import QtCore, QtWidgets, QtUiTools widget_xml = """<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>IntermittentWidget</class> <widget class="QWidget" name="IntermittentWidget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>127</width> <height>68</height> </rect> </property> <property name="windowTitle"> <string>Intermittent Widget</string> </property> <widget class="QPushButton" name="intermittent_button"> <property name="geometry"> <rect> <x>10</x> <y>20</y> <width>112</width> <height>32</height> </rect> </property> <property name="text"> <string>Intermittent</string> </property> </widget> </widget> <resources/> <connections/> </ui> """ class QtViewController(QtCore.QObject): def __init__(self, ui_file: str, parent: QtWidgets.QWidget = None): super().__init__() byte_array = QtCore.QByteArray(bytes(ui_file, 'utf_8')) file = QtCore.QTemporaryFile() file.open() file.write(byte_array) file.seek(0) loader = QtUiTools.QUiLoader() self._view = loader.load(file, parent) self._init_view() @property def view(self): return self._view def _init_view(self): pass class IntermittentController(QtViewController): def __init__(self, ui_file: str, parent: QtWidgets.QWidget = None): super().__init__(ui_file, parent) def _init_view(self): self.view.intermittent_button.clicked.connect(self.on_click) def on_click(self): msgBox = QtWidgets.QMessageBox() msgBox.setWindowTitle('Click Handler') msgBox.setText('Handled Click') msgBox.exec() def main(): # create app QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts) app = QtWidgets.QApplication(sys.argv) app.setApplicationName('IssueMRE') app.setApplicationDisplayName('Issue MRE') # create main window main_window = QtWidgets.QMainWindow() main_window.setWindowTitle('Issue MRE') # create mdi area mdi_area = QtWidgets.QMdiArea() mdi_area.setViewMode(QtWidgets.QMdiArea.TabbedView) mdi_area.setTabsClosable(True) mdi_area.setTabsMovable(True) mdi_area.setDocumentMode(True) main_window.setCentralWidget(mdi_area) # create subwindow subWindow = QtWidgets.QMdiSubWindow(mdi_area) # create widget with button intermittent_controller = IntermittentController(widget_xml) # create subwindow with widget subWindow.setWidget(intermittent_controller.view) subWindow.setAttribute(QtCore.Qt.WA_DeleteOnClose) mdi_area.addSubWindow(subWindow) intermittent_controller.view.setWindowState(QtCore.Qt.WindowMaximized) main_window.show() # enter app loop sys.exit(app.exec_()) main()
-
OK. I pretty much cut and pasted this working code into my app and I get the same problem. There has to be something about the context that this thing is running in that is preventing this signal from getting through...
-
This post is deleted! -
This is really bizarre. I had a typo in my code for some tests I was doing and I actually had left in the line:
my_pushbutton.connect()
I called this with no parameters and didn't event try to connect the signal. I got an error, but any time after that when I clicked on my button the clicked signal was sent and received as expected????
-
@Denni-0 In my real app I create the ui with Qt Creator. In my example code I just used the xml that was produced by Qt Creator incase it was doing something unique that might be causing the issue.
-
OK. I figured out what is causing this and a work around. I don't exactly know why it is causing the issue. I am creating my widget inside the handler of a menu click event. Something about this is causing my issue. If I create the widget outside of the handler and create the subwindow inside the handler, everything works as expected. Not sure what is going on, everything is on the same thread, maybe something is getting posted to the event loop in a way I don't understand and causing something to go out of order, or maybe qt's signal processing engine is doing some type of weird context thing I am unaware of. Not sure. But I have a work around I can live with.
-
Hi,
@Howard-Swope said in Signals blocked from widget in QMdiSubwindow but not in QDilaog:
OK. I figured out what is causing this and a work around. I don't exactly know why it is causing the issue. I am creating my widget inside the handler of a menu click event. Something about this is causing my issue. If I create the widget outside of the handler and create the subwindow inside the handler, everything works as expected. Not sure what is going on, everything is on the same thread, maybe something is getting posted to the event loop in a way I don't understand and causing something to go out of order, or maybe qt's signal processing engine is doing some type of weird context thing I am unaware of. Not sure. But I have a work around I can live with.
You likely have an object life time issue. If you create it within the slot and it only exist there, it might be garbage collected.
-
@SGaist : Thank you. You are exactly correct. I thought by calling the connect I was increasing the reference count and would avoid the garbage collection. Issue solved.
@Denni-0 : I think the use of super() is correct, at least after reviewing the python documentation:
https://docs.python.org/3.7/library/functions.html?highlight=super#super
-
Oh and @Denni-0 Thanks for your help on this. I am very pleased to have come to a resolution.
-
@Howard-Swope said in Signals blocked from widget in QMdiSubwindow but not in QDilaog:
have come to a resolution
so please don't forget to mark your post as solved!