PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : JFrame->KeyEvent + MousePosition Abfragen?



Matflasch
17-01-2005, 14:39
Hi.

kaum ist das erste Problem behoben, ist schon das nächste da.

Ich habe einen JFrame/JDialog. Ich will nun beim drücken von z.B. STRG+F9, dass ich dann mit getComponentAt(int x, int y) die Component abfragen kann. Im prinzip recht simpel.

Erstes Problem ist nur, dass der KeyListener nicht wirklich so funktioniert, wie ich es mir gedacht habe. Wenn ich über dem LayeredPane vom JFrame bin, dann registriert er den Tastendruck ja wohl, sobald ich aber über der Table bin, macht er das nichtmehr.
Ich will aber nicht jede Component mit einem Listener belegen, dann bring mit das getComponentAt(x,y) ja auch nix mehr.
Was ich möchte ist eigentlich, dass ich, egal wo im JFrame (also von der MausPosition her gesehen), solange der Frame aktiv ist, die TastenKombi drücken kann und dann möchte ich halt abfragen, ob Control-down ist, ob F9 gedrückt wurde und dann die X/Y-Position von der Maus. Damit möchte ich dann getComponentAt(x,y) aufrufen und diese in dem Component-Tree (Thread weiter unten) dann selektieren. Das Selektieren etc ist kein Problem. Nur die TastenKombi zu prüfen und gleichzeitig die MausPosition zu bekommen, das ist mein Problem.

Ansatzweise habe ich folgendes:



final ActionListener listener = new ActionListener() {
public final void actionPerformed(final ActionEvent event) {
System.out.println("Key typed.. " + " " + getX() + "x" + getY());
}
};

final KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_F9, 0, true);

getRootPane().registerKeyboardAction(listener, keyStroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);


Wenn ich nun F9 drücke, dann wird das, was in der ActionPerformed-Methode steht, ausgeführt. getX() und getY() sind allerdings nicht die Maus-Werte, denn diese sind immer gleich. Ausserdem ist es ja im moment nur F9, ohne Control.

Kann mir da jemand helfen?

TIA && Mfg, Matflasch

gaansch
17-01-2005, 16:13
Hi,

was ist denn, wenn der ActionListener gleichzeitig MouseMotionListener des JFrames wäre und so permanent mit der aktuellen Position der Maus versorgt wird. Wenn dann die Taste gedrückt werden würde, wüsste der ActionListener die aktuelle Position der Maus.

Denke, dass es so klappen könnte.

Gruss
Sebastian

Sym
17-01-2005, 18:45
Hi,

getX(), bzw. getY() gibt die Fenster-Werte zurück. Du muss schon die Werte, die Dir das Event zurückgibt nutzen.

Dann solltest Du auch ein MouseEvent nutzen und nicht nur das ActionEvent. Da gibt es dann auch die richtigen Funktionen.

Matflasch
17-01-2005, 20:22
Kann man den ActionListener denn gleichzeitig mit dem MouseMotionListener 'belegen'? Habe beim stöbern gelesen, dass das nicht gehen soll...?

Dass getX() und getY() einfach so verwendet die Fensterposition zurück liefert, habe ich auch noch rausgefunden ;)
Das Problem ist nur, dass mir das KeyEvent die X und Y-Position der Maus ja leider nicht zurück liefern, daher bräuchte ich eine Kombination aus KeyEvent und MouseListener, damit ich beides kombiniert nutzen kann, nur wie gesagt habe ich gelesen, dass das nicht so einfach gehen soll. Bei der Suche bin ich dann auch auf die Lösung gefunden, die ich gepostet habe, allerdings bin ich damit nicht glücklich, da mir die X/Y-Position der Maus fehlt, um getComponentAt(x,y) anwenden zu können :/

Ich werde morgen mal versuchen, die beiden irgendwie zu kombinieren...

Falls jemand sowas schonmal gemacht hat und mir direkt ne Lösung sagen kann, wäre das nicht schlecht ;)

Mfg, Matflasch

Sym
17-01-2005, 20:32
Hi,

Du musst einen MouseListener (oder MouseAdapter) implementieren. Dort kannst Du das MouseEvent abfangen. So sollte das klappen.

