Mehrere Tasteneingaben gleichzeitig verwerten

Alles rund um die Programmierung mit Qt
Antworten
LangerJan
Beiträge: 9
Registriert: 14. Juli 2007 23:34

Mehrere Tasteneingaben gleichzeitig verwerten

Beitrag von LangerJan »

Moin zusammen!

Ich bin neu hier, hab die Suchfunktion schon zu meinem Thema bemüht, aber nichts Entsprechendes gefunden. Sollte ich die Lösung wie den Wald vor lauter Bäumen nicht sehen, bitte ich um einen dezenten Hinweis :)

Ich habe da nun ein Widget, dass KeyEvents erhält. Auf einer 2D-Spielfläche (Eine QGraphicsScene) soll ein Raumschiff auf Tastendruck (Key_Left, Right, etc) rotiert werden und mit Schub/Rückschub bewegt werden.

So weit so gut. Diese Dinge klappen aber nur einzeln. Ich kann entweder rotieren oder Gas geben, aber nicht beides gleichzeitig. Halte ich bspw. "Links" gedrückt und drücke dann "Geradeaus", wird die Links-Operation abgebrochen und die Geradeaus-Operation beginnt.

Gibt es irgendeine Möglichkeit, dieses Problem zu umschiffen? Eventuell gibts ja bereits spezielle Methoden, die ich noch nicht kenne ;)

Wenn ihr noch weitere Infos braucht, um mir zu helfen, fragt mich.

Besten Dank im Voraus!

Ciao

Jan
Zuletzt geändert von LangerJan am 25. Juli 2007 17:32, insgesamt 2-mal geändert.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Es gibt für (fast?) jede Taste ein keyPressEvent und ein keyReleaseEvent. Die ReleaseEvents kommen immer erst beim loslassen der Taste und nicht wenn eine andere gedrückt wurde. Also ist es Sache deiner Anwendung, dies richtig auszuwerten.
LangerJan
Beiträge: 9
Registriert: 14. Juli 2007 23:34

Beitrag von LangerJan »

Moin upsala, danke für deine Antwort :)

Das KeyReleaseEvent habe ich schon ausprobiert. Das Problem ist wohl:

Ich halte eine Taste gedrückt. Dieses "gedrückt halten" wird dann (betriebssystemabhängig) nach einer gewissen Zeit als schnell hintereinanderfolgendes Drücken (quasi "Dauerfeuer") interpretiert.

Ich möchte jetzt nur ungern diese Funktion in meinem OS abschalten. Kann man das nicht programmintern abfangen?
Volker
Beiträge: 343
Registriert: 30. Juni 2005 05:27

Beitrag von Volker »

Schon auf die Idee gekommen einfach ein Array von bool Werten anzulegen und je nach Tastencode den entsprechenden Eintrag im Array auf true setzen wenn die Taste gedrückt wurde und auf false im Fall des Release Events?
Dann brauchst Du in der Update Loop deines Spiels nur noch das Array auswerten.
Bitte seid so nett und ändert den Titel von Beiträgen die gelöst wurden, auf [gelöst] Beitragstitel
LangerJan
Beiträge: 9
Registriert: 14. Juli 2007 23:34

Beitrag von LangerJan »

Wie gesagt, das ReleaseEvent wird bei "Dauerfeuer" gleich mit ausgelöst. Die Idee habe ich schon aus verschiedenen Quellen gehört und im englischsprachigem QT Forum habe ich nun auch eine (hoffentlich) passende Lösung gefunden:

Der Code stammt aus dem aktuellen QT Asteriods-Port und diese bool'sche Funktion habe ich noch nicht gekannt;

Code: Alles auswählen

 void KAstTopLevel::keyPressEvent( QKeyEvent *event )
 {
     if ( event->isAutoRepeat() || !actions.contains( event->key() ) )
     {
         event->ignore();
         return;
     }
[...]
Ich werde das, in Kombination mit einem ReleaseEvent mal ausprobieren.

Danke für eure Hilfe! Wenn das hier geklappt hat, setze ich den Thread auf "gelöst" :)
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Das Betriebssystem sendet, bei gedrückt gehaltener Taste abwechselnd keyPress und keyRelease? Tja, dann läßt sich da programmtechnisch mit vernünftigen Aufwand nicht viel machen.
LangerJan
Beiträge: 9
Registriert: 14. Juli 2007 23:34

Beitrag von LangerJan »

upsala hat geschrieben:Das Betriebssystem sendet, bei gedrückt gehaltener Taste abwechselnd keyPress und keyRelease? Tja, dann läßt sich da programmtechnisch mit vernünftigen Aufwand nicht viel machen.
Ja, es sendet bei gedrückt gehaltener Taste die Tasteneingabe mehrfach.

Beispiel: "s" gedrückt halten, ergibt: ssssssssssssssssssssssssssssssss

Da ist jedes "s" Signal ein KeyPress und ein KeyRelease.

Ich probiere jetzt erstmal obiges aus.
LangerJan
Beiträge: 9
Registriert: 14. Juli 2007 23:34

Beitrag von LangerJan »

okay, hier die Lösung, wie ich sie implementiert habe:

Es gibt ein Array aus bool'schen Werte namens Tastenspeicher.

Code: Alles auswählen

void Hilfsfenster::keyPressEvent(QKeyEvent* event){
        if(event->isAutoRepeat()){
          event->ignore();
          return;
        };
        switch (event->key()) {
	        case Qt::Key_Left: this->Tastenspeicher[0] = TRUE; break;
		case Qt::Key_Right:this->Tastenspeicher[1] = TRUE; break;
		case Qt::Key_Down: this->Tastenspeicher[2] = TRUE; break;
		case Qt::Key_Up:   this->Tastenspeicher[3] = TRUE; break;
		
		case Qt::Key_Control: this->Tastenspeicher[4] = TRUE; break;
        
		default: QWidget::keyPressEvent(event);
         };
};
Eine separate Funktion ruft mit Hilfe eines QTimers regelmäßig das Array auf und "drückt" die "Tasten" manuell. Die KeyRelease Funktion ist identisch mit der Press Funktion, nur, dass die Werte wieder auf FALSE gesetzt werden.

Danke an alle!
LangerJan
Beiträge: 9
Registriert: 14. Juli 2007 23:34

Beitrag von LangerJan »

Jetzt ist doch noch ein Problem aufgetreten und ich weiß es mir nicht so recht zu erklären.

Angenommen, jemand hält wahllos 4 (von mir mit Funktionen belegte) Buchstabentasten gedrückt. Dann kommt kein anderes KeyEvent mehr durch. Ich kann dann jede beliebige Taste drücken, aber deren Funktion wird nicht mehr ausgeführt.

Wenn ich aber die vier Pfeiltasten gleichzeitig drücke, sind noch andere KeyPressEvents möglich.

Weiß dazu jemand Rat, wie ich alle KeyPressEvents durchbekomme?
Antworten