# Kommunnikation in einer Applikation



## klein-odd (13. Nov 2006)

Hallo !

Es gibt in einer GUI-Applikation eine Klasse MainClass und NebenClass.
Beide haben eine JTextArea und einen JButton.

Es gelingt mir immer mit dem Main_JButton einen String zu Neben_JTextArea
hinzuzuschreiben per (Main_JButton ActionListener) :

NebenClass.Neben_JTextArea.append("text from main \n");

Umgekehrt ist es sehr schwieríg.
Erstellen einer neuen Instanz von der MainClass verursacht einblenden einer neuen GUI.

Und es soll ein String zu der Main_JTextArea  addiert werden in dem schon vorhandenen Fenster der MainClass.

Das heisst, dass von der MainClass keine neue Instanz erscheinen darf 
und es soll mit dem Neben_JButton ein String in die Main_JTextArea ein geschrieben werden, 
ebenfalls mit append.  

Der Listener von dem Neben_JButton soll in der JNeben_Class ode in einer SonstClass implementiert sein.

Wer kann das Rätsel knacken ?

Auf Wunsch der Code beider Dateien.


----------



## merxleben (13. Nov 2006)

Hi,

um eine solche Kommunikation zu realisieren, brauchst du in beiden Klassen eine Referenz auf die jeweils andere.


```
class MainClass {
  private NebenClass child;
}

class NebenClass {
  private MainClass owner;
}
```

Dann kannst du von beiden Klassen jeweils auf die Methoden der anderen zugreifen.

Wenn du du für deinen ActionListener eine separate Klasse entwickelst, kannst du auch folgenden Weg gehen.


```
class MainClassListener implements ActionListener {

  private MainClass owner;

  MainClassListener(MainClass owner) {
    this.owner = owner;
  }

  public void actionPerformed(ActionEvent ev) {
    owner.getTextArea().appendText("Test Text\n");
  }
}
```

Und wenn du deine Nebenklasse initialisierst, kannst du folgendes bei der Initialisierung der GUI machen


```
NebenClass child = new NebenClass();
child.addButtonAction(new MainClassListener(this));
```

Martin


----------



## Gast (14. Nov 2006)

besten Dank !
Ich muss es noch ausprobieren, um mich völlig zu begeistern aber Du hast mir von der Seele geschrieben !

Eben habe ich schon an Listener-Klassen gedacht.
Ich danke Dir schön !


----------



## klein-odd (14. Nov 2006)

Es funktioniert NICHT richtig !
Die MainClass schreibt, was sie will in den nachbarn,
die NebenClass packt es nicht.

Was mache ich falsch ?

Hier der Code der MainClass :

import java.awt.*;
import java.awt.event.*;

public class Main implements ActionListener 
{
	private Neben child;

	Frame mainF;
	Button mainB;
	TextField mainTF;
	TextArea mainTA;


	public Main()
	{
		mainF = new Frame("mainF");
		mainF.setBounds(40,40,360,300);

		mainTF = new TextField();		
		mainTF.setBounds(40,40,150,40);

		mainB = new Button("MAIN");
		mainB.addActionListener(this);
		mainB.setBounds(220,40,80,40);

		mainTA = new TextArea(10,20);
		mainTA.setBounds(40,200,280,80);

		mainF.setLayout(null);
		mainF.add(mainTF);
		mainF.add(mainB);
		mainF.add(mainTA);

		mainF.setVisible(true);

		mainF.addWindowListener(
				new WindowAdapter(){
			public void windowClosing(WindowEvent we)
			{
				System.exit(0);
			}
		});

		child = new Neben();
	}

	public static void main(String[] args) 
	{
		Main jetzt = new Main();	
	}

	public void actionPerformed(ActionEvent mae)
	{
		String mcmd = mae.getActionCommand();
		if(mcmd.equals("MAIN"))
		{
			child.nebenTA.append("new Line from Main \n");
			mainTA.append("new Line from Main \n");			
		}
	}

}


und hier der der NebenClass :

import java.awt.*;
import java.awt.event.*;

public class Neben implements ActionListener
{
	private Main owner ;/*= new Main();*/

	final Frame nebenF;
	Button nebenB;
	TextField nebenTF;
	TextArea nebenTA;

	public Neben()
	{
		nebenF = new Frame();
		nebenF.setBounds(450,50,300,300);

		nebenB = new Button("neben");
		nebenB.setBounds(150,50,80,40);

		nebenB.addActionListener(this);

		nebenTF = new TextField(24);
		nebenTF.setBounds(10,50,80,40);
		nebenTA = new TextArea(10,20);
		nebenTA.setBounds(50,180,200, 60);

		nebenF.add(nebenB);
		nebenF.add(nebenTF);
		nebenF.add(nebenTA);

		nebenF.setVisible(true);

		nebenF.addWindowListener(
				new WindowAdapter(){
					public void windowClosing(WindowEvent we)
					{
						nebenF.dispose();
					}
		});

	}

