Klassenübergreifendes Eventhandling, wie gestalten?

raptorrs

Aktives Mitglied
Moin zusammen!

Seit Jahren schlage ich mich einem für mich ungelösten Problem herum, jetzt bin ich es satt.

Wie teile ich einer zweiten Klasse (Reaktor) mit, dass in der ersten Klasse (Producer) ein Event stattfand? Wenn ich eine neue Instanz der zweiten Klasse erzeugen könnte, wäre die Angelegenheit trivial, das geht aber hier nicht.

Ich habe weiss der Teufel an dem Problem herumgedoktort, Action-Events im Konstruktor übergeben, Listener implementiert usw. Nichts half. Um das Problem unvoreingenommen darzustellen, ist hier gar kein Eventhandling für das Problem angegeben.

Ich habe zur Verdeutlichung ein simples Codebeispiel angehängt. Der Sachverhalt ist der, dass in der Producer-Klasse diverse Voreinstellungen vorgenommen werden. Nach Abschicken dieser Daten soll sich die Darstellung der weiteren GUI's entsprechend ändern.

Das TabPane:

Java:
package eventsueberklassen;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

public class EventsUeberKlassen extends JFrame
{
    private JPanel basePanel;
    private JTabbedPane tabPane;
    private Producer producer;
    private Reactor reactor;
    
    public EventsUeberKlassen() 
    {
        initComponents();
    }

    private void initComponents() 
    {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setTitle("Events über Klassen");
        
        basePanel = new JPanel();
        tabPane = new javax.swing.JTabbedPane();
        producer = new Producer();
        reactor = new Reactor(producer);

        tabPane.add("Producer", producer);
        tabPane.add("Reactor", reactor);

        tabPane.setSelectedIndex(1);
        basePanel.add(tabPane);
        add(basePanel);
        pack();
        setLocationRelativeTo(null);
    }

    public static void main(String[] args)
    {
        EventsUeberKlassen sf = new EventsUeberKlassen();
        sf.setLocationRelativeTo(null);
        sf.setVisible(true);
        sf.pack();
    }
}

Klasse Producer

Java:
package eventsueberklassen;

import javax.swing.JButton;
import javax.swing.JPanel;

public class Producer extends JPanel
{
    private JButton btn;
    
    public Producer()
    {
        initComponents();
    }

    private void initComponents() 
    {
        setPreferredSize(new java.awt.Dimension(250, 80));
        btn = new JButton("Click");
        btn.setPreferredSize(new java.awt.Dimension(150, 50));
        add(btn);
    }   
}

Die reagierende Klasse Reaktor

Java:
package eventsueberklassen;

import javax.swing.JLabel;
import javax.swing.JPanel;

public class Reactor extends JPanel
{
    private JLabel lbl;
    private int btnClicked;
    
    public Reactor(Producer producer)
    {
        initComponents();
        lbl.setText("Nothing happened yet");
    }

    private void initComponents() 
    {
        setPreferredSize(new java.awt.Dimension(250, 80));
        lbl = new JLabel();
        lbl.setPreferredSize(new java.awt.Dimension(150, 50));
        add(lbl);
        btnClicked = 0;
    }
    
    public void updateLabel() 
    {
        System.out.println("Reactor.UpdateLabel");
        lbl.setText("Der Button wurde "+(btnClicked++)+" mal geklickt!");
        btnClicked++;
        repaint();
    }
}

Ich freu mich schon auf die endgültige Lösung :)

Vielen Dank im Voraus

RAPTORRS
 

raptorrs

Aktives Mitglied
@Phash Vielen Dank für den Hinweis. Ich bin erstaunlichweise damit zurecht gekommen :)

Mit Design Pattern habe ich mich noch nie beschäftigt. Als ich anfing zu lesen, war ich zunächst einmal frustriert wegen der Menge an Code und Klassen, die scheinbar erforderlich sind.

Aber ich habe dann doch eine brauchbare Lösung mit nur wenigen zusätzlichen Code-Zeilen hinbekommen. Leider habe ich nun ein neues, ganz anderes Problem.

Da ja die Producerklasse nun nicht nur JPanel, sondern auch die Klasse Observable erweitert, kann ich nicht:
class Producer extends JPanel extends Observable schreiben. Daher war ich gezwungen, JPanel explizit innerhalb der Klasse auszuprogrammieren.

Jetzt weiss ich allerdings nicht mehr, wie ich sie noch im TabbedPane in der Klasse "EventsUeberKlassen" unterbringen kann.
Hat hier vielleicht noch jemand eine Lösung für mich?

Und für alle, die vielleicht meine Lösung interessiert, hier der Code. Kommentare sind gerne wilkommen!


Die Klasse mit dem TabbedPane-Problem

Java:
public class EventsUeberKlassen
{
    private Producer producer;
    private Reactor reactor;
    
    public EventsUeberKlassen() 
    {
        initComponents();
    }

    private void initComponents() 
    {
        producer = new Producer();
        reactor = new Reactor();
        producer.addObserver(reactor);//Register more observers here
        producer.changeMessage("Nothing yet");
    }

    public static void main(String[] args)
    {
        EventsUeberKlassen sf = new EventsUeberKlassen();
    }
}

Die Klasse, die die ein Event durch Mausklick o. ä. erzeugt

Java:
import java.awt.Dimension;
import java.awt.Toolkit;
import java.util.Observable;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Producer extends Observable
{
    private JPanel panel;
    private JButton btn1;
    private JButton btn2;
    private String message;
    
    public Producer()
    {
        initComponents();
    }

    private void initComponents() 
    {
        panel = new JPanel();
        panel.setPreferredSize(new java.awt.Dimension(280, 80));
        btn1 = new JButton("Click 1");
        btn1.setActionCommand("btn1");
        btn1.setPreferredSize(new java.awt.Dimension(150, 30));
        btn1.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) 
            {
                System.out.println("Btn1");
                changeMessage("Producer-Btn1 clicked");
            }
        });
        panel.add(btn1);
        btn2 = new JButton("Click 2");
        btn2.setPreferredSize(new java.awt.Dimension(150, 30));
        btn2.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) 
            {
                System.out.println("Btn2");
                changeMessage("Producer-Btn2 clicked");
            }
        });
        panel.add(btn2);
        JFrame fr = new JFrame();
        fr.add(panel);
        fr.pack();
        fr.setVisible(true);
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        fr.setLocation(dim.width/2-300, dim.height/2-100);
    }

    public void changeMessage(String message)
    {
        this.message = message;
        setChanged();
        notifyObservers(message);
    }
}

Die Klasse die auf das Event reagieren soll

Java:
import java.awt.Dimension;
import java.awt.Toolkit;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Reactor extends JPanel implements Observer 
{
    private JLabel lbl;
    private int btnClicked;
    
    public Reactor()
    {
        initComponents();
        lbl.setText("Nothing happened yet");
        addToFrame();
    }

    private void initComponents() 
    {
        setPreferredSize(new java.awt.Dimension(280, 80));
        lbl = new JLabel();
        lbl.setPreferredSize(new java.awt.Dimension(250, 50));
        add(lbl);
        btnClicked = 0;
    }
    
    @Override
    public void update(Observable o, Object arg) // this method comes from abstract Observer
    {
        System.out.println("Observable o = "+o.toString()+", Object arg = "+arg);
        System.out.println("Reactor.UpdateLabel");
        lbl.setText("Der Button wurde "+(btnClicked)+" mal geklickt!");
        btnClicked++;
        repaint();       
    }

    private void addToFrame() 
    {
        JFrame fr = new JFrame("Reactor");
        fr.add(this);
        fr.pack();
        fr.setVisible(true);
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        fr.setLocation(dim.width/2, dim.height/2-100);
    }  
}

Nochmals vielen Dank für den Lösungsvorschlag!

Schönen Tag noch!
 

Ähnliche Java Themen

Neue Themen


Oben