Reihenfolge Listeners ändern


#1

Wie kann ich n folgendes invertieren?

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class TestWeg {
    public static void main(String[] args) {
        // Frame
        JFrame myFrame = new JFrame("test");
        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myFrame.setBounds(100, 100, 450, 180);

        myFrame.setVisible(true);

        // Panel
        JPanel myPanel = new JPanel();
        myPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
        myFrame.setContentPane(myPanel);
        myPanel.setLayout(null);

        // Elements
        // -------------------------------------------------------
        JLabel myLabelFN = new JLabel("The Text");
        myPanel.add(myLabelFN);
        myLabelFN.setBounds(25, 28, 76, 14);
        myLabelFN.setVisible(true);

        JTextField myTF = new JTextField();

        myPanel.add(myTF);
        myTF.setBounds(100, 25, 300, 20);
        myTF.setVisible(true);

        myTF.getDocument().addDocumentListener(new DocumentListener() {
                @Override
                public void changedUpdate(DocumentEvent e) {
                    changeIt();
                } // end changedUpdate()

                public void removeUpdate(DocumentEvent e) {
                    changeIt();
                } // end removeUpdate()

                public void insertUpdate(DocumentEvent e) {
                    changeIt();
                } // end insertUpdate()

                public void changeIt() {
                    System.out.println("Erste Änderung");
                } // end changeIt()
            } // end new
        );

        myTF.getDocument().addDocumentListener(new DocumentListener() {
                @Override
                public void changedUpdate(DocumentEvent e) {
                    changeIt();
                } // end changedUpdate()

                public void removeUpdate(DocumentEvent e) {
                    changeIt();
                } // end removeUpdate()

                public void insertUpdate(DocumentEvent e) {
                    changeIt();
                } // end insertUpdate()

                public void changeIt() {
                    System.out.println("Zweite Änderung");
                } // end changeIt()
            } // end new
        );
    } // end main()
} // end TestWeg

#2

Moin,

was genau meinst Du ??
WAS soll wo invertiert werden ???

Ein paar Infos wären schon nett!!
VG Klaus


#3

Hi vlf_freak

schön dass Du mir helfen willst – sorry erstma wegen der verpatzen Codewiedergabe – aber vielleicht kannstes ja einfach kopieren.

