How to change the default QPushButton in a QDialogBox - c++

My goal is to have two buttons, "Cancel" and "Connect", and to have Cancel be the default button when the user presses ENTER. I also want the user to be able to TAB to the next button ("Connect") and press ENTER and have "Connect" get pushed. Here's my code:
QPushButton * cancelButton = new QPushButton(tr("&Cancel"));
cancelButton->setAutoDefault(true);
cancelButton->setDefault(true);
cancelButton->setFocus();
QPushButton * continueButton = new QPushButton(tr("Co&nnect"));
continueButton->setAutoDefault(true);
continueButton->setDefault(false);
ui->buttonBox->addButton(cancelButton, QDialogButtonBox::RejectRole);
ui->buttonBox->addButton(continueButton, QDialogButtonBox::AcceptRole);
Setting the Cancel button to the the default button doesn't actually seem to work.
Setting the autoDefault property on all the butons seems to be necessary in allow the buttons to get pushed after pressing TAB and ENTER for example. This seems to jive with the documentation for autoDefault. However, the documentation for the default property seems to indicate that the default button will get pushed only if there are no buttons that have the autoDefault property set. Otherwise, the button that gets pushed when ENTER is pressed will be the currently selected autoDefault button. So it seems like what I need to do is to make the cancelButton have focus by default, but I can't seem to figure out how to do this.

You have to call cancelButton->setFocus(); after adding the buttons to the QDialogButtonBox, not before.

Try adding below line before you call dialog->show
button->isEnabled(true)

Related

How to use CDialog::SetDefId with a non button control?

I've come across CDialog::SetDefId and while it is pretty easy and clear that it is for "pushbuttons" I wanted to use this functionality with a non button control.I understand that you have to press Enter or Return to make the dialog use that ID
If I set nID to 0 in the CDialog::OnInitDialog and have no default button setted the dialog will default to CDialog::OnOk, If I do have a default button setted, the dialog will push that button as expected.The thing is that I want to make this work for a non button control, so if I set nID to a control that is not a pushbutton, the dialog will do nothing even If I set the message handler for the keydown event or NM_RETURN, it doesn't matter if the control has focus or not, the dialog will still do nothing if I press Enter or Return.How can I make the control be the default control without using stuff like PreTranslateMessage? and which message is sent to the control?thanks in advance
Yes, it only works with buttons but you can use SetFocus to change focus to any other control:
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
GetDlgItem(IDC_CHECK1)->SetFocus();
return 0; // return TRUE unless you set the focus to a control
}
In this example the OK button may still be the default button. Enter key will go to default button, probably IDOK. But space key it will change the check box IDC_CHECK1.
There has to be a default button. If you don't want one, then add a fake button, lets say IDC_BUTTON1, and make it the default button and not visible, then you don't see a default button (you can still add IDC_BUTTON1 to message map and decide what to do with Enter key)

How to turn off QAbstractButton animateClick when lineEdit has focus

I am new to QT GUI programming and I am using QT Creator. The problem I am seeing is with my pushbutton and line edit when the user presses the enter key. My program opens a groupbox and allows the user to enter a password and press ok or cancel.
If the user presses the enter key when the line edit has focus, the program seems to emit a second signal for QAbstractButton animateClick(); So when the next group box opens and prompts the user to press ok or cancel, the program continues as if the user pressed the ok button.
I set up my Push buttons to allow the user to press the tab key and hit the enter key. In order to obtain this functionality I set okbutton->setAutodefault(true); and cancelButton->setAutodefault(true);
I also have a lineEdit for the user to enter a password and press enter. I set this up by connecting the return pressed signal to the ok button shown below.
connect(lineEdit, SIGNAL(returnPressed()), okButton, SIGNAL(clicked()));
I also tried to connect return pressed signal directly to the slot but the problem still occurs.
connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(chkPassword()));
If the user clicks the okButton with the mouse or I set okButton->setAutoDefault(false); the program functions as it should. I would like to know if it is possible to disable the animateClick signal that occurs when the line edit has focus.
Any help with this would be greatly appreciated.
Try never connecting lineEdit with the okButton, i.e. comment out this line in your code:
connect(lineEdit, SIGNAL(returnPressed()), okButton, SIGNAL(clicked()));
and check if the program behaves as you want it to.
Also, you might want to call
okButton->setDefault(true);
in addition to your setAutoDefault() calls on both buttons, depending on what exactly you want to happen when the user presses Enter with various things in focus. See this answer for more information on this subject.
I assume, since you never mention it, that you do not call setDefault() for any of your buttons. Thus, okButton is your first button with the autoDefault property set to true. This means that okButton becomes the dialog's "button of choice" whenever the dialog has to handle an Enter keypress that did not happen on some other autoDefault button (such as cancelButton in your case).
Everytime any widget in your dialog receives an Enter keypress and does not consume the event itself, the event ends up being handled by the dialog's default-button handling logic, which results in a click on the aforementioned "button of choice".
QLineEdit is not used for multi-line editing, so it probably just does not consume the key press event for Enter (while still handling it, in that it sends outs the returnPressed() signal). Thus, your connection of returnPressed() ends up doing whatever it is doing, and, additionaly, the default-button logic ends up clicking your button a second time.
Also check out this thread on the Qt project forums which seems to solve the same problem differently.

Qt - Why add '&' to the string?

QPushButton *quitButton = new QPushButton("&Quit");
Why add a & to the Quit? Removing & and it seems the code behaves the same.
The ampersand makes the button respond to a particular key-combination. In your case, if you press ALT + Q it will force the button to be pushed.
From Qt
The QPushButton widget provides a command button.
The push button, or command button, is perhaps the most commonly used widget in any graphical user interface. Push (click) a button to command the computer to perform some action, or to answer a question. Typical buttons are OK, Apply, Cancel, Close, Yes, No and Help.
A command button is rectangular and typically displays a text label describing its action. A shortcut key can be specified by preceding the preferred character with an ampersand in the text. For example:
QPushButton *button = new QPushButton("&Download", this);
In this example the shortcut is Alt+D. See the QShortcut documentation for details (to display an actual ampersand, use '&&').
The ampersand means that the letter 'Q' next to it will be used as a keyboard shortcut.

How to prevent closing QMessageBox after clicking a button

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()

Entering data into a Qt GUI with the keyboard: unintended side effects when pressing enter

I've written a Qt GUI which contains some QSpinBoxes and QDoubleSpinBoxes, among other stuff. Everything works as intended, except for one thing: when I enter a number into the QSpinBoxes and finish the entry by pressing the "Enter" key, this also activates the first widget in the tab order: i.e. instead of just changing the value of my spin box, I'm also pressing the button at the top of my dialog - which I don't want. How can I fix this? (Note that I need to press Enter for the new value to be accepted, because the spin boxes' keyboard tracking is deactivated.)
EDIT: In case someone comes across a similar problem: http://developer.qt.nokia.com/doc/qt-4.8/eventsandfilters.html
I think what might be happening is the default button of a QDialog is being pressed when you press Enter.
If you are subclassing QDialog yourself, then one of your QPushButtons has it's default property set to true. If you revert that to false, then the button will not react to the Enter key unless in focus. The disadvantage here, is that your dialog can't be dismissed by pressing Enter, if you want to stick with the default values for example.