PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Java] AWT Key Events


Monger
2005-12-05, 14:07:01
Hallo,

es ist wiedermal so weit, ich steh wie ein Ochs vorm Berg.

Ich schreibe gerade an einer kleinen Java3D Klasse, die ein Ereignis verarbeitet. Dieses Ereignis akzeptiert u.a. AWT Key Events, d.h. wenn ich eine bestimmte Taste drücke, passiert irgendwas.

Laut Beispiel sieht das derzeit so aus:


this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));


Das funktioniert auch ganz wunderbar. Jetzt möchte ich aber, dass nicht bei jedem beliebigen Tastendruck ausgelöst wird, sondern nur wenn ich z.B. die Taste "w" drücke. Laut API müsste das eigentlich so aussehen:


this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.VK_W));

Das funktioniert aber nicht, das Ereignis wird nicht ausgelöst. Was mache ich falsch? Auch keine andere spezifische Tastenkombination scheint zu funktionieren. Kennt sich hier jemand mit AWT Events aus?

mithrandir
2005-12-05, 14:38:38
Die VK_-Konstanten der Klasse KeyEvent repräsentieren eine Taste, die gedrückt wurde, keinen Event. Der KeyEvent hat eine Methode, die den Tastencode zurückgibt. Diesen kann man dann mit einer der Konstanten vergleichen, z.B. so:

if ( myKeyEvent.getKeyCode() == KeyEvent.VK_W )
{
// do something
}

Einfach eine Konstanten für einen Tastencode dem Konstruktor zu übergehen geht also sicher nicht. Wie das in Bezug mit WakeupOnAWTEvent funktioniert, weiß ich nicht. Ich vermute einmal, dass man generell einen KeyListener implementieren muss.

bye, Peter

f.reischl
2005-12-05, 14:44:26
Die VK_-Konstanten der Klasse KeyEvent repräsentieren eine Taste, die gedrückt wurde, keinen Event. Der KeyEvent hat eine Methode, die den Tastencode zurückgibt. Diesen kann man dann mit einer der Konstanten vergleichen, z.B. so:

if ( myKeyEvent.getKeyCode() == KeyEvent.VK_W )
{
// do something
}

Einfach eine Konstanten für einen Tastencode dem Konstruktor zu übergehen geht also sicher nicht. Wie das in Bezug mit WakeupOnAWTEvent funktioniert, weiß ich nicht. Ich vermute einmal, dass man generell einen KeyListener implementieren muss.

bye, Peter
Hmmm...
KeyEvent.KEY_PRESSED is ein Integer
und
KeyEvent.VK_W auch, müsste deshalb funktionieren.
Gehts mit den F-Tasten? Bei mir geht z.B. F9 oder F10 nicht, aber die anderen schon...

Monger
2005-12-05, 14:58:17
Einfach eine Konstanten für einen Tastencode dem Konstruktor zu übergehen geht also sicher nicht. Wie das in Bezug mit WakeupOnAWTEvent funktioniert, weiß ich nicht. Ich vermute einmal, dass man generell einen KeyListener implementieren muss.

bye, Peter

Es geht, definitiv. Schon deshalb, weil ich mir mein Event selbst bastele:


public class RotatingBehavior extends Behavior {

private Transform3D dummy;
private TransformGroup reactionTG;
private double angle = 0.0;

public RotatingBehavior(TransformGroup targetTG){
this.reactionTG = targetTG;
dummy = new Transform3D();
}

@Override
public void initialize() {
this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
}

@Override
public void processStimulus(Enumeration arg0) {
angle+= 0.1;
dummy.rotZ(angle);
reactionTG.setTransform(dummy);
this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
}

}


Wie du siehst, habe ich gar keinen direkten Zugriff auf ein KeyEvent, sondern registriere mich gewissermaßen nur als EventListener. Und der Konstruktor von WakeUpOnAWTEvent akzeptiert nunmal die Konstanten für das Tastaturschema.

Aber so in die Tiefe wollte ich gar nicht gehen. Ich habe ein "wakeUpOn", was auf ein Ereignis reagiert, und auf ein anderes nicht. Warum?

Übrigens habe ich auch andere Tasten durchprobiert, inklusive F-Tasten, Zahlen und Pfeile. Leider ohne Ergebnis...
Könnte es damit zusammenhägen, dass ich auf einem Laptop arbeite? Ist das Tastaturschema dort anders als auf einem "normalen" PC?

mithrandir
2005-12-05, 15:24:40
Dere!

WakeupOnAWTEvent(int AWTId)
Constructs a new WakeupOnAWTEvent object that informs the Java 3D scheduler to wake up the specified Behavior object whenever the specified AWT event occurs.
Ein Tastencode ist keine AWTId.

