How to prevent closing QMessageBox after clicking a button - c++

I have 3 buttons on QMessageBox added by QMessageBox::addButton() method. Is it possible to prevent closing the message box if a button has been clicked? By default every button closes the window, but I don't want to do it for one button.

One interesting way to approach it that worked for me is to completely disconnect the signals for the target button created, and then re-add the intended functionality. This won't work for everyone, especially if the button isn't created this way and/or you still want to close the dialog correctly. (There might be a way to add it back and/or simulate the behavior with QDialog::accept, QDialog::reject, QDialog::done - haven't tried yet.)
Example:
QMessageBox *msgBox = new QMessageBox(this);
QAbstractButton *doNotCloseButton = msgBox->addButton(tr("This button will not close anything"), QMessageBox::ActionRole);
// Disconnect all events - this will prevent the button from closing the dialog
doNotCloseButton->disconnect();
connect(doNotCloseButton, &QAbstractButton::clicked, this, [=](){ doNotCloseButton->setText("See? Still open!"); });

If you can get a pointer to the QMessageBox widget, you can try to install a QObject::eventFilter on it which filters the QEvent::Close.

Just had the same problem but I wanted to add a checkbox and it kept closing the dialog on clicked even with the ButtonRole set to QMessageBox::ActionRole (tried others too). For this scenario I just called blockSignals(true) on the QCheckBox and now it allows check/uncheck behaviour without closing the dialog. Luckily QCheckBox works fine without signals but assume you want a signal from your button.
They should likely add a new role that doesn't close the dialog as it's a pain to derive a class for simple customizations.

I looked through the addButton() functions overloads, but there is no custom behavior for the buttons you add with this method. They will behave like the standard buttons on a messagebox should.
However if you want to create a fully customizable dialog, then your best option is to extend the QDialog class and use whatever controlls you like on it.

Thanks to #Albert's Answer, I found that this also possible in python:
messagebox = QMessageBox()
button = QPushButton("This button will not close anything")
messagebox.addButton(button, QMessageBox.ButtonRole.NoRole)
button.disconnect()

Related

C++ Qt Action in menu not triggered by keyboard shortcut when menu open

I am building a Qt application on Linux. I have a menu bar in the main window with two menus in it, each with several actions, all of which have keyboard shortcuts associated with them. The keyboard shortcuts work when the menus are not open, but when one of the menus is open, none of them work.
The shortcuts were added to the actions with setShortcut prior to the actions being added to their respective menus with [menuobject]->addAction. All the actions have the main window as their parent. After reading QAction shortcut doesnt always work I added calls to addAction, adding the action to the main window. This did not correct the problem.
Example of the code for one of the menu items:
//In the main window constructor
gameQuit = new QAction(QString(tr("&Quit\tCtrl+Q")), this);
gameQuit->setShortcut(QKeySequence(Qt::Key_Q | Qt::CTRL));
addAction(gameQuit);
connect(gameQuit, SIGNAL(triggered()), this, SLOT(close()));
gameMenu = menuBar()->addMenu(QString(tr("&Game")));
gameMenu->addAction(gameQuit);
In QtCreator, which I assume was written with Qt, the keyboard shortcuts for the menu items do work when the menus are open, so I think there must be a way.
Thanks for any help.
Taking some advice from the comments of the cited post (which had been rebuked, which is why I didn't try it initially), I modified the shortcut context using [actionobject]->setShortcutContext(). Apparently the default does not work in my scenario.
I first tried setting to Qt::WindowShortcut, which didn't work. Qt::ApplicationShortcut did work, however, this may have shortcomings as noted in the comments of the cited post. They don't happen to matter for this particular application of mine though, so I am going to post and accept this as the answer.
Example of the correcting code:
//In the constructor of the main window, after creation of the action and
//setting of the shortcut
gameQuit->setShortcutContext(Qt::ApplicationShortcut);

Qt - Pushbutton click not always working

I have a QT App and have currently added a new QPushButton.
I have connected the button properly with:
QObject::connect(ui->myButton, SIGNAL(clicked()), this, SLOT(SendResetEchoRequest()));
Most of the time it is working when i click it calls the function. But sometimes it doesn't register my click. Sometimes i need up to 5-10 clicks to make the function fire once and i don't know why.
To be sure this is a problem with the Button / Click i have tried using the function on key UP like this:
if(GetAsyncKeyState(VK_UP)){
SendResetEchoRequest();
}
This works 100% perfectly fine. And when i press my UP key it triggers the function.
Anybody got an idea why sometimes it doesn't register my click?
I am not sure if it will be of any help, I would like to suggest a quick exercise to examine.
You can connect to the signals pressed and released and in the slot routine try to set the button text to "Pressed"and on button release it should go back to "<your button text>"
QObject::connect(ui->myButton, SIGNAL(pressed()), this, SLOT(setbuttonPressed()));
QObject::connect(ui->myButton, SIGNAL(released()), this, SLOT(setbuttonReleased()));
setbuttonPressed() {
ui->myButton->setText("Pressed"); }
setbuttonReleased() {
ui->myButton->setText("My Button"); }
This way when you see that occasional problem you can examine if QAbstractButton or QPushButton class ever signals anything. This is just my thought to debug what's going on, may not be the solution to your problem.

How to disable user interaction in a Qt application when a DialogBox shown?

I have a modeless QDialog box that popup on errors/warning in my Qt application, I want to force the user to only focus on that dialog box and not click anything in the application until they clicked Ok on the dialog box.
I need the dialog box to remain modeless. A solution like hiding the main window or covering it up is not acceptable.
At the moment I'm using setModal(true); to solve my problem. But I think this method might be stopping the main application from executing.
From the documentation:
If you use show() and setModal(true) together to perform a long
operation, you must call QApplication::processEvents() periodically
during processing to enable the user to interact with the dialog.
Instead of using a QDialog box, try using qDebug statements in your code or a log file using qInstallMsgHandler.
You could also show a QTextEdit and post your log/error messages there in real time, too.
http://qt-project.org/doc/qt-4.8/debug.html
http://qt-project.org/doc/qt-4.8/qdebug.html#details
http://qt-project.org/doc/qt-4.8/qtglobal.html#qInstallMsgHandler
http://qt-project.org/doc/qt-4.8/qtextedit.html#details
If you still really want to debug using a QDialog box for errors, in a pseudo modal dialog but not modal dialog, you could try using eventFilters to prevent mouse and keyboard events from arriving at any other window, but it would be tricky to allow the exception to end up only at QDialog, but it is do-able.
You could also go to the one or two widgets that accept mouse and keyboard input, and ignore the input if the a QDialogBox is visible. But both of these ways of showing an error, but limiting input without making it Modal is really hacky, and would probably be error prone.

What signal QListView sends when is about to hide

In my code I do have to do manually:
/*This works but there must be a better way*/
listView->hide();//INSTEAD OF THIS I'D RATHER SEND A SIGNAL CAUSING
LISTVIEW TO UPDATE -
update(), viewport()->update, repaint() doesn't work,
Basically I have a listView in which I'm displaying selection of files. After pressing ok this dialog closes. When I open this dialog again and pick another set of files the old ones are shown, and I have to hide and show listView in order to see newly selected files.
What you need is the clearSelection slot. Connect it to the finished signal of your dialog.

QWidgetAction : how to make the menu disappear after the user completes his input

In my QMenuBar, I have several menus.
One of those menus has a QWidgetAction in it.
It shows up fine, but the problem is that once the user completes his input, I want the menu to disappear (as is the normal behavior for a classical QAction).
However, I am not sure on how to do that. In my QWidgetAction, there is a button the user presses when he is done; I can therefore bind to this button's clicked() signal.
In the slot, I tried to setFocus() an element outside the menu but the menu still doesn't disappear.
How to tell the menu to close itself when my users finish interacting with the QWidgetAction?
Thanks
QMenu inherits QWidget, so calling yourMenu->hide() should do the work.
Hope this helps.