Подтвердить что ты не робот

Каков сигнал, когда виджет теряет фокус?

В диалоговом окне, когда нажата клавиша tab, фокус меняется на другой виджет. В Qt есть ли сигнал, когда виджет теряет фокус? Могу ли я использовать его для проверки правильности ввода? Если нет, могу ли я установить фокус назад и попросить пользователя повторно ввести?

4b9b3361

Ответ 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);