Message Box X Button Works like the Cancel Button Of the Box
-
I am facing some difficulty understanding how the functionality of the QMessage box is working. Here I have created a Simple Dialog box with a push button.
Here on clicking that push button. It will show a MessageBox.
Below I have attached the code for the QMessageBox.
void dialog::on_pushButton_clicked() { QMessageBox box; box.setText("Choose An Option"); QPushButton *pDiscardChangesBtn = box.addButton("Discard Changes", QMessageBox::RejectRole); QPushButton *pSaveChangesBtn = box.addButton("Save Changes", QMessageBox::AcceptRole); box.setDefaultButton(pSaveChangesBtn); box.exec(); if(box.clickedButton() == pSaveChangesBtn) { qInfo() << "Save Changes Button Clicked"; } else if(box.clickedButton() == pDiscardChangesBtn) { qInfo() << "Discard Changes Button clicked"; } else { qInfo() << "Closed"; } }
here I have attached the output of the terminal.
I got the above output by first selecting "Save Changes" btn, then "Discard Changes" btn, the X button of the MessageBox Window.
Here I have noticed that on clicking "Discard Changes" btn, X button of the windows same block of code (else if block) is getting executed.
My doubt is
- why is this happening? Internally are they same or calling same method?
- How can I get the code in the else block get executed when clicked on X button?
-
- Internally QMessageBox will try to find an "escape" button from all buttons to set as the clicked button when "Escape" key is pressed or X is clicked,
QMessageBox::RejectRole
is one of the case to be chosen. - If there is no such button, the X will be disabled.
So if you don't want the discard button and X to act the same, just don't set it's role to
QMessageBox::RejectRole
.
QMessageBox::DestructiveRole
is more suitable for that case.You can also use
StandardButtons
likeQMessageBox box; box.setText("Choose An Option"); box.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); //I add cancel to make X enabled box.setDefaultButton(QMessageBox::Save); int result = box.exec(); if(result == QMessageBox::Save) { qInfo() << "Save Button Clicked"; } else if(result == QMessageBox::Discard) { qInfo() << "Discard Button clicked"; } else { qInfo() << "Cancelled"; }
- Internally QMessageBox will try to find an "escape" button from all buttons to set as the clicked button when "Escape" key is pressed or X is clicked,
-
What should happen else? The dialog was discarded by clicking on the 'X'. I don't see why another (spurious) return value should be returned in this case.
-
@Christian-Ehrlicher Then the having the "Discard Changes" button is of no use when it does the same thing. What I want is on clicking the "X" button I need it to run the else part. Is there a way?
The scenario I'm thinking. I have a properties page of a device, the user after filling it when the user clicks "OK". This Message Box should appear. On clicking "Save Changes" internally a saveProperties() will be triggered, It will do its thing and it will also close the properties dialog. Similarly, On clicking the "Discard Changes" Button it will call discardChanges() is triggered it does its thing and closes the properties dialog, but on clicking the "X" button only the Message Box should be closed and the properties dialog should be remained opened so that the user can continue editing the device properties.
But from the simple example, I gave. if it's implemented for the above scenario then on clicking the "X" button it will call the discardChanges() and close the properties dialog.
-
Then I would expect a third button for this.
-
- Internally QMessageBox will try to find an "escape" button from all buttons to set as the clicked button when "Escape" key is pressed or X is clicked,
QMessageBox::RejectRole
is one of the case to be chosen. - If there is no such button, the X will be disabled.
So if you don't want the discard button and X to act the same, just don't set it's role to
QMessageBox::RejectRole
.
QMessageBox::DestructiveRole
is more suitable for that case.You can also use
StandardButtons
likeQMessageBox box; box.setText("Choose An Option"); box.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); //I add cancel to make X enabled box.setDefaultButton(QMessageBox::Save); int result = box.exec(); if(result == QMessageBox::Save) { qInfo() << "Save Button Clicked"; } else if(result == QMessageBox::Discard) { qInfo() << "Discard Button clicked"; } else { qInfo() << "Cancelled"; }
- Internally QMessageBox will try to find an "escape" button from all buttons to set as the clicked button when "Escape" key is pressed or X is clicked,
-
This post is deleted!
-
@Abhi_Varma
Wow, I would never think of that, but yes you can...
I've triedbox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); box.button(QMessageBox::Cancel)->hide();
or in your orignal code
QPushButton *pDiscardChangesBtn = box.addButton("Discard Changes", QMessageBox::DestructiveRole); QPushButton *pSaveChangesBtn = box.addButton("Save Changes", QMessageBox::AcceptRole); QPushButton *pCancelBtn = box.addButton(QMessageBox::Cancel); pCancelBtn->hide();
It can do the trick. :)
-
@Abhi_Varma
Well, it is not a normal way since Qt intentionally disable X button when there's no escape button.
So this is kind of a cheat way.
Also there's no guarantee that it will always work as expected in all future Qt versions.
I would keep the cancel button if I don't have to hide it. -
@Abhi_Varma
What do you mean? To have the X button enabled without adding and hiding a cancel/close button?
You can, for example, write your own dialog instead of using QMessageBox and handle everything by yourself, but I think there's no need to do that.
I would say hiding the button is already the best solution in my opinion...
If you really need the button invisible, just do it.
I would also cheat / try to change Qt's behavior in my code if I have to.