Also:
Der Titel sagts ja schon “Reihenfolge der listeners ändern”
Im Quelltext dann, 2 listener, der erste wird aber zuerst aufgerufen — ist bei allen swing-listeners so — macht für mich keinen Sinn und für mein Vorhaben ist das sehr hinderlich — Für mich ist die Frage: ob man die Reihenfolge der Aufrufe umdrehen kann. Würde von allein denken dass der erste Listener zuerst aufgerufen wird – das ist leider nicht so ;-(

Grüße


#4

Moin,
was soll der Code denn genau machen?
Warum zweimal den exakt gleichen Listener am gleichen Textfeld (vom SysOut mal abgesehen) ??
VG Klaus


#5

Hi Klaus – das ist lediglich ein Beispielcode, der das Prinzip vereinfachen soll(es geht letztendlich um das Binding einer Variable - was aber eigentlich gar nichts zur Sache tun)

Grundsätzlich gehe ich als Programmierer davon aus das der erste implementierte Listener auch als erstes ausgeführt wird --> das ist leider nicht so --> siehe funktionierendes Beispiel

//Warum zweimal den exakt gleichen Listener am gleichen Textfeld
Stell Dir vor das ganze ist vererbt und Listener 1 ist Grundfunktionalität - Listener 2 baut jemand der die Komponente verwenden will

Grüße


#6

Mit Listenern ist das so eine Sache, weil die gemultiplexed werden, wobei eigentlich gar keine Reihenfolge festgelegt werden kann, soweit ich weiß.
Den Listener würde ich mit

super.addDocumentListener(myListener);

bei der Klasseninitialisierung übergeben und die Methode in der Klasse überschreiben (nebst “removeDocumentListener()”). Die durch diese Methode geaddeten Listener würde ich dann in einer Liste speichern, die von deinem Listener abgearbeitet wird, sobald er mit den Grundfunktionen durch ist.

Allerdings muss ich dazu sagen, dass mir das spanisch vorkommt, denn Komponenten verändert man nicht über Listener, sondern direkt. Listener sind dann nur dazu da, registrierte Programmabschnitte über diese Änderungen zu informieren, ohne dass Letztere noch etwas daran ändern können sollten.


#7

Man kann was “dengeln”. Aber du solltest

sehr

genau überlegen, ob du das wirklich willst. Warum spielt die Reihenfolge eine Rolle? Man kann oder sollte sich nicht darauf verlassen. Wenn die Reihenfolge eine Rolle spielt, sollte man eine andere Lösung in Betracht ziehen.

Die gedengelte Lösung wäre das hier - nicht schön:

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.Document;

public class TestWeg {
    public static void main(String[] args) {
        // Frame
        JFrame myFrame = new JFrame("test");
        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myFrame.setBounds(100, 100, 450, 180);

        myFrame.setVisible(true);

        // Panel
        JPanel myPanel = new JPanel();
        myPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
        myFrame.setContentPane(myPanel);
        myPanel.setLayout(null);

        // Elements
        // -------------------------------------------------------
        JLabel myLabelFN = new JLabel("The Text");
        myPanel.add(myLabelFN);
        myLabelFN.setBounds(25, 28, 76, 14);
        myLabelFN.setVisible(true);

        JTextField myTF = new JTextField();

        myPanel.add(myTF);
        myTF.setBounds(100, 25, 300, 20);
        myTF.setVisible(true);

        addAsFirst(myTF.getDocument(), new DocumentListener() {
                @Override
                public void changedUpdate(DocumentEvent e) {
                    changeIt();
                } // end changedUpdate()

                public void removeUpdate(DocumentEvent e) {
                    changeIt();
                } // end removeUpdate()

                public void insertUpdate(DocumentEvent e) {
                    changeIt();
                } // end insertUpdate()

                public void changeIt() {
                    System.out.println("Erste Änderung");
                } // end changeIt()
            } // end new
        );

        addAsFirst(myTF.getDocument(), new DocumentListener() {
                @Override
                public void changedUpdate(DocumentEvent e) {
                    changeIt();
                } // end changedUpdate()

                public void removeUpdate(DocumentEvent e) {
                    changeIt();
                } // end removeUpdate()

                public void insertUpdate(DocumentEvent e) {
                    changeIt();
                } // end insertUpdate()

                public void changeIt() {
                    System.out.println("Zweite Änderung");
                } // end changeIt()
            } // end new
        );
    } // end main()
    
    private static void addAsFirst(
        Document document, DocumentListener documentListener)
    {
        if (document instanceof AbstractDocument)
        {
            AbstractDocument abstractDocument = (AbstractDocument)document;
            DocumentListener[] oldListeners = 
                abstractDocument.getListeners(DocumentListener.class);
            for (DocumentListener oldListener : oldListeners)
            {
                document.removeDocumentListener(oldListener);
            }
            document.addDocumentListener(documentListener);
            for (DocumentListener oldListener : oldListeners)
            {
                document.addDocumentListener(oldListener);
            }
        }
    }
} // end TestWeg

#8

Wenn der zweite Listener vom ersten Listener abhängt, dann füge doch stattdessen lieber dem ersten Listener einen Listener hinzu.


#9

Mir ist nicht ganz klar was du da tatsächlich vorhast zu machen. Das naheliegenste was ich mir vorstellen könnte wäre sowas wie ein einfacher Greeter:

image

Listener 1 würde Hello Karl schreiben und listener 2 soll dann irgendwas darauf basierend machen. Angenommen das ganze schaut klassentechnisch so aus:

GreeterPanel
|- TextInput (value=Karl)
|- Label (value=Hello Karl)

Dann sollte der zweite listener eher am GreeterPanel angebracht werden, der bei einer “Begrüßungsänderung” getriggert wird.

Denn wie schon gesagt: die Reihenfolge der Listener sollte egal sein. Vor allem sollten die Listener unabhängig voneinander funktionieren.

Dein Vorhaben klingt eher als ob du in deiner Architektur einen Fehler drin hast.


#10

Also, ich denke auch, dass deine Architektur daneben ist, aber falls du sowas wirklich brauchst, wäre es auch eine Möglichkeit, einen “Über-Listener” zu schreiben, der deine Listener in Reihenfolge aufnehmen kann:

public class MasterListener implements DocumentListener {

      private List<DocumentListener> subListeners = new ArrayList<>();
      
      public void addListener(DocumentListener listener) { subListeners.add(listener); }

      @Override    
      public void changeUpdate(DocumentEvent e) {
           subListeners.forEach(l -> l.changeUpdate(e)); 
      }        
      ...
}

Natürlich musst du dann deine Listener dort und nur dort registrieren. Aber noch mal zur Warnung:


#11

Warum die Warnung? Das ist ziemlich genau das, was ich bei

im Kopf hatte. Das gepostete ist halt die “generischste” Form, d.h. das public class sollte in der Praxis bestenfalls ein class sein. Aber ansonsten: Wenn man die Reihenfolge berücksichtigen muss, dann muss irgendeine übergeordnete Instanz dafür sorgen, dass sie berücksichtigt wird


#12

Hi

Danke für die viele Überlegungen - ich höhre schon raus das es kein guter aufbau ist - und Ihr habt recht!

//Wenn die Reihenfolge eine Rolle spielt, sollte man eine andere Lösung in Betracht ziehen.

So siehts aus!

@Tomatensalat:
//Das naheliegenste was ich mir vorstellen könnte wäre sowas wie ein einfacher Greeter:

Ja sowa
ja sowas ähnliches — ein einfaches Binding für Swing :wink: