2013-04-06 13 views
10

Ich habe eine QDialog mit einer QDialogButtonBox. Die OK und Abbrechen Schaltflächen sind aktiv. Gelegentlich deaktiviere oder verberge ich die OK-Schaltfläche basierend auf dem Status meines Dialogs. Es scheint, egal was ich mache, die Enter-Taste aktiviert immer die OK-Taste. Ich möchte wirklich nicht, dass das passiert. Ich habe versucht:Wie kann ich verhindern, dass die Eingabetaste meinen QDialog schließt (Qt 4.8.1)

  • Einstellung Werks- und autoDefault Eigenschaften auf false jedes Mal, wenn ich zeigen/verstecken/enable/disable/was auch immer die Taste
  • einen Ereignisfilter auf die Schaltfläche OK Installation Schlüsselereignisse abfangen (gedrückt und wieder losgelassen) für die Rückkehr eingeben und Raum
  • auf den Button den Fokus Richtlinieneinstellung NoFocus

und mit allen Kombinationen dieser oben genannten Dinge, nimmt die Enter-Taste noch den Dialog. Hat jemand eine Ahnung, wie man das blockiert? Es scheint so, als ob ich in der Lage wäre, etwas so Einfaches wie dieses zu blockieren?

+0

Können Sie den Post Ereignisfilter Code posten? –

+0

Ist es Ihr eigener Dialog oder Sie sprechen über die Standarddialoge, die Qt bietet? – dtech

+0

Meine Dialogklasse – cppguy

Antwort

7

Die Filterung der Tastendruckereignisse sollte im Dialogfeld selbst erfolgen, da der Code, der die Weiterleitung der Tasten Return und Enter an die Standardschaltfläche behandelt, in QDialog::keyPressEvent liegt.

void Dialog::keyPressEvent(QKeyEvent *evt) 
{ 
    if(evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) 
     return; 
    QDialog::keyPressEvent(evt); 
} 

Oder

theDialog−>installEventFilter(anotherClassObject); 

bool AnotherClass::eventFilter(QObject *obj, QEvent *evt) 
{ 
    if(evt->type() == QEvent::KeyPress) { 
     QKeyEvent *keyEvent = static_cast<QKeyEvent*>(evt); 
     if(keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) 
      return true; // mark the event as handled 
    } 
    return false; 
} 
+0

korrekt positioniert werden, sollte ich das Ereignis ignorieren()? – cppguy

+0

Das hat nicht funktioniert. Ich erhalte keinen keyPressEvent-Aufruf in meiner QDialog-basierten Klasse, wenn Enter gedrückt wird. – cppguy

+2

Sie sollten das Ereignis nicht ignorieren(), aber akzeptieren und nichts tun. Wenn die Abbrechen-Schaltfläche jedoch weiterhin aktiviert ist und den Fokus erhalten kann, wird sie möglicherweise weiterhin mit der Eingabetaste aktiviert und der Dialog geschlossen. – alexisdm

1

QDialog verfügt über einen eigenen Steckplatz accept() genannt. Wenn QDialogButtonBox accepted() (durch Drücken der Eingabetaste oder Ok) ausgibt, wird dieser private Steckplatz aufgerufen. Also versuche sie zu trennen.

disconnect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));

Das ist für mich gearbeitet.

+0

Ich habe diese Verbindung nie explizit eingerichtet und diese Verbindung aus der ui-Datei vor langer Zeit entfernt – cppguy

-1

In PySide (und ich stelle mir PyQt vor) konnte ich die Annahme- und Ablehnungsfunktionen des QDialogs neu definieren.

def custom_accept(): 
    # perform custom actions when you hit open 
    pass 

def custom_reject(): 
    # perform custom actions when you hit cancel 
    pass 

file_dialog = QtGui.QFileDialog(directory=".") 
file_dialog.accept = custom_accept 
file_dialog.reject = custom_reject 

Dies hielt den Dateidialog von Schließ- und gab mir den Zugriff auf die Daten, wenn die ‚ok‘ (nehmen) oder ‚Abbrechen‘ (ablehnen) Funktionen ausgelöst wurden (entweder mit eingeben oder indem Sie die Schaltflächen klicken)

1

Das Problem ist der Ereignisfilter sollte nicht auf der Schaltfläche OK installiert werden.

Wenn Ihre Schaltfläche OK deaktiviert ist, wird das Ereignis enter nicht empfangen. Welches Widget auch immer den Fokus hat. Und wenn sie das Enter-Ereignis nicht akzeptieren, geht QDialog zu accept() selbst.

Zwei Möglichkeiten das Problem zu lösen:

1) Aufschalten QDialog::accept() und rufen QDialog ‚s akzeptieren Methode in der neuen accept Funktion nur, wenn OK aktiviert ist

void MyDialog::accept() { 
    if (okEnabled) { 
     QDialog::accept(); 
    } 
} 

2) Installieren Sie einen Ereignisfilter unter für jedes Widget im Dialogfeld, das die Eingabetaste nicht akzeptiert (Zeilenänderungen) , ...).

würde das Ereignisfilter wie so sein:

class KeyPressEater : public QObject 
{ 
    Q_OBJECT 

protected: 
    bool eventFilter(QObject *obj, QEvent *event); 
}; 

bool KeyPressEater::eventFilter(QObject *obj, QEvent *event) 
{ 
    if (event->type() == QEvent::KeyPress) { 
     QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); 
     bool res = QObject::eventFilter(obj, event); 

     if (keyEvent->key() == Qt::Key_Return) { 
      return true; /* Always accept return */ 
     } else { 
      return res; 
     } 
    } else { 
     // standard event processing 
     return QObject::eventFilter(obj, event); 
    } 
} 

Und in Ihrem Code für jedes Widget im Dialog:

myWidget->installEventFilter(myKeyPressEater); 
1

Wenn Sie auf dem Dialog normale QPushButtons haben dann, wenn die Tasten Haben Sie die AutoDefault und/oder Standard Eigenschaften auf ihnen gesetzt, dann erhalten Sie eine Standard-Taste - was ist die Eingabe-Taste auslöst. In diesem Fall entfernen Sie autoDefault auf den Schaltflächen und drücken Sie die Eingabetaste in einem anderen Widget, um den Dialog nicht mehr zu schließen.

Im Falle einer QDialogButtonBox können Sie wahrscheinlich über die Schaltflächen iterieren, um dieses Zeug in der Ctor Ihres Dialogs auszuschalten. Nicht hier getestet, sollte aber funktionieren. Wenn nicht, dann müssen Sie auch sehen, ob es eine Standardschaltfläche gibt, die auch auf dem QDialog gesetzt wird.

0

Um zu vermeiden, "OK" -Taste oder "Enter" -Taste aus Schließen Dialogfeld: in der XML-Datei ui, entfernen Sie die Verbindung/Slot für akzeptieren/ablehnen. Dann, in Ihrem Code, emit accept() wann und wie nötig;

Beispiel aus ui-Datei, die() -Steckplatz akzeptieren:

<connections> 
    <connection> 

    <sender>products_ButtonBox</sender> 

    <signal>accepted()</signal> 

    <receiver>Products_Dialog</receiver> 
     <slot>accept()</slot> 
     <hints> 
     <hint type="sourcelabel"> 
     <x>248</x> 
     <y>254</y> 
     </hint> 
     <hint type="destinationlabel"> 
     <x>157</x> 
     <y>274</y> 
     </hint>e 
     </hints> 
     </connection> 
Verwandte Themen