В диалоговом окне, когда нажата клавиша tab, фокус меняется на другой виджет. В Qt есть ли сигнал, когда виджет теряет фокус? Могу ли я использовать его для проверки правильности ввода? Если нет, могу ли я установить фокус назад и попросить пользователя повторно ввести?
Каков сигнал, когда виджет теряет фокус?
Ответ 1
Нет сигнала, но если вы хотите узнать, когда ваш виджет потерял фокус, переопределите и переопределите void QWidget::focusOutEvent(QFocusEvent* event)
в своем виджете. Он будет вызываться всякий раз, когда ваш виджет потеряет фокус. Чтобы выделить фокус для виджета, используйте QWidget::setFocus(Qt::FocusReason)
.
Чтобы проверить ввод в QLineEdit
или QComboBox
, вы можете подклассом QValidator
и реализовать свой собственный валидатор или использовать один из существующих подклассов QIntValidator
, QDoubleValidator
или QRegExpValidator
. Установите валидатор с QLineEdit::setValidator(const QValidator*)
и QComboBox::setValidator(const QValidator*)
соответственно.
Если вы хотите проверить содержимое модального диалогового окна, одним из способов было бы переопределить QDialog::exec()
с реализацией следующим образом:
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;
}
Это не позволит пользователю закрыть диалоговое окно с помощью кнопки OK или любой другой кнопки с помощью принятой роли, если содержимое диалогового окна не будет успешно проверено. В этом примере я предполагаю, что в диалоговом окне есть QLineEdit
с именем lineEdit
, а функция validate
гарантирует, что его содержимое не будет пустым. Если это так, он установит фокус на QLineEdit
и снова отобразит диалоговое окно.
Ответ 2
Также возможно (и проще) создать сигнал самостоятельно
В .cpp(не забудьте включить 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);
};
И подключить его:
connect(new FocusWatcher(myWidget), &FocusWatcher::focusChanged, this, &View::doSomething);