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