web-dev-qa-db-fra.com

Comment rendre un QPushButton pressable pour la touche Entrée?

Je veux rendre mon application portable. Je peux tabuler partout, mais si je tabule sur un QPushButton je ne peux pas appuyer dessus avec Enter, seulement avec space.
Quel est le problème? Comment le rendre pressable pour Enter?

32
totymedli

tl; dr

  1. Dans la vue de l'interface utilisateur de Qt Creator, sélectionnez le bouton que vous souhaitez rendre pressable pour Enter.
  2. Dans le côté droit de l'éditeur de propriétés, faites défiler vers le bas jusqu'à la partie bleue intitulée QPushButton.
  3. Cochez la case par autoDefault ou default.

Property Editor

La plupart des cas, la principale différence entre autoDefault et default est la façon dont le bouton sera rendu. Mais il y a des cas où cela peut provoquer des choses inattendues.Pour plus d'informations, lisez la suite ci-dessous.


Revue complète

Aperçu

Chaque QPushButton possède 3 propriétés qui ne sont pas héritées. Parmi ceux-ci, deux (default et autoDefault) ont un rôle majeur lorsque nous plaçons des boutons sur QDialogs, car ces paramètres (et le focus sur l'un des boutons) décident lesquels bouton sera enfoncé si nous frappons Enter.
Toutes ces propriétés sont définies comme fausses par défaut. La seule attente est autoDefault qui sera vraie si le bouton a un parent QDialog.

Chaque fois que vous appuyez sur space le bouton avec le focus sera pressé. Les éléments suivants décrivent ce qui se passe si vous appuyez sur Enter.

Propriété par défaut

Si cela est défini sur true, le bouton sera un bouton par défaut .
Si Enter est enfoncé dans la boîte de dialogue, ce bouton sera enfoncé, sauf lorsque le focus est sur un bouton autoDefault.

Il ne devrait y avoir qu'un seul bouton par défaut. Si vous en ajoutez plus, le dernier ajouté sera le bouton par défaut.

Propriété AutoDefault

Si cela est défini sur true, le bouton sera un bouton autoDefault .
Si Enter est enfoncé dans la boîte de dialogue, alors ce bouton sera enfoncé si le focus est dessus.

Si le focus n'est pas sur un bouton autoDefault et qu'il n'y a pas de bouton par défaut, le bouton autoDefault suivant sera enfoncé pendant Enter.

Propriété plate

Si cela est défini sur true, la bordure du bouton ne sera pas augmentée.

Exemples de tableaux

Les tableaux suivants montrent quel bouton sera pressé avec différents boutons sur différents focus. Les boutons sont ajoutés de gauche à droite.

Regular, autoDefault and default buttons

Regular and autoDefault buttons

Code de test

Le code suivant est un moyen d'ajouter des boutons à une boîte de dialogue. Il peut être utilisé pour tester en modifiant les valeurs boolean dans setDefault() et/ou setAutoDefault().
Il vous suffit de créer une fenêtre, d'ajouter un QPushButton appelé pushButton et un QLabel appelé label (c'est le nom par défaut) . N'oubliez pas de #include <QMessageBox>. Copiez ensuite ce code dans le signal clicked() du bouton:

void MainWindow::on_pushButton_clicked()
{
   QMessageBox msgBox;

   QPushButton button("Button");
   button.setDefault(false);
   button.setAutoDefault(false);
   msgBox.addButton(&button, QMessageBox::ActionRole);

   QPushButton autodefaultbutton("AutoDefault Button");
   autodefaultbutton.setDefault(false);
   autodefaultbutton.setAutoDefault(true);
   msgBox.addButton(&autodefaultbutton, QMessageBox::ActionRole);

   QPushButton autodefaultbutton2("AutoDefault Button2");
   autodefaultbutton2.setDefault(false);
   autodefaultbutton2.setAutoDefault(true);
   msgBox.addButton(&autodefaultbutton2, QMessageBox::ActionRole);

   QPushButton defaultbutton("Default Button");
   defaultbutton.setDefault(true);
   defaultbutton.setAutoDefault(false);
   msgBox.addButton(&defaultbutton, QMessageBox::ActionRole);

   msgBox.exec();

   if (msgBox.clickedButton() == &button) {
      ui->label->setText("Button");
   } else if (msgBox.clickedButton() == &defaultbutton) {
      ui->label->setText("Default Button");
   } else if (msgBox.clickedButton() == &autodefaultbutton) {
      ui->label->setText("AutoDefault Button");
   } else if (msgBox.clickedButton() == &autodefaultbutton2) {
      ui->label->setText("AutoDefault Button2");
   }
}

