Swing Krieg die Krise mit dem AWTEventListener

Schesam

Bekanntes Mitglied
Hallo

Erstmal der code:

Java:
 Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
            @Override
            public void eventDispatched(AWTEvent event) {
                //                if (event.getSource() != musikDateienTabelle && event.getSource() != scrollPane) {
                //                    System.out.println("Nicht die Tabelle: " + event.getSource());
                //                }
                Object src = event.getSource();
                synchronized (getTreeLock()) {
                    for (Component c : Gui.this.getContentPane().getComponents()) {
                        if ((c == src && c != volumeSlider && c != scrollPane) || src == Gui.this) {
                            System.out.println("Source: " + src);
//                        } else {
//                            System.out.println("Component: " + c);
                        }
                    }
                }
//                if (src == Gui.this) {
//                    System.out.println("OMFG");
//                }
            }
        }, AWTEvent.MOUSE_WHEEL_EVENT_MASK);

Probiere jetz ne halbe Stunde schon rum und kriegs nicht hin... Ich möchte meinem ganzen Frame nen Listener hinzufügen, AU?ER meiner JTable und dem Slider selbst. Dieser soll einfach den Wert meines Sliders ändern (Ist ne Lautstärkeregelung).

Aber ich kriegs nicht hin, das er ihn nur auf meinen Komponenten UND der freien Fläche ausführt. An der if Konstellation seht ihr meinen letzten Versuch. hatte es davor ohne das oder und er Klammer Und verknüpft. Dann aht er es auf allen Komponenten, aber nciht der freien Fläche ausgeführt... Weiß wer ne Lösung?
 

Jardcore

Top Contributor
Die Frage ist, wieso möchtest du einen Listener auf dem Frame? Und nächste Frage wieso der AWTEventListener? Die API sagt dazu: "Most applications should never use this class".

Vielleicht kannst du nochmal genauer Beschreiben was dein Ziel ist, dann könnte man eine einfacherer Variante finden dein Problem zu lösen.
 

Joose

Top Contributor
Vielleicht kannst du nochmal genauer Beschreiben was dein Ziel ist, dann könnte man eine einfacherer Variante finden dein Problem zu lösen.
So wie ich es seinem Beitrag entnommen habe will er egal wo der Fokus in der Anwendung liegt (ob Fenster, Button, Textfield, ...) mittels diesem Listener die Lautstärke regeln können.
Davon ausgenommen ist ein JTable bzw. ein JSlider.
 

Schesam

Bekanntes Mitglied
Vergessen zu erwähnen: @Jardcore: Das ist richtig, das die meisten sie nciht verwenden sollen. Aber nur weil in den meisten Fällen dafür keine Notwendigkeit besteht. Aber bei mir will ich halt überall nen listener haben und dafür ist er halt da. In meinem speziellen Fall müssen halt 2 spezielle Komponenten ausgelassen werden und das ist mein Problem grad
 

Meniskusschaden

Top Contributor
Ich glaube, ich habe das Problem noch nicht verstanden. Eigentlich müsste es doch genügen, einfach aus der Listener-Methode zu springen, falls sie von einer zu ignorierenden Komponente ausgelöst wurde:
Java:
@Override
public void eventDispatched(AWTEvent event) {
    if (event.getSource()==ignoredComponent) {
        return;
    }
    doSomething();
}
 

Schesam

Bekanntes Mitglied
Das funktioniert so aber nicht, um dir das zu demonstrieren hab ich den Inhalt des Listeners so umgeändert:
Java:
if (src == scrollPane || src == volumeSlider) {
                    System.out.println(src);
                } else {
                    System.out.println("NO");
                }
