小部件失去焦点时的信号是什么?

时间:2021-12-03 22:16:49

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?

在对话框中,按Tab键时,焦点将更改为另一个窗口小部件。在Qt中,是否有任何关于小部件失去焦点的信号?我可以用它来检查输入是否有效吗?如果没有,我可以设置焦点并要求用户重新输入吗?

2 个解决方案

#1


18  

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

没有信号,但是如果你想知道你的小部件何时失去了焦点,则在你的小部件中覆盖和重新实现void QWidget :: focusOutEvent(QFocusEvent * event)。只要您的小部件失去焦点,就会调用它。要将焦点放在窗口小部件上,请使用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.

要验证QLineEdit或QComboBox中的输入,您可以继承QValidator并实现自己的验证器,或使用现有子类之一,QIntValidator,QDoubleValidator或QRegExpValidator。分别使用QLineEdit :: setValidator(const QValidator *)和QComboBox :: setValidator(const QValidator *)设置验证器。

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:

如果要验证模式对话框的内容,一种方法是使用如下实现覆盖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;
}

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.

除非成功验证对话框的内容,否则不允许用户使用“确定”按钮或具有“已接受”角色的任何其他按钮关闭对话框。在这个例子中,我假设对话框有一个名为lineEdit的QLineEdit,而validate函数将确保其内容不为空。如果是,则将焦点设置为QLineEdit并再次显示对话框。

#2


7  

It is also possible (and easier) to create the signal yourself

您自己也可以(并且更容易)创建信号

In the .cpp (do not forget to include the moc)

在.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);
};

And to connect it:

并连接它:

connect(new FocusWatcher(myWidget), &FocusWatcher::focusChanged, this, &View::doSomething);

#1


18  

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

没有信号,但是如果你想知道你的小部件何时失去了焦点,则在你的小部件中覆盖和重新实现void QWidget :: focusOutEvent(QFocusEvent * event)。只要您的小部件失去焦点,就会调用它。要将焦点放在窗口小部件上,请使用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.

要验证QLineEdit或QComboBox中的输入,您可以继承QValidator并实现自己的验证器,或使用现有子类之一,QIntValidator,QDoubleValidator或QRegExpValidator。分别使用QLineEdit :: setValidator(const QValidator *)和QComboBox :: setValidator(const QValidator *)设置验证器。

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:

如果要验证模式对话框的内容,一种方法是使用如下实现覆盖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;
}

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.

除非成功验证对话框的内容,否则不允许用户使用“确定”按钮或具有“已接受”角色的任何其他按钮关闭对话框。在这个例子中,我假设对话框有一个名为lineEdit的QLineEdit,而validate函数将确保其内容不为空。如果是,则将焦点设置为QLineEdit并再次显示对话框。

#2


7  

It is also possible (and easier) to create the signal yourself

您自己也可以(并且更容易)创建信号

In the .cpp (do not forget to include the moc)

在.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);
};

And to connect it:

并连接它:

connect(new FocusWatcher(myWidget), &FocusWatcher::focusChanged, this, &View::doSomething);