In a dialog, when the tab key is pressed, the focus changes to another widget. In Qt, is there any signal for when a widget loses its focus? Can I use it to check if the input is valid or not? If not, can I set the focus back and ask the user to re-input?
There's no signal but if you want to know when your widget has lost focus, override and reimplement void QWidget::focusOutEvent(QFocusEvent* event)
in your widget. It will be called whenever your widget has lost focus. To give focus to a widget, use QWidget::setFocus(Qt::FocusReason)
.
To validate input in a QLineEdit
or QComboBox
you can subclass QValidator
and implement your own validator, or use one of the existing subclasses, QIntValidator
, QDoubleValidator
, or QRegExpValidator
. Set the validator with QLineEdit::setValidator(const QValidator*)
and QComboBox::setValidator(const QValidator*)
respectively.
If you want to validate the contents of a modal dialog box, one way would be to override QDialog::exec()
with an implementation like this:
int MyDialog::exec() {
while (true) {
if (QDialog::exec() == QDialog::Rejected) {
return QDialog::Rejected;
}
if (validate()) {
return QDialog::Accepted;
}
}
}
bool MyDialog::validate() {
if (lineEdit->text().isEmpty()) {
QMessageBox::critical(this, "Invalid value", "The specified value is not valid");
lineEdit->setFocus();
lineEdit->selectAll();
return false;
}
return true;
}
It will not allow the user to close the dialog with the OK button or any other button with the Accepted role unless the contents of the dialog is successfully validated. In this example I assume the dialog has a QLineEdit
named lineEdit
and the validate
function will make sure that its content is not empty. If it is, it will set the focus to the QLineEdit
and show the dialog again.
It is also possible (and easier) to create the signal yourself
In the .cpp (do not forget to include the moc)
class FocusWatcher : public QObject
{
Q_OBJECT
public:
explicit FocusWatcher(QObject* parent = nullptr) : QObject(parent)
{
if (parent)
parent->installEventFilter(this);
}
virtual bool eventFilter(QObject *obj, QEvent *event) override
{
Q_UNUSED(obj)
if (event->type() == QEvent::FocusIn)
emit focusChanged(true);
else if (event->type() == QEvent::FocusOut)
emit focusChanged(false);
return false;
}
Q_SIGNALS:
void focusChanged(bool in);
};
And to connect it:
connect(new FocusWatcher(myWidget), &FocusWatcher::focusChanged, this, &View::doSomething);
来源:https://stackoverflow.com/questions/17818059/what-is-the-signal-for-when-a-widget-loses-focus