Dialogue vanishes when any button is pressed.
-
I have a dialogue that has a number of buttons: Add, Delete, Load, and Close.
The only one that invokes QDialog::accept() is the Close button.
If I run the code with a breakpoint in the slot for one of Add/Delete/Load, then when I press the relevant button I can debug through the handler and press F5 at the end of the code for the slot (this is Windows and Visual Studio), then the dialogue remains visible.
But if there's no breakpoint set the dialogue just vanishes when any of those buttons are pressed !! ???
If relevant this is Qt 6.8.0.
Sample slot:
void ProcessingSettingsDlg::addPressed() { QString name{ settingsName->text() }; currentSettings.name_ = name; // Set name of current settings settingsMap.emplace(name, currentSettings); // Add current settings to the set settingsList->addItem(name); // Add the name to the list of named settings dirty = true; }
Am I missing something obvious?
David
-
Finally I think I have got to the bottom of this! I found these two lines in ui_ProcessingSettingsDlg.h
QObject::connect(addButton, &QPushButton::clicked, DSS__ProcessingSettingsDlg, qOverload<>(&QDialog::accept)); QObject::connect(deleteButton, &QPushButton::clicked, DSS__ProcessingSettingsDlg, qOverload<>(&QDialog::reject));
which explains what is happening, so I went digging and found that they were in the signal/slot section of the ui file. I've no idea how that happened!!!
I've no clue why putting breakpoints in the slots was stopping that from happening.
David
-
I have a dialogue that has a number of buttons: Add, Delete, Load, and Close.
The only one that invokes QDialog::accept() is the Close button.
If I run the code with a breakpoint in the slot for one of Add/Delete/Load, then when I press the relevant button I can debug through the handler and press F5 at the end of the code for the slot (this is Windows and Visual Studio), then the dialogue remains visible.
But if there's no breakpoint set the dialogue just vanishes when any of those buttons are pressed !! ???
If relevant this is Qt 6.8.0.
Sample slot:
void ProcessingSettingsDlg::addPressed() { QString name{ settingsName->text() }; currentSettings.name_ = name; // Set name of current settings settingsMap.emplace(name, currentSettings); // Add current settings to the set settingsList->addItem(name); // Add the name to the list of named settings dirty = true; }
Am I missing something obvious?
David
@Perdrix said in Dialogue vanishes when any button is pressed.:
The only one that invokes QDialog::accept() is the Close button.
Some button have a default role which triggers a certain action (reject / accept).
How do you create these buttons and how do you verify that nothing happens when there is no breakpoint?!
I would say that it is impossible that the same code behaves differently depending on breakpoints. -
@Perdrix said in Dialogue vanishes when any button is pressed.:
The only one that invokes QDialog::accept() is the Close button.
Some button have a default role which triggers a certain action (reject / accept).
How do you create these buttons and how do you verify that nothing happens when there is no breakpoint?!
I would say that it is impossible that the same code behaves differently depending on breakpoints.@Pl45m4 I didn't say nothing happened when those buttons were pressed without a breakpoint in the slot.
I do know that the the dialog has returned to the caller with result equal to QDialog::Accepted.
The buttons are defined in the .ui file.
<widget class="QPushButton" name="addButton"> <property name="text"> <string>Add</string> </property> <property name="autoDefault"> <bool>false</bool> </property> </widget> </item> <item> <widget class="QPushButton" name="deleteButton"> <property name="text"> <string>Delete</string> </property> <property name="autoDefault"> <bool>false</bool> </property> </widget> </item> <item> <spacer> <property name="orientation"> <enum>Qt::Orientation::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> <item> <widget class="QPushButton" name="loadButton"> <property name="text"> <string>Load</string> </property> <property name="autoDefault"> <bool>false</bool> </property> <property name="default"> <bool>false</bool> </property> </widget> </item> <item> <widget class="QPushButton" name="closeButton"> <property name="text"> <string>Close</string> </property> <property name="autoDefault"> <bool>true</bool> </property> </widget> </item>
-
@Pl45m4 I didn't say nothing happened when those buttons were pressed without a breakpoint in the slot.
I do know that the the dialog has returned to the caller with result equal to QDialog::Accepted.
The buttons are defined in the .ui file.
<widget class="QPushButton" name="addButton"> <property name="text"> <string>Add</string> </property> <property name="autoDefault"> <bool>false</bool> </property> </widget> </item> <item> <widget class="QPushButton" name="deleteButton"> <property name="text"> <string>Delete</string> </property> <property name="autoDefault"> <bool>false</bool> </property> </widget> </item> <item> <spacer> <property name="orientation"> <enum>Qt::Orientation::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> <item> <widget class="QPushButton" name="loadButton"> <property name="text"> <string>Load</string> </property> <property name="autoDefault"> <bool>false</bool> </property> <property name="default"> <bool>false</bool> </property> </widget> </item> <item> <widget class="QPushButton" name="closeButton"> <property name="text"> <string>Close</string> </property> <property name="autoDefault"> <bool>true</bool> </property> </widget> </item>
-
@Perdrix
If you are having "funnies" when debugging/stepping through, resort to the old-fashioned printing output (qDebug()
) judiciously dropped around to see what appears to be going on and compare.@JonB That's not quite the problem - it works when I have breakpoints in the slots (i.e. it doesn't exit with QDialog::Accepted).
If there aren't breakpoints, pressing ANY of the buttons results in the slot for that button being run, and then the dialogue returns to the invoker with QDialog::Accepted.
D.
-
@JonB That's not quite the problem - it works when I have breakpoints in the slots (i.e. it doesn't exit with QDialog::Accepted).
If there aren't breakpoints, pressing ANY of the buttons results in the slot for that button being run, and then the dialogue returns to the invoker with QDialog::Accepted.
D.
@Perdrix
The idea is to compare behaviour withqDebug()
versus debugging step through. There is plenty you could put in to try to determine what is happening when in the non-debugging state. Have you tried in a standalone program? Else you can wait and see if someone else magically knows, but I doubt it. -
@Perdrix
The idea is to compare behaviour withqDebug()
versus debugging step through. There is plenty you could put in to try to determine what is happening when in the non-debugging state. Have you tried in a standalone program? Else you can wait and see if someone else magically knows, but I doubt it.@JonB I did put the qDebug() calls there and they just proved that the slots were invoked.
The call stack when I put a breakpoint on QDialog::accept() is mighty odd.
> Qt6Widgetsd.dll!QDialog::accept() Line 628 C++ DeepSkyStacker.exe!QtPrivate::FunctorCall<QtPrivate::IndexesList<>,QtPrivate::List<>,void,void (__cdecl QDialog::*)(void)>::call::__l2::<lambda_1>::operator()() Line 152 C++ DeepSkyStacker.exe!QtPrivate::FunctorCallBase::call_internal<void,`QtPrivate::FunctorCall<QtPrivate::IndexesList<>,QtPrivate::List<>,void,void (__cdecl QDialog::*)(void)>::call'::`2'::<lambda_1>>(void * * args, QtPrivate::FunctorCall<QtPrivate::IndexesList<>,QtPrivate::List<>,void,void (__cdecl QDialog::*)(void)>::call::__l2::<lambda_1> && fn) Line 65 C++ DeepSkyStacker.exe!QtPrivate::FunctorCall<QtPrivate::IndexesList<>,QtPrivate::List<>,void,void (__cdecl QDialog::*)(void)>::call(void(QDialog::*)() f, QDialog * o, void * * arg) Line 151 C++ DeepSkyStacker.exe!QtPrivate::FunctionPointer<void (__cdecl QDialog::*)(void)>::call<QtPrivate::List<>,void>(void(QDialog::*)() f, QDialog * o, void * * arg) Line 199 C++ DeepSkyStacker.exe!QtPrivate::QCallableObject<void (__cdecl QDialog::*)(void),QtPrivate::List<>,void>::impl(int which, QtPrivate::QSlotObjectBase * this_, QObject * r, void * * a, bool * ret) Line 570 C++ Qt6Cored.dll!QtPrivate::QSlotObjectBase::call(QObject * r, void * * a) Line 486 C++ Qt6Cored.dll!doActivate<0>(QObject * sender, int signal_index, void * * argv) Line 4120 C++ Qt6Cored.dll!QMetaObject::activate(QObject * sender, const QMetaObject * m, int local_signal_index, void * * argv) Line 4181 C++ Qt6Widgetsd.dll!QAbstractButton::clicked(bool _t1) Line 325 C++ Qt6Widgetsd.dll!QAbstractButtonPrivate::emitClicked() Line 383 C++ Qt6Widgetsd.dll!QAbstractButtonPrivate::click() Line 375 C++ Qt6Widgetsd.dll!QAbstractButton::mouseReleaseEvent(QMouseEvent * e) Line 977 C++ Qt6Widgetsd.dll!QWidget::event(QEvent * event) Line 8964 C++ Qt6Widgetsd.dll!QAbstractButton::event(QEvent * e) Line 934 C++ Qt6Widgetsd.dll!QPushButton::event(QEvent * e) Line 685 C++ Qt6Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3294 C++ Qt6Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 2772 C++ Qt6Cored.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1165 C++ Qt6Cored.dll!QCoreApplication::sendSpontaneousEvent(QObject * receiver, QEvent * event) Line 1624 C++ Qt6Widgetsd.dll!QApplicationPrivate::sendMouseEvent(QWidget * receiver, QMouseEvent * event, QWidget * alienWidget, QWidget * nativeWidget, QWidget * * buttonDown, QPointer<QWidget> & lastMouseReceiver, bool spontaneous, bool onlyDispatchEnterLeave) Line 2353 C++ Qt6Widgetsd.dll!QWidgetWindow::handleMouseEvent(QMouseEvent * event) Line 634 C++ Qt6Widgetsd.dll!QWidgetWindow::event(QEvent * event) Line 299 C++ Qt6Widgetsd.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e) Line 3294 C++ Qt6Widgetsd.dll!QApplication::notify(QObject * receiver, QEvent * e) Line 3245 C++ Qt6Cored.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1165 C++ Qt6Cored.dll!QCoreApplication::sendSpontaneousEvent(QObject * receiver, QEvent * event) Line 1624 C++ Qt6Guid.dll!QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent * e) Line 2462 C++ Qt6Guid.dll!QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent * e) Line 2189 C++ Qt6Guid.dll!QWindowSystemInterface::sendWindowSystemEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 1120 C++ Qt6Guid.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 45 C++ Qt6Cored.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 470 C++ Qt6Guid.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 36 C++ Qt6Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 101 C++ Qt6Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 191 C++ Qt6Widgetsd.dll!QDialog::exec() Line 568 C++ DeepSkyStacker.exe!DSS::ProcessingDlg::onSettings() Line 1204 C++
the code at line 1204 in ProcessingDlg.cpp simply says:
if (QDialog::Accepted == dlg.exec() && dlg.settingsChanged()) { processingSettings = dlg.settings(); updateControlsFromSettings(); processAndShow(false); showHistogram(false); updateControls(); setDirty(); }
If it were something in my dialogue that was invoking accept() I would expect to see references to code in the ProcessingSettingsDlg class in the call stack but there are not any of those.
David
-
@Perdrix
The idea is to compare behaviour withqDebug()
versus debugging step through. There is plenty you could put in to try to determine what is happening when in the non-debugging state. Have you tried in a standalone program? Else you can wait and see if someone else magically knows, but I doubt it.@JonB You said that "there's plenty I could put in "
Where? I instrumented the slot for the Add button (which I'm using for the tests) and the qDebug output was shown in the debug output, but I can't see anywhere I could instrument to see what's driving accept(). My code only invokes that from the Close button. The call stack when accept() is driven doesn't refer to my dialogue code at all:
void ProcessingSettingsDlg::connectSignalsToSlots() { connect(addButton, &QPushButton::pressed, this, &ProcessingSettingsDlg::addPressed); connect(deleteButton, &QPushButton::pressed, this, &ProcessingSettingsDlg::deletePressed); connect(loadButton, &QPushButton::pressed, this, &ProcessingSettingsDlg::loadPressed); connect(closeButton, &QPushButton::pressed, this, &ProcessingSettingsDlg::closePressed); connect(settingsName, &QLineEdit::textEdited, this, &ProcessingSettingsDlg::nameEdited); connect(settingsList, &QListWidget::itemDoubleClicked, this, &ProcessingSettingsDlg::listItemDoubleClicked); } ProcessingSettingsDlg::~ProcessingSettingsDlg() {} // // Slots // void ProcessingSettingsDlg::addPressed() { ZFUNCTRACE_RUNTIME(); qDebug() << "in ProcessingSettingsDlg::addPressed()"; QString name{ settingsName->text() }; if (name.isEmpty()) { qDebug() << "name is empty"; return;; } currentSettings.name_ = name; // Set name of current settings settingsMap.emplace(name, currentSettings); // Add current settings to the set settingsList->addItem(name); // Add the name to the list of named settings dirty = true; } void ProcessingSettingsDlg::deletePressed() { ZFUNCTRACE_RUNTIME(); QString name = settingsList->currentItem()->text(); delete settingsList->takeItem(settingsList->currentRow()); settingsMap.erase(name); dirty = true; } void ProcessingSettingsDlg::loadPressed() { ZFUNCTRACE_RUNTIME(); QString name = settingsList->currentItem()->text(); settingsName->setText(name); // // The next statement could throw a std::out_of_range exception if the item doesn't exist. // This would indicate a serious logic error in the code ... // currentSettings = settingsMap.at(name); settingsLoaded = true; } void ProcessingSettingsDlg::closePressed() { if (dirty) { // // Loop over all the settings // for (auto it = settingsMap.cbegin(); it != settingsMap.cend(); ++it) { it->second.saveSettings(); } } QDialog::accept(); }
-
Finally I think I have got to the bottom of this! I found these two lines in ui_ProcessingSettingsDlg.h
QObject::connect(addButton, &QPushButton::clicked, DSS__ProcessingSettingsDlg, qOverload<>(&QDialog::accept)); QObject::connect(deleteButton, &QPushButton::clicked, DSS__ProcessingSettingsDlg, qOverload<>(&QDialog::reject));
which explains what is happening, so I went digging and found that they were in the signal/slot section of the ui file. I've no idea how that happened!!!
I've no clue why putting breakpoints in the slots was stopping that from happening.
David
-
Finally I think I have got to the bottom of this! I found these two lines in ui_ProcessingSettingsDlg.h
QObject::connect(addButton, &QPushButton::clicked, DSS__ProcessingSettingsDlg, qOverload<>(&QDialog::accept)); QObject::connect(deleteButton, &QPushButton::clicked, DSS__ProcessingSettingsDlg, qOverload<>(&QDialog::reject));
which explains what is happening, so I went digging and found that they were in the signal/slot section of the ui file. I've no idea how that happened!!!
I've no clue why putting breakpoints in the slots was stopping that from happening.
David
@Perdrix said in Dialogue vanishes when any button is pressed.:
why would uic put those lines there???
I suspect that Add and Delete button were the buttons that come with a
QDialog
QtDesigner template... these are connected to the slots by default... to reject and to accept respectively.
I think you used these two, renamed and re-designed them while modifying your UI file, while the connection persists.
Similar to the "hidden" connect slots by name mechanic, which also might confuse you if one is not aware of that :) -
P Perdrix has marked this topic as solved on