Matflasch
17-01-2005, 20:44
Jo das hatte ich auch gemacht bei dem JFrame, allerdings brauche ich ja die Kombination aus KeyEvent und MouseListener :/

Beim drücken von STRG+F9 will ich ja die Mouse-Position abfragen, das geht ja auch nicht mit dem MouseListener alleine.
Ausgelöst werden soll das Event eigentlich nur durch drücken von STRG+F9. Dann will ich halt die Component haben, die gerade unter der Maus liegt.
Die Component selbst soll nicht angeklickt werden oder so, das macht mir das ganze Problem eigentlich nur.

Kann man in einem solchen Listener denn beides Kombinieren?
Weil das Problem mit dem KeyEvent ist ja auch, dass dann der Focus auf dem JFrame sein muss, und wenn der Focus grad bei der Table ist, dann registriert er das KeyEvent ja nicht wirklich. Habe da heut schon voll viel mit rumprobiert, ohne erfolg.. :(

Das einzige, was geklappt hat bisher, war mit dem KeyStroke. Den müsste ich irgendwie mit dem MouseListener verbinden.

Ich werde das morgen früh einfach nochmal ausprobieren, irgendwie muss das ja gehen :D

Sym
17-01-2005, 21:06
So schwer ist das doch nicht.

Du kannst doch in einem Boolean speichern, ob die Maus im Frame ist, oder eben nicht. Immer wenn Du mit der Maus rausgehst, wird der Wert auf false gesetzt. Wenn Du wieder das Frame "enterst", wird gewechselt.

Und im ActionListener greifst Du darauf zu.

gaansch
17-01-2005, 22:58
Also ich würde einfach eine neue Klasse implementieren, die sowohl ActionListener als auch MouseListener realisiert. Und diese neue Klasse meldest du dann als Listener an der entsprechenden Komponente an.

Ich glaub mit der anonymen Klasse bekommst du das nicht hin, MouseMotionListener und ActionListener zu erzeugen.

Also irgendwas wir:




public class FrameAction implements MouseMotionListener, ActionListener {

private int xWert;
private int ywert;

public void mouseDragged(MouseEvent e) {
}

public void mouseMoved(MouseEvent e) {

this.xWert = e.getX();
this.yWert = e.getY();
}

public void actionPerformed(ActionEvent e) {

//Aufruf der Methode, die die Kompoente ermittelt.
}
}



Übernehme keine Garantie, dass da auch wirklich so funktioniert, aber ich glaub schon, dass es das so tun sollte.

Gruss
Sebastian

Matflasch
18-01-2005, 10:23
Danke für die Antworten zwischendurch mal :D

Also ich habe mir nun eine eigene Klasse erstellt, die MouseMotionListener, ActionListener, KeyListener, MouseListener implementiert.
Damit kann ich zwar die entsprechenden Listener setzen bei dem Frame, allerdings klappt das ganze nicht über der JTable. Wahrscheinlich muss ich dann jeder Component den Listener bekannt machen, richtig?
Das ist eigentlich das, was ich nicht wollte.

Bzw. Ich nutze den Listener nun mit dem KeyStroke (oben) zusammen. Somit wird mitlerweile bei STRG+F9 erkannt, dass er was tun soll. Führt auch schön die actionPerformed() aus und hat durch die mouseMove() auch die X/Y-Position der Maus. (Ist das nicht unnötige Rechenzeit, bei jeder Mausbewegung die Positionen zu setzen? Sind zwar nur 2 int-Werte, aber... ich bin von sowas eigentlich nicht so der Fan, sehe nur keine andere Möglichkeit...).

Das Problem ist halt noch, dass das ganze nur bei dem LayeredPane dann greift, somit also bei Toolbar, Menuebar, leider aber nicht bei JScrollPane, JTable etc.

Ein weiteres Problem, was mir nun aufgefallen ist, getComponentAt(x,y) liefert leider nur die oberste Component *g*
Ich bräuchte aber die Unterste. ;)

Meine Idee wäre:
Ich habe die Oberste Component. Somit kann ich, wie bei dem JTree, auch alle UnterComponents rausfinden. Die MausPosition habe ich auch, daher könnte ich eine Art Abfrage machen, die testet, ob es in dem Rechteck liegt...:
X-Position, X+WIDTH,
Y-Position, Y+HEIGHT