Afficher

Si vous compilez le code, vous pouvez obtenir cette fenêtre. Vous n'avez même pas besoin de cliquer sur les boutons car la façon dont ils sont rendus par le système d'exploitation montre lequel sera pressé si vous appuyez sur Enter ou space.

OS rendered buttons

Documentation officielle

La plupart de cette réponse a été faite selon la documentation officielle.
La documentation QPushButton faite par Qt déclare ceci:

Les boutons par défaut et par défaut définissent ce qui se passe lorsque l'utilisateur appuie sur Entrée dans une boîte de dialogue.

Un bouton avec cette propriété définie sur true (c'est-à-dire le bouton par défaut de la boîte de dialogue) sera automatiquement enfoncé lorsque l'utilisateur appuiera sur Entrée, à une exception près: si un bouton autoDefault a actuellement le focus, le bouton autoDefault est enfoncé. Lorsque la boîte de dialogue contient des boutons autoDefault mais pas de bouton par défaut, appuyez sur Entrée pour appuyer sur le bouton autoDefault qui a actuellement le focus ou, si aucun bouton n'a le focus, sur le bouton autoDefault suivant dans la chaîne de focus.

Dans une boîte de dialogue, un seul bouton poussoir à la fois peut être le bouton par défaut. Ce bouton est ensuite affiché avec un cadre supplémentaire (selon le style de l'interface graphique).

Le comportement par défaut des boutons n'est fourni que dans les boîtes de dialogue. Les boutons peuvent toujours être cliqués à partir du clavier en appuyant sur la barre d'espace lorsque le bouton est actif.

Si la propriété par défaut est définie sur false sur le bouton par défaut actuel alors que la boîte de dialogue est visible, une nouvelle valeur par défaut sera automatiquement attribuée la prochaine fois qu'un bouton poussoir de la boîte de dialogue recevra le focus.

Il vaut également la peine de vérifier QDialog et QMessageBox .

65
totymedli

Selon la documentation de Qt, Enter devrait fonctionner

Les boutons de commande dans les boîtes de dialogue sont par défaut des boutons par défaut automatiques, c'est-à-dire qu'ils deviennent automatiquement le bouton poussoir par défaut lorsqu'ils reçoivent le focus d'entrée du clavier. Un bouton par défaut est un bouton poussoir qui est activé lorsque l'utilisateur appuie sur la touche Entrée ou Retour dans une boîte de dialogue. Vous pouvez changer cela avec setAutoDefault ().

http://qt-project.org/doc/qt-4.8/qpushbutton.html

2
Amxx

la réponse de totymedli est excellente. J'ai ajouté un petit programme pour tester différentes combinaisons de fonctions isDefault, autoDefault, setDefault et setAutoDefault.

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class Window(QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        autoDefaultInitialState = True
        defaultInitialState = False

        self.lineEdit1 = QLineEdit(self)
        self.lineEdit2 = QLineEdit(self)
        self.lineEdit3 = QLineEdit(self)

        # if we create a new button (e.g. "Print state"), with the same function,
        # it doesn't work, because adding a new button (apart from our 3 buttons)
        # produces total mess, so we use this lineedit for this purpose
        self.lineEdit1.returnPressed.connect(self.printState)

        #------------------------------------

        self.chkAutoDefaultOk = QCheckBox('OK setAutoDefault', self)
        self.chkAutoDefaultCancel = QCheckBox('Cancel setAutoDefault', self)
        self.chkAutoDefaultApply = QCheckBox('Apply setAutoDefault', self)

        self.chkDefaultOk = QCheckBox('OK setDefault', self)
        self.chkDefaultCancel = QCheckBox('Cancel setDefault', self)
        self.chkDefaultApply = QCheckBox('Apply setDefault', self)

        self.chkAutoDefaultOk.setChecked(autoDefaultInitialState)
        self.chkAutoDefaultCancel.setChecked(autoDefaultInitialState)
        self.chkAutoDefaultApply.setChecked(autoDefaultInitialState)

        self.chkDefaultOk.setChecked(defaultInitialState)
        self.chkDefaultCancel.setChecked(defaultInitialState)
        self.chkDefaultApply.setChecked(defaultInitialState)

        #------------------------------------

        self.pushButtonOk = QPushButton(self)
        self.pushButtonOk.setText("Ok")
        self.pushButtonOk.clicked.connect(lambda : print('ok'))

        self.pushButtonCancel = QPushButton(self)
        self.pushButtonCancel.setText("Cancel")
        self.pushButtonCancel.clicked.connect(lambda : print('cancel'))

        self.pushButtonApply = QPushButton(self)
        self.pushButtonApply.setText("Apply")
        self.pushButtonApply.clicked.connect(lambda : print('apply'))

        #------------------------------------

        self.pushButtonOk.setAutoDefault(autoDefaultInitialState)
        self.pushButtonCancel.setAutoDefault(autoDefaultInitialState)
        self.pushButtonApply.setAutoDefault(autoDefaultInitialState)

        self.pushButtonOk.setDefault(defaultInitialState)
        self.pushButtonCancel.setDefault(defaultInitialState)
        self.pushButtonApply.setDefault(defaultInitialState)

        #------------------------------------

        self.chkAutoDefaultOk.stateChanged.connect(self.chkChangeState)
        self.chkAutoDefaultCancel.stateChanged.connect(self.chkChangeState)
        self.chkAutoDefaultApply.stateChanged.connect(self.chkChangeState)

        self.chkDefaultOk.stateChanged.connect(self.chkChangeState)
        self.chkDefaultCancel.stateChanged.connect(self.chkChangeState)
        self.chkDefaultApply.stateChanged.connect(self.chkChangeState)

        #------------------------------------

        self.layout = QGridLayout(self)
        self.layout.addWidget(self.lineEdit1, 0, 0, 1, 3)
        self.layout.addWidget(self.lineEdit2, 1, 0, 1, 3)
        self.layout.addWidget(self.lineEdit3, 2, 0, 1, 3)

        self.layout.addWidget(self.chkAutoDefaultOk, 3, 0)
        self.layout.addWidget(self.chkAutoDefaultCancel, 3, 1)
        self.layout.addWidget(self.chkAutoDefaultApply, 3, 2)

        self.layout.addWidget(self.chkDefaultOk, 4, 0)
        self.layout.addWidget(self.chkDefaultCancel, 4, 1)
        self.layout.addWidget(self.chkDefaultApply, 4, 2)

        self.layout.addWidget(self.pushButtonOk, 5, 0)
        self.layout.addWidget(self.pushButtonCancel, 5, 1)
        self.layout.addWidget(self.pushButtonApply, 5, 2)

    def chkChangeState(self):
        obj = self.sender()
        if (obj == self.chkAutoDefaultOk):
            self.pushButtonOk.setAutoDefault(self.chkAutoDefaultOk.isChecked())
        Elif (obj == self.chkAutoDefaultCancel):
            self.pushButtonCancel.setAutoDefault(self.chkAutoDefaultCancel.isChecked())
        Elif (obj == self.chkAutoDefaultApply):
            self.pushButtonApply.setAutoDefault(self.chkAutoDefaultApply.isChecked())
        Elif (obj == self.chkDefaultOk):
            self.pushButtonOk.setDefault(self.chkDefaultOk.isChecked())
        Elif (obj == self.chkDefaultCancel):
            self.pushButtonCancel.setDefault(self.chkDefaultCancel.isChecked())
        Elif (obj == self.chkDefaultApply):
            #print('sender: self.chkDefaultApply')
            #print('before: ', self.pushButtonApply.isDefault())
            self.pushButtonApply.setDefault(self.chkDefaultApply.isChecked())
            #print('after: ', self.pushButtonApply.isDefault())

    def printState(self):
        print(self.pushButtonOk.autoDefault(), self.pushButtonCancel.autoDefault(), self.pushButtonApply.autoDefault())
        print(self.pushButtonOk.isDefault(), self.pushButtonCancel.isDefault(), self.pushButtonApply.isDefault())
        print('-' * 50)

app = QApplication(sys.argv)
main = Window()
main.show()
sys.exit(app.exec_())
1
nenad