	public void actionPerformed(ActionEvent nae)
	{
		String ncmd = nae.getActionCommand();
		if(ncmd.equals("neben"))
		{
			owner.mainTA.append("new Line from Neben \n");
			nebenTA.append("new Line from here \n");

		}
	}
}


kann da jemand helfen ?


----------



## SlaterB (14. Nov 2006)

in Neben gibt es eine Exemparvariable auf owner,
aber die wird nirgendwo gesetzt!

wie soll denn das funktionieren, wieso setzt du die nicht auf das owner-Objekt?


```
child = new Neben(this); 

-----

 public Neben(Main owner)
{ 
   this.owner = owner;
   ..
}
```


----------



## klein-odd (14. Nov 2006)

"Slater" !!!

Du hast mich aus dem Koma geholt !!!
Ich lebe wieder !!!!!!!!!

Danke schön !


----------



## klein-odd (22. Nov 2006)

Hey !

Ich brauchte eine Applikation mit mehreren Klassen aufzubauen.
Das heisst, 
dass die MAIN Klasse (mit JFrame mainFrame) eigenen Menu-Bar
von der Klasse MENUBAR bekommt (mainFrame.setJMenuBar(new MENUBAR())).

Die Steuerelemente werden mit Aktionen von der Klasse Actions versorgt.

Problem kann so definiert werden :

Es gibt ein JMenuItem open im MenuBar, mit dem ein JFileChooser durch Aktion ACTIONS.openAct() gestartet wird.

Der JFileChooser filechooser soll als eingangsvariable String PFAD von dér MAIN-Klasse  benutzen
und sein Erfolg 
String FileName = filechooser.getSelectedFile.getName();
soll in eine Variable String NAME eingeschrieben werden.

Schema für Obiges sieht etwa so aus (Klassen MAIN, MENUBAR und ACTIONS):


```
MAIN
{
    String PFAD="C:";
    String NAME=null;
    JFrame mainFrame;
    MENUBAR menuB;

    MAIN()
    {
        mainFrame = new JFrame();
        menuB = new MENUBAR();
        mainFrame.setJMenuBar(menuB);
    }
}
```


```
MENUBAR
{
   JMenu openM;
   JMenuItem open;
   MENUBAR()
    {
        open = new JMenuItem(ACTIONS.openAct());
        openM = JMenu("OPEN");
        openM.add(open);
        add(openM);
    }
}
```


```
ACTIONS
{
    static Action openAct()
    AbstractAction OpenDir = new AbstractAction("OPEN")
    {
        public void actionPerformed(final ActionEvent o)
            {
                fc = new JFileChooser(MAIN.PFAD);
                //die Eingangsvariable MAIN.PFAD für fc soll der String von der Klasse MAIN sein
                int returnVal = fc.showDialog(null,"open");
                File file = fc.getSelectedFile();
                String fileName = file.getName();

                   // wie kann der Wert (Typ: String) der Variablen NAME in MAIN übergeben werden ?

            }
    }
}
```


weiss da jemand den Weg ?

Die Ratschläge von früher funktionieren wunderbar aber hier habe ich eine Dimension mehr, oder ?

Danke im Voraus


----------



## SlaterB (22. Nov 2006)

das ist ganz schön wirr,
was IST denn das Problem?

jede Komponente, egal ob 1 oder 100, braucht eine Referenz auf den Controller (oder Zwischencontroller für bestimmte Bereiche)
und ruft dort passende Operationen zum Programmfluss auf


----------



## klein-odd (22. Nov 2006)

Ich will, dass die Variable NAME in der Klase MAIN den Namen der Datei bekommt,
die der JFileChooser öffnet.

Der JFileChooser fc soll für seine Aktion den Pfad (eine Stringvariable)
von der Klasse MAIN nehmen.

Den JFilechooser (genannt fc) startet JMenuItem open in dem Fenster frame in der Klasse MAIN.
Der Balken MenuBar wird in der Klasse MENUBAR konstruiert.

Und dem JMenuItem open wird bei der Konstruktion  die Aktion openAct zugewiesen.
(der Lauscher des open steckt in der Klasse ACTIONS.)

Meine Referenzier-fähigkeiten sind durch meine Eclipse nicht akzeptiert.

Soll ich über konkrete Fehlerdiagnose etwas schreiben ?


----------



## SlaterB (22. Nov 2006)

klein-odd hat gesagt.:
			
		

> Ich will, dass die Variable NAME in der Klase MAIN den Namen der Datei bekommt,
> die der JFileChooser öffnet.
> 
> Der JFileChooser fc soll für seine Aktion den Pfad (eine Stringvariable)
> ...



also ganz einfach: 
AbstractAction("OPEN") braucht eine Referenz auf MAIN,
zum Setzen und Lesen,
nix einfacher als das, geht nicht gibts nicht, was nicht passt wird passend gemacht 

--------

so und was genau ist das Problem?
bei anonymen inneren Klassen ist es natürlich nicht so einfach, final-Variablen helfen aber vielleicht schon?

dein Code-Ausschnitt ist nicht ganz ersichtlich, wo wird diese Action erzeugt?
statisch oder nicht? in einer Operation/ Konstruktor, direkt in der Klasse?