Ich sehe nur schon das Problem bei JScrollPanes/JTables. Die haben doch die gleichen Koordinaten/Breite/Höhe, oder?

Mfg, Matflasch

Matflasch
18-01-2005, 13:12
Ok,

hab nun alles soweit, mein einziges(, vorerst letztes ;)) Problem ist:

Wie kann ich allen Components den Listener zuweisen, ohne es von Hand zu machen? Bei teilweise 200 Components keine schöne aufgabe... das ganze dann bei X anwendungen...

Ich will dem JFrame/this einfach den Listener zuweisen und dann sollen alle Components im JFrame sich den vom JFrame holen, geht das?

Hier mal meine Listener-Klasse:


public class FrameListener implements MouseMotionListener, ActionListener, KeyListener, MouseListener {

// Besitzer des Listeners
Frame ownerFrame = null;

// Die Component, über der die Maus gerade steht
Component objHoverComponent = null;

// X-Position der Maus
private int intXPosition = 0;

// Y-Position der Maus
private int intYPosition = 0;

/**
* Standardkonstruktur
*
* @param p_Frame
* p_Frame Der Frame wird übergeben, da die getComponentAt(x,y)
* Methode aufgerufen wird. Diese benötigt den Frame, von dem aus
* die Methode aufgerufen werden soll
*/
public FrameListener(Frame p_Frame) {
// ownerFrame setzen
ownerFrame = p_Frame;
}
public void mouseClicked(MouseEvent e) {
// System.out.println("FrameListener -> mouseClicked()");
}
public void mouseEntered(MouseEvent e) {
// System.out.println("FrameListener -> mouseEntered()");
}
public void mouseExited(MouseEvent e) {
// System.out.println("FrameListener -> mouseExited()");
}
public void mousePressed(MouseEvent e) {
// System.out.println("FrameListener -> mousePressed()");
}
public void mouseReleased(MouseEvent e) {
// System.out.println("FrameListener -> mouseReleased()");
}
public void keyPressed(KeyEvent e) {
// System.out.println("FrameListener -> keyPressed()");
}
public void keyReleased(KeyEvent e) {
// System.out.println("FrameListener -> keyReleased()");
}
public void keyTyped(KeyEvent e) {
// System.out.println("FrameListener -> keyTyped()");
}
public void mouseDragged(MouseEvent e) {
// System.out.println("FrameListener -> actionPerformed()");
}
public void mouseMoved(MouseEvent e) {
System.out.println("FrameListener -> mouseMoved()" + e.getX() + "x" + e.getY() + "C:" + e.getComponent());
// Componente sichern, die sich momentan unter der
// Maus befindet
objHoverComponent = e.getComponent();
// X-Position der Maus sichern
this.intXPosition = e.getX();
// Y-Position der Maus sichern
this.intYPosition = e.getY();
}
public void actionPerformed(ActionEvent e) {
getComponent(objHoverComponent);
}
public void getComponent(Component p_Component) {
// Die Component, die als Root-Stamm angezeigt werden soll
Component t_ComponentRoot = ownerFrame.getComponentAt(intXPosition, intYPosition);
// dlgShowAppComponents-Dialog erstellen
dlgShowAppComponents dlgShowAppComponents = new dlgShowAppComponents(ownerFrame, new BO_StartParameter(), t_ComponentRoot, null, p_Component);
// Dialog anzeigen
dlgShowAppComponents.show();
}


Angewendet wird der Listener nun mit:



// Instanz-Variable des Listeners erstellen
final FrameListener objFrameListener = new FrameListener(this);
// KeyStroke erstellen STRG+F9
final KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_F9, InputEvent.CTRL_DOWN_MASK, true);


Folgendes muss ich nun pro Component machen (was ich sehr mühsam finde, wenn es 100-200Components sind...):


// this
this.addMouseMotionListener(objFrameListener);
this.addMouseListener(objFrameListener);
this.addKeyListener(objFrameListener);

addMouseListener kann ich wahrscheinlich zwar auch weg lassen, aber naja.

Es muss doch irgendwie gehen, dass die Components sich die Listener von der übergeordneten Component(JFrame,JDialog) holen, oder ist das unmöglich?

Es wäre schön, wenn die insgesamt 5 Zeilen alles wären, was mich nun zum Ziel bringt :)