SO, scrolle ich nun in meiner Table gibt er das aus:
Java:
javax.swing.JScrollPane[scrollPane,6,6,726x413,layout=javax.swing.ScrollPaneLayout$UIResource,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@5f6a7ab4,flags=320,maximumSize=,minimumSize=,preferredSize=,columnHeader=javax.swing.JViewport[,3,3,720x22,layout=javax.swing.ViewportLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=25165832,maximumSize=,minimumSize=,preferredSize=,isViewSizeSet=true,lastPaintPosition=java.awt.Point[x=0,y=0],scrollUnderway=false],horizontalScrollBar=javax.swing.JScrollPane$ScrollBar[,0,0,0x0,hidden,layout=javax.swing.plaf.synth.SynthScrollBarUI,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@12a06f09,flags=4194632,maximumSize=,minimumSize=,preferredSize=,blockIncrement=10,orientation=HORIZONTAL,unitIncrement=1],horizontalScrollBarPolicy=HORIZONTAL_SCROLLBAR_AS_NEEDED,lowerLeft=,lowerRight=,rowHeader=,upperLeft=,upperRight=javax.swing.plaf.nimbus.TableScrollPaneCorner[,0,3,0x22,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=],verticalScrollBar=javax.swing.JScrollPane$ScrollBar[,708,25,15x385,hidden,layout=javax.swing.plaf.synth.SynthScrollBarUI,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@39e93ff1,flags=4194632,maximumSize=,minimumSize=,preferredSize=,blockIncrement=10,orientation=VERTICAL,unitIncrement=1],verticalScrollBarPolicy=VERTICAL_SCROLLBAR_NEVER,viewport=javax.swing.JViewport[,3,25,720x385,layout=javax.swing.ViewportLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=25165832,maximumSize=,minimumSize=,preferredSize=,isViewSizeSet=true,lastPaintPosition=java.awt.Point[x=0,y=0],scrollUnderway=false],viewportBorder=javax.swing.plaf.synth.SynthScrollPaneUI$ViewportBorder@32715a87]
NO

Das Event wird also 2x dispatched und 1x kommts immer durch

Scrolle ich woanders (Freie Fläche als Beispiel) gibt er das aus:
Java:
NO

Jetz wird also nur 1x dispatched. Heißt für mich es wird immer pro Komponent dispatched. Bin ich in der freien Fläche, nur 1x für das Frame. Bin ich auf ner Komponenten 1x fürs Frame und 1x für die Komponente. Das ist das Problem das ich habe, das selbst auf ner komponenten fürs Frame dispatched wird
 

Meniskusschaden

Top Contributor
Habe das Problem jetzt verstanden, weiß für AWTEventListener aber leider keine Lösung. Vielleicht kannst du stattdessen einfach die normalen Swing-Events nutzen, indem du den Listener für den Frame und die zu ignorierenden Komponenten registrierst:
Java:
frame.addMouseWheelListener(this);
scrollPane.addMouseWheelListener(this);
Dann kannst du die Doppelaufrufe mit consume() unterbinden:
Java:
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
    e.consume();
    if (e.getSource()==scrollPane) {
        return;
    }
    System.out.println("Source: " + e.getSource() + " Event: " + e);
}
 

Meniskusschaden

Top Contributor
Für den Ansatz über AWTEventListener könnte man vielleicht noch eine ziemlich häßliche Lösung testen, indem man sich bei der Verarbeitung des ersten Ereignisses merkt, dass das nächste Ereignis ignoriert werden soll:
Java:
@Override
public void eventDispatched(AWTEvent event) {
    if (ignoreNextEvent) {
        ignoreNextEvent = false;
        return;
    }
    if (event.getSource()==scrollPane) {
        ignoreNextEvent = true;
        return;
    }
    System.out.println("Source: " + event.getSource() + "\nEvent: " + event);
}
Mir kommt das aber etwas wackelig vor. Ich habe die Information hier einfach in der boolean-Variable ignoreNextEvent gespeichert. Es würde mir besser gefallen, wenn man irgendwie direkt vergleichen könnte, ob die beiden Ereignisse aus derselben Aktion stammen. Dafür habe ich aber keinen Weg gefunden. Das zweite Ereignis scheint auch erst nach Verarbeitung des ersten in die Queue gestellt zu werden, denn zu diesem Zeitpunkt findet man es noch nicht in der Queue und kann es auch nicht mittelsToolkit.getDefaultToolkit().getSystemEventQueue().getNextEvent();entfernen.
 

Ähnliche Java Themen


Oben