web-dev-qa-db-fra.com

Quel est le signal lorsqu'un widget perd le focus?

Dans une boîte de dialogue, lorsque le tab est enfoncée, le focus passe à un autre widget. Dans Qt, y a-t-il un signal pour quand un widget perd son focus? Puis-je l'utiliser pour vérifier si l'entrée est valide ou non? Sinon, puis-je rétablir la mise au point et demander à l'utilisateur de ressaisir?

29
user1899020

Il n'y a pas de signal mais si vous voulez savoir quand votre widget a perdu le focus, remplacez et réimplémentez void QWidget::focusOutEvent(QFocusEvent* event) dans votre widget. Il sera appelé chaque fois que votre widget a perdu le focus. Pour donner le focus à un widget, utilisez QWidget::setFocus(Qt::FocusReason).

Pour valider l'entrée dans un QLineEdit ou QComboBox vous pouvez sous-classe QValidator et implémenter votre propre validateur, ou utiliser l'une des sous-classes existantes, QIntValidator, QDoubleValidator ou QRegExpValidator. Définissez le validateur avec QLineEdit::setValidator(const QValidator*) et QComboBox::setValidator(const QValidator*) respectivement.

Si vous souhaitez valider le contenu d'une boîte de dialogue modale, une façon serait de remplacer QDialog::exec() avec une implémentation comme celle-ci:

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;
}

Il ne permettra pas à l'utilisateur de fermer la boîte de dialogue avec le bouton OK ou tout autre bouton avec le rôle Accepté à moins que le contenu de la boîte de dialogue ne soit validé avec succès. Dans cet exemple, je suppose que la boîte de dialogue a un QLineEdit nommé lineEdit et la fonction validate s'assurera que son contenu n'est pas vide. Si c'est le cas, il mettra le focus sur QLineEdit et affichera à nouveau la boîte de dialogue.

19
Daniel Hedberg

Il est également possible (et plus simple) de créer vous-même le signal

Dans le .cpp (n'oubliez pas d'inclure le 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);
};

Et pour le connecter:

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