```
{
    final MAIN main = ..;

    AbstractAction OpenDir = new AbstractAction("OPEN")
    {
        public void actionPerformed(final ActionEvent o)
            {
                fc = new JFileChooser(MAIN.PFAD);
                //die Eingangsvariable MAIN.PFAD für fc soll der String von der Klasse MAIN sein
                int returnVal = fc.showDialog(null,"open");
                File file = fc.getSelectedFile();
                String fileName = file.getName();

                   // wie kann der Wert (Typ: String) der Variablen NAME in MAIN übergeben werden ?
                  --->> main.setName(NAME);

            }
    } 

}
```


----------



## klein-odd (22. Nov 2006)

Slater, guter Mensch !

Aktion openAct wird in der Klasse ACTIONS erzeugt.
Die Methode openAct  wird folgendermaßen begonnen:

static Action openAct()

Ich wollte die 3 zusammenarbeitende Klassen eben in 3 Code Abschnitten darstellen.

In der Klasse Main steckt nur das JFrame mirt dem MenuBar.

Alle Aktionen werden in der Klasse ACTIONS.class erzeugt.

Ich werde jetzt versuchen, Deine Tipps umzusetzen.

Danke


----------



## klein-odd (22. Nov 2006)

Also Probleme ergeben sich in der Methode openAct.

Ich habe als Eingangsparameter die MAIN-Klasse genommen,
also sieht die Klasse ACTIONS.class folgendermaßen aus :

```
public class ACTIONS
{
    MAIN main;
    
    static Action openAct(MAIN main)
    {
        this.main = main;
        AbstractAction openA = new AbstractAction("OPEN)
        {
            public void actionPerformed(ActionEvent op)
            {
                // zur Vereinfachung : in die String Variable NAME in der Klasse MAIN.class
                // soll String "ALLRIGHT" übergeben werden

                main.NAME = "ALLRIGHT";                

            }

        };
        

    
        return openA;
    }
}
```

die Eingangsvariable in openAct muß auch bei der Konstruktion des JMenuItems open 
angegeben werden.


```
public class MENUBAR
{
    MENUBAR()
    {    
        open = new JMenuItem(ACTIONS.openAct(  /*auch  Klasse MAIN */  ))
    }
}
```

und beim Einfügen des MenuBars in der Klasse MAIN mußdie Klasse auf-sich-selbsr refernziert werden, oder ?


```
JFrame.setJMenuBar(new MENUBAR(   /* was  soll hier stehen  ?*/ ));
```


----------



## SlaterB (22. Nov 2006)

main-mania

```
Frame.setJMenuBar(new MENUBAR(this)); 

public class MENUBAR
{
    MENUBAR(Main main)
    {   
        open = new JMenuItem(ACTIONS.openAct(main))
    }
}
```


----------



## klein-odd (23. Nov 2006)

Danke Dir, Slater, es funktioniert.


----------



## klein-odd (2. Apr 2007)

Jetzt habe ich neue Herausforderung :

in der Klasse LAB gibt es eine JLabel.


```
public class LAB
{
JLabel label;
	public LAB()
	{
	       label = new JLabel();
	}
}
```
Klasse NOTE soll einen String in die JLabel schreiben,

```
public class NOTE
{
   	String wort;
	LAB back;

	public NOTE(LAB lab)
	{

                    back = lab;
	    String wort="token";

	    /*das jedenfalls bringt keinen Effekt */

	    back.label.setText(wort);			   
	}
}
```
was fehlt in dem Code damit das wort in die Label eingesetzt werden kann ?


----------



## SlaterB (3. Apr 2007)

nichts
schreibe ein vollständiges Programm mit 50 Zeilen,
dann sieht man wo der Fehler liegt,
vielliecht zeigst du ein ganz anderes Label in der GUI an


----------



## klein-odd (19. Apr 2007)

Hallo Slater !
Nach einiger Lesezeit Deiner früheren Worte habe ich meine Fehler entdeckt und korrigiert.
Die Tipps und Bemerkungen in Deinen früheren eMails 
waren GENIAL. 
Besonders lehrhaft war Dein Eintrag im Forum "Main-Mania".

Eigentlich ist es egal, welche Programmiersprache betrachtet 
wird, dem Rechner muß man immer den kompletten Eingangssatz liefern. 

So habe ich dann zum Starten jeder Klasse oder Methode 
genügend Eingangsgrößen geliefert. 
So wie ich vor vielen Jahren mit Fortran gemacht habe.
Jetzt werden nur andere Wörter benutzt.

Echt vielen Dank.

Hast Du vielleicht Erfahrungen mit der Klasse PinterJob ?

Im Forum AWT, Swing & SWT habe ich neue Suche nach Rat gestartet.
Thema : Drucken von JTextComponenten.

Es geht mir um Ausdruck vom html-formatierten Inhalt
JTextComponenten () aufs Papier. Und im Web ist es sehr spärlich betrachtet.

Also : besten Dank für Deine Worte, Slater.


----------



## SlaterB (20. Apr 2007)

zum Drucken kenne ich nix


----------