Du müsstest IMO einfach in deiner Methode processStimulus den eigentlichen Event abfragen:


public void processStimulus(Enumeration criteria)
{
AWTEvent[] array = kriterium.getAWTEvent();
if ( array[0] instanceof KeyEvent )
{
int code = ((KeyEvent)array[0]).getKeyCode();
if ( code == KeyEvent.VK_W )
{
// Juhu, W gedrueckt
}
else
{
// andere Taste gedrueckt
}
}
}

Monger
2005-12-06, 10:50:40
...
public void processStimulus(Enumeration criteria)
{
AWTEvent[] array = kriterium.getAWTEvent();
if ( array[0] instanceof KeyEvent )
{...


Wo soll ich denn das "kriterium" herkriegen? Bzw. ich habe nichts, was eine Methode "getAWTEvent" hätte. Oder soll ich einfach raten, dass in der Enumeration schon der richtige Typ drin steckt?

Mein Problem ist ja gerade, dass ich keinen unmittelbaren Zugriff auf die AWT Ereignisse habe.

mithrandir
2005-12-06, 11:29:25
Dere!

public java.awt.AWTEvent[] getAWTEvent()

Retrieves the array of consecutive AWT event that triggered this wakeup. A value of null implies that this event was not the trigger for the behavior wakeup.

Returns:
either null (if not resposible for wakeup) or the array of AWTEvents responsible for the wakeup.
Das ist eine Methoder der Klasse WakeupOnAWTEvent.

bye, Peter

Monger
2005-12-06, 14:50:58
Ich hab jetzt mal ein bißchen durchdebuggt, und das Problem liegt ganz woanders: Die Key Events stimmen einfach nicht mit den Nummern überein!

@mithrandir: Wenn man sich so durchboxt wie du das vorgeschlagen hast, landet man nämlich letztendlich tatsächlich wieder auf einer Zahl - weil nunmal ein Key Event anhand seiner Nummer identifiziert wird. Und die stimmt nicht.

Muss ich vielleicht irgendwie ein Tastaturschema definieren oder so, damit es wieder passt?

mithrandir
2005-12-06, 14:59:55
Warum nicht einfach nach diesem Tutorial machen, dort geht's ja auch:
http://72.14.207.104/search?q=cache:BIwWb-9ff9YJ:www.fhs-hagenberg.ac.at/staff/haller/mmp5_20012002/07java3d_1.pdf+WakeupOnAWTEvent+KeyEvent&hl=de

Übrigens: Das Problem liegt schon dort, wo ich es sehe. Man kann Key-Codes und AWTEvent-Codes nicht einfach auswechseln.

Monger
2005-12-06, 16:11:17
So, jetzt funktionierts. Du hattest natürlich völlig recht, ich stand da nur echt auf dem Schlauch...

Das folgende ist jetzt ein Verhaltensknoten, mit dem man einen anderen Knoten mit den WASD Tasten um die X- und Y-Achse rotieren lassen kann. Wie ich festgestellt habe, ist untenstehende For Schleife für die AWT Events sinnlos, weil sowieso immer nur ein einziges gleichzeitig ansteht ?!?
Tastenkombinationen kann ich also derzeit nicht decodieren, so dass er z.B. nach links oben rotiert.
Könnte es sein, dass ich dafür Threads erzeugen muss, weil die Bearbeitung des aktuellen Threads alle weiteren Tastatureingaben blockiert?

public class RotatingBehavior extends Behavior {

private Transform3D zTransform;
private Transform3D yTransform;
private TransformGroup reactionTG;
private double zAngle = 0.0;
private double yAngle = 0.0;
private WakeupOnAWTEvent event;

public RotatingBehavior(TransformGroup targetTG){
this.reactionTG = targetTG;
zTransform = new Transform3D();
yTransform = new Transform3D();
}

@Override
public void initialize() {
this.wakeupOn(event = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
}

public void processStimulus(Enumeration criteria)
{
AWTEvent[] array = event.getAWTEvent();
for(int i = 0; i < array.length; i++){
Object item = array[i];
if ( item instanceof KeyEvent ){
int code = ((KeyEvent)array[i]).getKeyCode();
if ( code == KeyEvent.VK_W )
{
zAngle+= 0.1;
}
if ( code == KeyEvent.VK_S){
zAngle-= 0.1;
}
if ( code == KeyEvent.VK_A){
yAngle-= 0.1;
}
if (code == KeyEvent.VK_D){
yAngle += 0.1;
}
zTransform.rotZ(zAngle);
yTransform.rotY(yAngle);
zTransform.mul(yTransform);
reactionTG.setTransform(zTransform);
}
}
this.wakeupOn(event = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
}
}