Wie: Eigener Listener, eigenes Event (möglichst einfach)

Status
Nicht offen für weitere Antworten.

ernst

Top Contributor
Hallo allerseits,
ich will in (mit Hilfe einer Schleife) ein Bild (image) immer wieder etwas einzeichnen (z.B. einen Kreis).
Bei jedem Einzeichnen eines Kreises soll ein (selbstgebasteltes?) Ereignis erzeugt werden, durch das dann ein (selbstgebastelter) Listener aufgerufen wird.
Ich habe schon zwar ein paar Sachen darüber gelesen, aber ich habe es bis jetzt noch nicht geschafft ein funktionsfähiges Programm zu schreiben. Ich bekomme es einfach nicht hin.

Kann mir jemand ein _lauffähiges_ - möglichst einfaches Programm - geben (das die Kreise einzeichnet und z.B. bei jedem Einzeichnen den Listener aufruft, der eine Meldung auf dem Bildschirm ausgibt), so dass ich daran das Prinzip erkennen kann.

mfg
Ernst
 

dieta

Top Contributor
Mal vorweg:

Vor dem ersten Posten bitte lesen!!! hat gesagt.:
- Wir machen keine Hausaufgaben. Ihr müsst schon eigene Ideen, bzw. Lösungsvorschläge haben.


An sonsten: Beide Teilfragen die du hast, werden in den FAQs reecht ausführlich behandelt. Die Foren-Suche und Google helfen auch weiter.

http://www.gidf.de/
 
G

Guest

Gast
>
>Wir machen keine Hausaufgaben. Ihr müsst schon eigene Ideen, bzw. Lösungsvorschläge haben.
>
ich muss keine Hausaufgaben mehr machen.
>
>An sonsten: Beide Teilfragen die du hast, werden in den FAQs reecht ausführlich behandelt.
>
Meinst du etwa:
http://www.java-forum.org/de/viewtopic.php?t=3569
Das hilft mir leider auch nicht!
>
>Die Foren-Suche und Google helfen auch weiter.
>
Leider nein.
>
>http://www.gidf.de/
>
Das hat mir leider auch nicht geholfen.

Trotzdem Dank für deine Hilfe.
Da du dich offenbar auskennst (“Die Foren-Suche und Google helfen auch weiter“) bitte ich dich, mir einen _konkreten_ Link oder den Quellcode zu geben, in dem ein _lauffähiges_ Programm vorkommt, da ich leider schon ziemlich viel rumprobiert habe und nicht weitergekommen bin.

mfg
Ernst
 
S

SlaterB

Gast
> Kann mir jemand ein _lauffähiges_ - möglichst einfaches Programm - geben [..], so dass ich daran das Prinzip erkennen kann

du verdrehst die Aufgaben:
Kannst DU ein _lauffähiges_ - möglichst einfaches Programm - geben, so dass man daran deine bisherigen Versuchen, Fehler und weiteren Probleme erkennen kann?!
Eine textuelle Beschreibung außer 'hab viel versucht, nix geht' wäre natürlich (alternativ/ ergänzend) auch nicht schlecht.

Ganz ohne Grundlagen gehts natürlich nicht,
schaue dir die Klassen Observer, Observable an,
http://www.galileocomputing.de/openbook/javainsel6/javainsel_08_006.htm#Xxx1000605
 

ernst

Top Contributor
>
>du verdrehst die Aufgaben:
>Kannst DU ein _lauffähiges_ - möglichst einfaches Programm - geben,
>so dass man daran deine bisherigen Versuchen, Fehler und weiteren Probleme erkennen kann?!
>Eine textuelle Beschreibung außer 'hab viel versucht, nix geht' wäre natürlich
>(alternativ/ ergänzend) auch nicht schlecht.
>
>Ganz ohne Grundlagen gehts natürlich nicht,
>schaue dir die Klassen Observer, Observable an,
>http://www.galileocomputing.de/openbook/javainsel6/javainsel_08_006.htm#Xxx1000605
>
Für Observable/Observer habe ich ein funktionierenes Programm. Aber ich will mein Programm nicht mit Observable/Observer realisieren, sondern mit Listener/Event!

Nur: mit Listener/Event gibt es Probleme.
Ich habe irgendwie ein paar Programmteile zusammengefügt, aber das hat alles nur Schrott gegeben.

Ich muss eine eigene Listener-Klasse z.B. MyListenerKlasse (implementiert EventListener) und eine eigene Event-Klasse z.B. MyEventKlasse (extends EventObject) bauen.
Wie kann ich aber nun dem System mitteilen, dass beim Zeichnen eines Kreises auf das Image ein Objekt _meiner_ selbstgebastelten Listener-Klasse MyListenerKlasse erzeugt wird?
Brauche ich dazu noch irgendwelche Methoden?

Bei den vorgegebenen (im Java-System schon existierenden) Listenern ist mir das klar:
Bei einem Mausklick wird durch das Java-System (VM?) ein Ereignis vom Datentyp einer im Java-System schon implementierten Klasse erzeugt.
Aber wie ist es, wenn ich alles selber basteln muss?


mfg
Ernst
 

kleiner_held

Top Contributor
Das ist doch an sich wirklich kein kompliziertes Konzept.
Deine Klasse die das Zeichnen vornimmt und die Events ausloesen soll muss folgendes implementieren:
1. 2 Methoden addMyListener(MyListenerKlasse listener) und removeMyListener(MyListenerKlasse listener) die die Listener intern z.B. in einer Liste verwalten
2. eine private oder protected Methode fireMyEvent(MyEventKlasse event) die den Event an alle deine registrierten Listener aus der obrigen Liste ausloest
3. den Aufruf von fireMyEvent() mit einem neuen MyEvent an allen Stellen im Code, an denen du einen Event ausloesen willst.
 
S

SlaterB

Gast
jo, und du kannst nur vom System vorgegebene Events wie MausEvents nutzen, um bei deren Bearbeitung eigene Events auszulösen,
was leicht unsinnig ausschaut,

du kannst die Maus nicht so konfigurieren, dass sie direkt was anderes macht, dazu ist Java nicht gedacht ;)

ob das nun Observable oder Listener heißt ist da doch egal?
 

ernst

Top Contributor
kleiner_held hat gesagt.:
Das ist doch an sich wirklich kein kompliziertes Konzept.
Deine Klasse die das Zeichnen vornimmt und die Events ausloesen soll muss folgendes implementieren:
1. 2 Methoden addMyListener(MyListenerKlasse listener) und removeMyListener(MyListenerKlasse listener) die die Listener intern z.B. in einer Liste verwalten
2. eine private oder protected Methode fireMyEvent(MyEventKlasse event) die den Event an alle deine registrierten Listener aus der obrigen Liste ausloest
3. den Aufruf von fireMyEvent() mit einem neuen MyEvent an allen Stellen im Code, an denen du einen Event ausloesen willst.

Das ist der Punkt:
Du schreibst _eigene_ Methoden
fireMyEvent()
addMyListener(MyListenerKlasse listener)
removeMyListener(MyListenerKlasse listener)
...
Was mir aber nicht klar ist. Wer garantiert, dass diese _selbstgebastelten_ Methoden das Gewünschte machen?
Wer bzw. welcher Mechanismus garantiert, dass das Java-System wirklich ein Ereignisobjekt erzeugt?
Da muss doch dann die Vererbung oder sonst was eine Rolle spielen (die mir dann _Funktionalität_ vererbt).

Ich kann doch auch nicht einfach eine Funktion schreiben, wie z.B.
char HoleByteVonSeriellerSchittstelle(){
...
}
Die holt mir garantiert nichts, wenn ich nicht auf schon _bestehende_ Ressourcen des Java-Systens zurückgreife, die irgendwas mit der seriellen Schnittstelle zu tun haben. Ansonsten müsste ich selbst über die Portadressen die serielle Schnittstelle ansprechen, was meiner Meinung nach nicht funktioniert (weil der der Prozessor im protected Mode läuft und er deshalb eine Hardware-Exception auslöst; unter DOS war so was mit C möglich).

mfg
Ernst
 
S

SlaterB

Gast
wie gesagt: wenn die Maus oder die serielle Schnittstelle etwas besonderes in deinem Programm machen soll,
dann hat das erstmal nix mit Ereignisbehandlung oder Swing zu tun (Tenor in diesem Thread),
dann öffne einen neuen Thread (a la 'Maus aus Systemebene kontrollieren')
oder such dir am besten eine passendere Programmiersprache ;)

mit Swing hast du einen MouseListener und eine Operation mousePressed
und da kannst du entweder nix tun oder eine eigene Operation
'createMyEvent' aufrufen,
keine große Kunst
 

kleiner_held

Top Contributor
ernst hat gesagt.:
Das ist der Punkt:
Du schreibst _eigene_ Methoden
fireMyEvent()
addMyListener(MyListenerKlasse listener)
removeMyListener(MyListenerKlasse listener)
...
Was mir aber nicht klar ist. Wer garantiert, dass diese _selbstgebastelten_ Methoden das Gewünschte machen?
Wer bzw. welcher Mechanismus garantiert, dass das Java-System wirklich ein Ereignisobjekt erzeugt?
Da muss doch dann die Vererbung oder sonst was eine Rolle spielen (die mir dann _Funktionalität_ vererbt).

Irgendwie bin ich verwirrt - deine Frage handelt sich darum, wie man den Listner Mechanismus per Hand implementiert und dann willst du das das Java-System irgend etwas fuer dich macht?

Das "Java System" wird fuer deine selbstgestrickten Events nie etwas fuer dich machen - wie auch, wenn du eigene Events generierst, dann weisst auch nur du wann denn das Ereignis eintritt und ein Event ausgeloest werden muss. Man kann doch nicht einfach eine Klasse EsIstVollmondEvent anlegen und darauf warten das deine JVM von selbst mitkriegt das Vollmond ist und ein Event ausgeloest werden soll. Du musst dich um alles selbst kuemmern, um das Registrieren der Listener, um das Anlegen Event Objekte und um das Senden dieser Events an alle Listener.

Vielleicht solltest du nochmal genau erklaeren was du eigentlich willst.
 

Tobias

Top Contributor
Äh, die Implementierung eines eigenen Listeners habe ich doch (lauffähig, wenn man eine kleine main drumpackt) ausführlichst in der FAQ erklärt?? Den Link hat man dir ja schon gegeben ... Raff ich nicht, wie man damit nicht klar kommen kann.

mpG
Tobias
 

ernst

Top Contributor
kleiner_held hat gesagt.:
Irgendwie bin ich verwirrt - deine Frage handelt sich darum, wie man den Listner Mechanismus per Hand implementiert und dann willst du das das Java-System irgend etwas fuer dich macht?

Das "Java System" wird fuer deine selbstgestrickten Events nie etwas fuer dich machen - wie auch, wenn du eigene Events generierst, dann weisst auch nur du wann denn das Ereignis eintritt und ein Event ausgeloest werden muss. Man kann doch nicht einfach eine Klasse EsIstVollmondEvent anlegen und darauf warten das deine JVM von selbst mitkriegt das Vollmond ist und ein Event ausgeloest werden soll. Du musst dich um alles selbst kuemmern, um das Registrieren der Listener, um das Anlegen Event Objekte und um das Senden dieser Events an alle Listener.

Vielleicht solltest du nochmal genau erklaeren was du eigentlich willst.

Vermutlich ist die Verwirrung in meinem Kopf.
Wenn ich will, dass beim Zeichnen eines Kreises ein Ereignis ausgelöst werden soll, benötige ich doch Hilfe vom Java-System. Ich brauche doch irgendenen Befehl vom Java-System, der dann wirklich die VJM veranlasst ein Ereignis auszulösen. Ich kann zwar irgendeine Methode wie z.B. myBitteLoeseEreignisAus() schreiben, doch innerhalb dieser Methode benötige ich doch eine Methode des Java-Systems, die die dann die VJM veranlasst, dies zu tun
Oder bin ich da voll auf dem Holzweg?

mfg
Ernst
 

Tobias

Top Contributor
Du hast eine Zeichenfläche (zum Beispiel eine Canvas). Du hast einen JToggleButton, auf dem steht "Kreis zeichnen". Der User markiert diesen Button und zieht anschließend auf der Zeichenfläche per Drag & Drop den Kreis aus. In der mouseReleased()-Methode des Canvas-MouseListeners stellst du jetzt fest "Aha, das Kreiszeichnen-Werkzeug ist aktiviert und die Maus wurde gerade wieder losgelassen. Also wurde gerade ein Kreis gezeichnet.". Und nachdem du das festgestellt hast, feuerst du einen KreisGezeichnetEvent an alle registrierten KreisZeichnerListener.

Wo ist das Problem?

mpG
Tobias

P.S.: Du kannst dich nicht in die Eventauslösenden Routinen von Java einklinken. Du kannst einen Listener anbieten, der auf den Event reagieren kann (zum Beispiel wie oben das Systemevent in ein eigenes "höher Aggregiertes" übersetzen), aber mehr nicht. Ist auch weder sinnvoll noch nötig.
 

kleiner_held

Top Contributor
Du bist auf dem Holzweg, es gibt keinen speziellen JVM Mechanismus fuer sowas.

Du zeichnest deinen Kreis, legst selbet einen neues EventObjekt mit new an, Iterierst ueber alle registrierten Listener und rufst an jedem Listener ein Methode handleEvent(myEvent) auf.
Das Senden des Events passiert linear in dem gleichen Thread in dem du auch den Kreis gezeichnet hast, im Programmablauf behandeln erst alle Listener den Event und dann wird deine zeichneKreis() methode fortgesetzt.

Ich vermute Du denkst an sowas wie eine asyncrone Eventverarbeitung, also ein kurzer Methodenaufruf und dannach laeuft die Abarbeitung deiner Methode zeichneKreis() weiter, waehrend im Hintergrund parallel (sprich in anderen Threads) alle Listener mit dem Event gefuettert werden. Das ist aber unueblich. Um mal auf das Beispiel des MouseListeners zurueck zu kommen - wenn du einen MouseListener einer beliebigen Swing-Componente hinzufuegst, dann erfolgt die Abarbeitung eines mouseClicked(MouseEvent e) in deinem GUIThread (der sogenannte AWT-Event) und wenn Du in der Methode ein Thread.slepp(10000); einfuegen wuerdest, wuerdest Du feststellen, dass deine GUI nach dem Mausklick fuer 10 Sekunden haengt.
 

ernst

Top Contributor
kleiner_held hat gesagt.:
Ich vermute Du denkst an sowas wie eine asyncrone Eventverarbeitung, also ein kurzer Methodenaufruf und dannach laeuft die Abarbeitung deiner Methode zeichneKreis() weiter, waehrend im Hintergrund parallel (sprich in anderen Threads) alle Listener mit dem Event gefuettert werden. Das ist aber unueblich. Um mal auf das Beispiel des MouseListeners zurueck zu kommen - wenn du einen MouseListener einer beliebigen Swing-Componente hinzufuegst, dann erfolgt die Abarbeitung eines mouseClicked(MouseEvent e) in deinem GUIThread (der sogenannte AWT-Event) und wenn Du in der Methode ein Thread.slepp(10000); einfuegen wuerdest, wuerdest Du feststellen, dass deine GUI nach dem Mausklick fuer 10 Sekunden haengt.

Ich versuche mal mein Anliegen an dem folgenden Programm unten zu erklären.
In dem Programm werden verzögert Kreise auf dem Bildschirm ausgegeben.
Um das zu synchronisieren verwende ich pfuschmäßig die Variable "ichMaleGerade".

Jetzt will ich das Programm ohne die Synchronisation machen und das Programm so abändern, dass nach jeder Verzögerung (sleep(500)) ein Ereignis (Objekt einer selbstgebastelten Klasse) ausgelöst wird und dadurch automatisch ein selbstgebastelten Listener aufgerufen wird, der einen Kreis zeichnet.
(Wobei ein Ereignis auslösen doch CPU-intern intern einen Hardware-Interrupt auslöst und dies im Java-System verwendet wird, also wiederum eine Ressorce, die _JVM bietet_ und vom Programmierer benutzt wird. Das ist wieder der Punkt, wo ich auf dem Schlauch stehe).

Kann mir jemand dazu einen möglichst einfachen Quellcode (mit Listener und Event) geben, an dem ich das Problem dann verstehen kann. Ich glaube, dass ich ohne einen einfachen Quellcode das Problem nicht verstehen kann.


Code:
package de;
import java.awt.*;
import javax.swing.*;

public class MainVerzoegertZeichnen1 {
	  public static void main(String[] args){
	    JFrame f = new JFrame();
	    f.setSize(550,550);
	    Diagramm diagramm = new Diagramm(550, 550);
	    f.getContentPane().add(diagramm);
	    Thread t = new Thread(diagramm);
	    t.start();
	    f.setVisible(true);
	  }
	}

class Diagramm extends JPanel implements Runnable{
  private int xpAnz;
  private int ypAnz;
  private int i; 
  private Image myimg;
  private Graphics myg;
  private int sx; 
  private int sy;
  private boolean ichMaleGerade;

  public Diagramm(int xpAnz, int ypAnz){  
    i=0; 
    this.xpAnz=xpAnz;
    this.ypAnz=ypAnz;    
    myimg=null;  
    ichMaleGerade=true;    
  }
  
  public void paintComponent(Graphics g){
  	if(myimg==null){
  	    sx = this.getSize().width;  
  	    sy = this.getSize().height;
  	    myimg = createImage(sx, sy);
  	    myg = myimg.getGraphics();
  	}
  	myg.setColor(Color.red);
 	myg.drawOval(i , 2*i+15, 20, 20);
       ichMaleGerade=false;    
  	g.drawImage(myimg,0,0,null);
  }
	
  public void run(){
    while(i<200){
      this.repaint();
      while(ichMaleGerade==true){
      }
      ichMaleGerade=true;
      try{
        Thread.sleep(500);
      }
      catch(Exception e){}
      i = i+20;
    }
  }
}


mfg
Ernst
 

Tobias

Top Contributor
Wobei ein Ereignis auslösen doch CPU-intern intern einen Hardware-Interrupt auslöst und dies im Java-System verwendet wird, also wiederum eine Ressorce, die _JVM bietet_ und vom Programmierer benutzt wird.

Auf Java bezogen völliger Schwachsinn, darum, was die Hardware macht, kümmere ich mich als Programmierer überhaupt nicht.

Ein "Ereignis auslösen" heißt soviel wie "Callback-Methoden aufrufen und diesen Informationen über die gerade geschehene Aktion mitteilen".

mpG
Tobias
 
S

SlaterB

Gast
Code:
try{ 
        Thread.sleep(500); 
        paintCircle()
}
oder auch
Code:
try{ 
        Thread.sleep(500); 
        createAnyKindOfEvent()
}
 

kleiner_held

Top Contributor
Abgesehen davon ist ein Listener/Event Mechanismus fuer dein Beispiel nichtmal unbedingt noetig.

Code:
import java.awt.*;
import java.awt.image.BufferedImage;

import javax.swing.*;

public class MainVerzoegertZeichnen1 {
     public static void main(String[] args){
       JFrame f = new JFrame();
       f.setSize(550,550);
       Diagramm diagramm = new Diagramm(550, 550);
       f.getContentPane().add(diagramm);
       Thread t = new Thread(diagramm);
       t.start();
       f.setVisible(true);
     }
   }

class Diagramm extends JPanel implements Runnable{
  private int xpAnz;
  private int ypAnz;
  private int i;
  private Image myimg;
  

  public Diagramm(int xpAnz, int ypAnz)
  { 
    i=0;
    this.xpAnz=xpAnz;
    this.ypAnz=ypAnz;   
    myimg = new BufferedImage(xpAnz, ypAnz, BufferedImage.TYPE_INT_RGB);
  }
  
  @Override
  public Dimension getPreferredSize()
  {
	  return new Dimension(xpAnz, ypAnz);
  }
  
  protected void paintComponent(Graphics g)
  {
     synchronized(myimg)
     {
    	 g.drawImage(myimg,0,0,null);
     }
  }
   
  public void addKreis()
  { 
     synchronized(myimg)
     {
        Graphics myg = myimg.getGraphics(); 
        myg.setColor(Color.red);
        myg.drawOval(i , 2*i+15, 20, 20);
        myg.dispose();
     }
  }

  public void run(){
    while(i<200){
      try{
        Thread.sleep(500);
      }
      catch(Exception e)
      {
      }
      i = i+20;
      addKreis();
      this.repaint();
    }
  }
}
 

ernst

Top Contributor
>
>Auf Java bezogen völliger Schwachsinn, darum, was die Hardware macht, kümmere ich mich
>als Programmierer überhaupt nicht.
>
Stimmt. Ich wollte nur ausdrücken, dass das Java-System etwas macht, das der Programmierer nutzen kann und das er nicht selbst machen muss.

mfg
Ernst
 

ernst

Top Contributor
>
>Abgesehen davon ist ein Listener/Event Mechanismus fuer dein Beispiel nichtmal unbedingt noetig.
>
Danke für dein Programm. Mit einer Synchronisation (so wie Java es vorsieht) habe ich es noch nicht probiert (habe aber gerade davon gelesen) Ich werde mir das anschauen und hoffentlich davon lernen.

Trotzdem:
Wie macht man es mit dem Listener/Event Mechanismus

mfg
Ernst
 
R

Roar

Gast
ernst hat gesagt.:
Stimmt. Ich wollte nur ausdrücken, dass das Java-System etwas macht, das der Programmierer nutzen kann und das er nicht selbst machen muss.
hm, irgendwie verstehst du das nicht. das "java-system" macht *nix*
dein listener/events zeug sind nur stinknormale *methodenaufrufe* wie du sie zig-fach in deinem code hast. nicht mehr. du rufst eine methode auf und der übergibst du ein interface und irgendwann später wird wieder eine methode aus dem interface aufgerufen. mehr ist da nich, mehr macht java da nicht. mehr steht auch nicht in den Observer/Observable klassen drin. :gaen:
 

kleiner_held

Top Contributor
Hier ein Beispiel mit Listenern.

Obwohl ich nur ein sich aenderendes Diagramm habe und das Diagramm weder die DiagrammPanel noch das JLabel kennt (und nichtmal weiss was ein DiagrammPanel ist), werden alle 7 Panels und das Label zeitnah aktualisiert - das ist der Zweck von Events/Listenern. In der main() methode siehst Du auch die Verwendung eines annonymen Listeners.

Code:
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.EventObject;
import java.util.List;

import javax.swing.*;

public class MainVerzoegertZeichnen1
{
	public static void main(String[] args)
	{
		JFrame f = new JFrame();
		f.setSize(400, 200);
		final Diagramm diagramm = new Diagramm(100, 100);
		f.getContentPane().setLayout(new GridLayout(2, 4));
		for (int i = 0; i < 7; i++)
		{
			f.getContentPane().add(new DiagrammPanel(diagramm));
		}
		final JLabel label = new JLabel(Integer.toString(diagramm.getI()));
		label.setHorizontalAlignment(JLabel.CENTER);
		diagramm.addListener(new MyListener()
			{
				public void handleEvent(MyEvent event)
				{
					label.setText(Integer.toString(diagramm.getI()));
				}
			});
		f.getContentPane().add(label);
		Thread t = new Thread(diagramm);
		t.start();
		f.setVisible(true);
	}

	public static class DiagrammPanel extends JPanel implements MyListener
	{
		private Diagramm diagramm;

		public DiagrammPanel(Diagramm diagramm)
		{
			this.diagramm = diagramm;
			diagramm.addListener(this);
		}

		public Dimension getPreferredSize()
		{
			return new Dimension(diagramm.getWidth(), diagramm.getHeight());
		}

		protected void paintComponent(Graphics g)
		{
			diagramm.draw(g);
		}
		
		public void handleEvent(MyEvent event)
		{
			repaint();
		}
	}

	public static class Diagramm implements Runnable
	{
		private int width;

		private int height;

		private int i;

		private Image myimg;

		private List<MyListener> listeners = new ArrayList<MyListener>();

		public Diagramm(int xpAnz, int ypAnz)
		{
			i = 0;
			this.width = xpAnz;
			this.height = ypAnz;
			myimg = new BufferedImage(xpAnz, ypAnz, BufferedImage.TYPE_INT_RGB);
		}

		public void draw(Graphics g)
		{
			synchronized (myimg)
			{
				g.drawImage(myimg, 0, 0, null);
			}
		}

		public void addKreis()
		{
			synchronized (myimg)
			{
				Graphics myg = myimg.getGraphics();
				myg.setColor(Color.red);
				myg.drawOval(i, i, 20, 20);
				myg.dispose();
			}
			fireEvent();
		}

		public void run()
		{
			while (i < 60)
			{
				try
				{
					Thread.sleep(500);
				}
				catch (Exception e)
				{
				}
				i = i + 10;
				addKreis();
			}
		}

		public int getWidth()
		{
			return width;
		}

		public int getHeight()
		{
			return height;
		}

		public void addListener(MyListener listener)
		{
			listeners.add(listener);
		}

		public void removeListener(MyListener listener)
		{
			listeners.remove(listener);
		}

		protected void fireEvent()
		{
			MyEvent event = new MyEvent(this);
			for (MyListener listner : listeners.toArray(new MyListener[listeners.size()]))
			{
				listner.handleEvent(event);
			}
		}

		public int getI()
		{
			return i;
		}
	}

	public static interface MyListener extends EventListener
	{
		public void handleEvent(MyEvent event);
	}

	public static class MyEvent extends EventObject
	{
		public MyEvent(Object source)
		{
			super(source);
		}
	}
}
 

ernst

Top Contributor
>Obwohl ich nur ein sich aenderendes Diagramm habe und das Diagramm weder die DiagrammPanel
>noch das JLabel kennt (und nichtmal weiss was ein DiagrammPanel ist), werden alle 7 Panels und das
>Label zeitnah aktualisiert - das ist der Zweck von Events/Listenern. In der main() methode siehst Du
>auch die Verwendung eines annonymen Listeners.
>
>
Erst mal vielen, herzlichen Dank für deinen Quellcode.
Habe sofort mit meiner Eclipse Entwicklungsumgebung ein Projekt erzeugt.
Leider kommt bei der folgenden Zeile eine Fehlermeldung:

private List<MyListener> listeners = new ArrayList<MyListener>();

Eclipse kann mit <MyListener> nichts anfangen.

Ich kenne das übrigens auch nicht (so weit ich mich erinnern ist das unter C++ ein Template).
Geht das auch ohne die eckigen Klammern?

mfg
Ernst
 

kleiner_held

Top Contributor
welche Java Version verwendest Du? Bei 1.4 oder älter gibts keine Generics, dann muss da einfach stehen:
Code:
private List listeners = new ArrayList();

und die for schleife in fireEvent() muss ungefähr so aussehen:
Code:
      protected void fireEvent()
      {
         MyEvent event = new MyEvent(this);
         MyListener[] listenerArray = (MyListener[]) listeners.toArray(new MyListener[listeners.size()]);
         for (int i = 0; i < listenerArray.length, i++)
         {
              listenerArray[i].handleEvent(event);
         }
      }
 

ernst

Top Contributor
>private List listeners = new ArrayList();[/code]
>
>und die for schleife in fireEvent() muss ungefähr so aussehen:
>protected void fireEvent()
>{
>MyEvent event = new MyEvent(this);
>MyListener[] listenerArray = (MyListener[]) listeners.toArray(new MyListener[listeners.size()]);
>for (int i = 0; i < listenerArray.length, i++)
>{
>listenerArray.handleEvent(event);
>}
>
Bis auf das fehlende Semikolon hat alles gepaßt (das habe ich korrigiert). Es wird fehlerfrei kompiliert und das Programm läuft.
Jetzt schaue ich mir in Ruhe mal den Quellcode an und bedanke mich derweil bei dir ganz herzlich, da du mir sehr geholfen hast. Ich hoffe, dass dann wieder mehr Klarheit in mein verwirrtes Hirn kommt.

mfg
Ernst
 
G

Guest

Gast
kleiner_held hat gesagt.:
welche Java Version verwendest Du? Bei 1.4 oder älter gibts keine Generics, dann muss da einfach stehen:
Code:
private List listeners = new ArrayList();

und die for schleife in fireEvent() muss ungefähr so aussehen:
Code:
      protected void fireEvent()
      {
         MyEvent event = new MyEvent(this);
         MyListener[] listenerArray = (MyListener[]) listeners.toArray(new MyListener[listeners.size()]);
         for (int i = 0; i < listenerArray.length, i++)
         {
              listenerArray[i].handleEvent(event);
         }
      }

Ich habe mir den Code angeschaut und habe dazu eine Frage:
MyListener[] listenerArray = (MyListener[]) listeners.toArray(new MyListener[listeners.size()]);

In meiner Doku steht über toArray folgendes:
Object[] toArray(Object[] a)

1) Mir ist nicht klar warum man das Array a benötigt. Wird es mit return zurückgegeben?
Dann würde man es doch nicht als input benötigen?

2) Was mir auch noch nicht klar ist:
MyListener ist ein Interface. Von einem Interface dürfen aber keine Objekte erzeugt werden.
Das wird doch aber mit:
MyListener[] listenerArray = (MyListener[]) listeners.toArray(new MyListener[listeners.size()]);
gemacht, oder?

mfg
Ernst
 

kleiner_held

Top Contributor
1. Der Parameter bei List.toArray() ist dazu da, der Liste zu sagen von welchem Typ der Array ist. Der Sachverhalt wird an dieser Stelle erklaert, deswegen spare ich mir mal die detailierten Ausfuehrungen.

2. Nein an der Stelle wird kein neuer MyListener erstellt, sondern es wird ein Array erstellt, der nur MyListener's enthalten kann. Als Inhalt bekommt er dann alle MyListener's aus der Liste zugewiesen. Wen Du in Hinsicht auf Arrays noch nicht ganz so bewandert bist, hier nochmal eine Literaturempfehlung: Java-Insel: 3.9 Arrays
ist uebrigens das gleiche Buch wie im obrigen Link.
 

ernst

Top Contributor
kleiner_held hat gesagt.:
1.
Der Parameter bei List.toArray() ist dazu da, der Liste zu sagen von welchem Typ der Array ist. Der Sachverhalt wird an dieser Stelle erklaert, deswegen spare ich mir mal die detailierten Ausfuehrungen.

Danke für die Links. Ich habe die Quelle gelesen und mir folgendes überlegt:

Wichtige Bemerkung zur Bezeichnung:
X sei eine Klasse, die das Interface Y implementiert.
Von X werde ein Objekt erzeugt:
X x;
dann sage ich:
a) x _ist_ ein X-Objekt (als solches im Arbeitsspeicher angelegt)
b) x _hat_ den Datentyp Y

Ist dies vernünftig, oder gibt es eine besser Möglichkeit der Bezeichnung?

1)
listeneres besteht aus Objekten, die aus einer anonymen Klasse, ich nenne
sie hier einfach mal Z, erzeugt wurden und die MyListener als Interface
enthalten:
diagramm.addListener(new MyListener()
{
public void handleEvent(MyEvent event)
{
label.setText(Integer.toString(diagramm.getI()));
}
});


Dies entspricht gleichwertig:

Z implements MyListener{
public void handleEvent(MyEvent event){
label.setText(Integer.toString(diagramm.getI()));
}
}

Also bestehen die Elemente von listeneres aus Z-Objekten und nicht aus
MyListener-Objekten.

Ist das richtig?


2)
Durch die Angabe von MyListener im Parameter von toArray wird erreicht,
dass toArray die Elemente von listeners in listenerArray reinkopiert und der
Datentyp MyListener ist.

Ist das richtig?

Frage:
Welchen Sinn har dann aber noch der cast-Operator MyListener[] vor listeners?
Muss dies nicht immer der gleiche Datentyp wie das Objekt im Parameter sein?

3)
Mit dem Parameter
new MyListener[listeners.size()]
wird zwar ein Array mit dem Datentyp MyListener erzeugt, aber es werden keine
MyListener-Objekte in dem Array erzeugt, sondern es wird ein Array erzeugt, das als
Werte Referenzen mit dem Wert "null" hat.

Ist das richtig?


4) Was mir noch völlig unklar ist:

diagramm.addListener(new MyListener()

ruft auf auf:

public void addListener(MyListener listener)
{
listeners.add(listener);
System.out.println("hallo1");
}

Das geschieht doch nur _einmal_ (ich sehe in main() nur einmal den Aufruf diagramm.addListener(new MyListener() und nirgends eine Schleife).
Warum erscheint trotzdem mehrmals die Ausgabe
hallo1

Wo ist mein Dekfehler?

mfg
Ernst
 

kleiner_held

Top Contributor
ich beantworte mal in anderer Reihenfolge

4) Du hast schon richtig erkannt, in Zeile 24 wird genau ein annonymer Listener erstellt, der die Aufgabe hat das Label zu aktualisieren und dieser Listener wird am Diagramm registriert.
In Zeile 20 werden aber in einer Schleife 7 DiagrammPanel's angelegt, die das Diagramm als Prameter fuer ihren Constructor bekommen. Und im Constructor von DiagrammPanel registriert sich das DiagrammPanel selbst als Listener am Diagramm (Zeile 44). Das ist moeglich, da die Klasse DiagrammPanel das Interface MyListener implementiert.

1) ist richtig fuer den annonymen Listener von Zeile 24, allgemein koennen aber in dem Array beliebige Objkete sein, die
MyListener implementieren. Um mal deinen Definitionen zu verwenden:
Die Elemente von listeneres bestehen aus Z-Objekten (1 mal), aber auch aus DiagrammPanel's (7 mal)

2) Der Cast ist noetig, da die Methode toArray() laut Deklaration nur einen Object[] array zurueckgibt. Der Compiler weiss nicht, das es in diesem Fall ein MyListener[] Array ist, deswegen muss man es ihm explizit sagen. Ab Java 1.5 ist dieser Cast aber tatsaechlich nicht mehr noetig, da der Compiler durch die Verwendung von Generics mitbekommt, dass der Typ des zurueckgegebenen Arrays gleich dem Typ des Parameter Arrys entspricht.

3) Richtig
 

ernst

Top Contributor
kleiner_held hat gesagt.:
ich beantworte mal in anderer Reihenfolge

4) Du hast schon richtig erkannt, in Zeile 24 wird genau ein annonymer Listener erstellt, der die Aufgabe hat das Label zu aktualisieren und dieser Listener wird am Diagramm registriert.
In Zeile 20 werden aber in einer Schleife 7 DiagrammPanel's angelegt, die das Diagramm als Prameter fuer ihren Constructor bekommen. Und im Constructor von DiagrammPanel registriert sich das DiagrammPanel selbst als Listener am Diagramm (Zeile 44). Das ist moeglich, da die Klasse DiagrammPanel das Interface MyListener implementiert.
------------------------------
Zu 4)
Ich habe folgendes nicht beachtet:
// wirkt sich auf diagramm in DiagrammPanel aus !!
this.diagramm = diagramm;
// wirkt sich auf diagramm in main aus !!
diagramm.addListener(this);
Aber jetzt ist mir es klarer.


Zu den anderen Punkten:
Ich schreibe es nochmals mit meinen Worten.
Wenn du damit einverstanden bist, nehme ich es zu meinen "Akten".

1)
listeneres besteht aus Objekten, die aus einer anonymen Klasse, ich nenne
sie hier einfach mal Z, erzeugt wurden und und DiagrammPanel-Objekten.
Diese enthalten MyListener jeweils als Interface.
Der folgende Programmteil nimmt z-Objekte in listeneres auf:

diagramm.addListener(new MyListener()
{
public void handleEvent(MyEvent event)
{
label.setText(Integer.toString(diagramm.getI()));
}
});


Dies entspricht gleichwertig:
Z implements MyListener{
public void handleEvent(MyEvent event){
label.setText(Integer.toString(diagramm.getI()));
}
}

Also bestehen die Elemente von listeneres aus Z-Objekten und DiagrammPanel-Objekten,
aber nicht aus MyListener-Objekten, aber diese Objekte haben alle den Datentyp
MyListener

2)
Durch die Angabe von MyListener im Parameter von toArray wird erreicht,
dass toArray die Elemente von listeners in listenerArray reinkopiert und der
Datentyp MyListener ist.

Frage:
Welchen Sinn har dann aber noch der cast-Operator MyListener[] vor listeners?
Muss dies nicht immer der gleiche Datentyp wie das Objekt im Parameter sein?

Antwort:
Wenn man es weg lassen würde, würde laut Deklaration von toArray der Datentyp
Object[] zurückgegeben.
Dann würde aber folgende Anweisung einen Compilerfehler ergeben:
MyListener[] listenerArray = listeners.toArray(new MyListener[listeners.size()]);
weil listenerArray ein Objekt vom Typ Object[] zugewiesen werden würde.


PS:
Das Programm ist ziemlich komplex, was man aber erst bei genauerer Durchsicht mitbekommt.

mfg
Ernst
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
G JavaDocu in eigener Bibliothek Allgemeine Java-Themen 2
HarleyDavidson Eigener PropertyChangeListener funktioniert einfach nicht Allgemeine Java-Themen 3
T Datei öffnen mit eigener Applikation.exe Allgemeine Java-Themen 4
D Arraylist eigener Klasse an iReport übergeben Allgemeine Java-Themen 7
K Jar mit eigener JRE ausliefern Allgemeine Java-Themen 13
G eigener PropertyChangedListener Allgemeine Java-Themen 2
S OOP ClassCastException bei casting von eigener Klasse aus Iterator Allgemeine Java-Themen 3
V Serialisierung von Instanz eigener Klasse Allgemeine Java-Themen 5
N Vergleich eigener Klassen Allgemeine Java-Themen 5
T Vererbung Eigener Datentyp: Betriebsmittel Allgemeine Java-Themen 2
J Erste Schritte Kommerzielle nutzung eigener Javaapplets auf der Homepage Allgemeine Java-Themen 2
B Probleme mit eigener equals Methode Allgemeine Java-Themen 18
Kr0e Eigener Updatemechanismus Allgemeine Java-Themen 7
J Mein eigener Messenger und dessen Probleme Allgemeine Java-Themen 48
S Profiler-Funktionen in eigener Applikation nutzen..? Allgemeine Java-Themen 5
R Eigener Comparator Allgemeine Java-Themen 2
T Zeit von einem Server/Webseite auslesen und in eigener GUI anzeigen Allgemeine Java-Themen 6
V Probleme mit eigener Hashmap Allgemeine Java-Themen 10
B Eigener ClassLoader Allgemeine Java-Themen 9
R Eigener Assoziativ-Speicher Allgemeine Java-Themen 7
T CP Problem: Webstart + Logging properties file + eigener Handler Allgemeine Java-Themen 7
P eigener Klassenname Allgemeine Java-Themen 4
D Eigener Key bei AES Verschlüsselung Allgemeine Java-Themen 4
T enums - eigener startwert Allgemeine Java-Themen 5
J Eigener ClassLoader wird nicht immer verwendet Allgemeine Java-Themen 3
P eigener Thread für einen JButton Allgemeine Java-Themen 32
F Checkbox in JTable , eigener Cellrenderer -wie gehts weiter? Allgemeine Java-Themen 2
A JRE auf eigener Seite verlinken oder zum Download anbieten? Allgemeine Java-Themen 13
G eigener logger mittels classe (dynamische logfilename) log4j Allgemeine Java-Themen 15
D Eigener Maven2 Plugin Server? Allgemeine Java-Themen 3
I RSA - Eigener Quelltext Allgemeine Java-Themen 4
M eigener LautstärkeRegler schädlich für soundkarte? Allgemeine Java-Themen 4
K JTree plus eigener FileLoader Allgemeine Java-Themen 2
L Problem mit eigener, abgeleiteter Klasse Allgemeine Java-Themen 2
S Eigener Editor Allgemeine Java-Themen 7
L Eigener Onlinestunden- Zähler / Problemchen Allgemeine Java-Themen 2
berserkerdq2 Was heißt es mit FXML Listener zu setzen ind Buttons zu erstellen? Allgemeine Java-Themen 6
L Wie programmiert man einen Listener? Allgemeine Java-Themen 1
S Threads Serielle Schnittstelle mit Listener / Aufrufendes GUI Allgemeine Java-Themen 4
H Listener Verständnisproblem Allgemeine Java-Themen 5
D Action Listener Problem Allgemeine Java-Themen 3
S Key Listener mit Strg + s Allgemeine Java-Themen 12
K Threads Listener für Future finish Allgemeine Java-Themen 2
TheWhiteShadow Listener Reihenfolge Allgemeine Java-Themen 4
D Listener auf System.out.err / System.out.println Allgemeine Java-Themen 5
A Listener für constructor einer bestimmen Klasse Allgemeine Java-Themen 9
E Bild mit Listener einfügen Allgemeine Java-Themen 3
P Listener für Tastatureingaben ohne Focus Allgemeine Java-Themen 4
serjoscha WatchDog Thread und Listener Allgemeine Java-Themen 10
hdi Listener für Desktop-Veränderungen Allgemeine Java-Themen 7
T JTextField in Listener leeren Allgemeine Java-Themen 2
lenniii Listener & JList Allgemeine Java-Themen 3
K Key listener ohne Fokus aktiv behalten ? Allgemeine Java-Themen 12
G Code-Convention für Listener Allgemeine Java-Themen 2
T Observer vs Listener Allgemeine Java-Themen 18
S Listener Allgemeine Java-Themen 3
P Abstrakte Elternklasse als Listener Allgemeine Java-Themen 6
MQue KeyAction listener Allgemeine Java-Themen 2
M generische Listener Allgemeine Java-Themen 2
S Listener für Kalender Allgemeine Java-Themen 2
B Observer vs Listener (GUI-Programmierung) Allgemeine Java-Themen 5
J Listener für Ende eines Threads gesucht... Allgemeine Java-Themen 5
S Listener Implentierung bei Eingabe in Textfeld Allgemeine Java-Themen 2
G Objekt einer inneren Klasse als Listener Allgemeine Java-Themen 3
D Boolean Listener? Allgemeine Java-Themen 28
M Listener und Performance Allgemeine Java-Themen 9
D Observer/Observable Pattern vs. Listener-Konzept Allgemeine Java-Themen 4
G Listener auf aktuelles Datum / Uhrzeit Allgemeine Java-Themen 2
Escorter Eigenen Listener schreiben Allgemeine Java-Themen 3
E Gibt es so etwas wie einen Windows Listener? Allgemeine Java-Themen 6
T SelectionProvider und Listener Frage Allgemeine Java-Themen 14
I Listener, der zeitlich-periodisch aufgerufen wird Allgemeine Java-Themen 3
R Generische Listener und Sender Allgemeine Java-Themen 12
B Listener dynamisch setzen Allgemeine Java-Themen 6
A Listener Tastatur Allgemeine Java-Themen 3
D Thread vs Listener Allgemeine Java-Themen 6
K Listener einem Objekt hinzufügen Allgemeine Java-Themen 3
S Listener-Problematik in komplexem Projekt Allgemeine Java-Themen 2
I Listener/Event selber machen. Allgemeine Java-Themen 4
M Time Listener ? Allgemeine Java-Themen 2
Z Zwei Listener zwischen zwei Klassen Allgemeine Java-Themen 4
B statusbar update -> mit thread oder listener? Allgemeine Java-Themen 7
M Action-listener Allgemeine Java-Themen 6
M Bean Listener hinzufügen und Methode später überschreiben Allgemeine Java-Themen 27
G Flavor-Listener Allgemeine Java-Themen 6
E Listener für Änderung der Fenstergröße Allgemeine Java-Themen 3
W Listener an ein beliebiges Objekt hänger, der mir Änderung Allgemeine Java-Themen 8
Z Problem beim Aufruf eines Listener? Allgemeine Java-Themen 4
A HILFE: subclass von Hashtable mit listener aufstellen Allgemeine Java-Themen 5
S Interface Design von HookUp oder Callback Methoden für eigenes Framework Allgemeine Java-Themen 9
L Variablen Eigenes Objekt wie z.B. einen Integer zuweisen Allgemeine Java-Themen 3
S Eclipse Github Projekt in eigenes Projekt einbinden und nutzen Allgemeine Java-Themen 13
B eigenes Consumer Interface Allgemeine Java-Themen 0
Thallius Eigenes Message Center erstellen Allgemeine Java-Themen 3
M eigenes Seekarten-Tool (oder PlugIn?) Allgemeine Java-Themen 2
Z LanguageTool in eigenes GUI einbetten Allgemeine Java-Themen 0
W String Parsen und auf eigenes Muster anwenden (kein Regex) Allgemeine Java-Themen 11
O log4j - eigenes Log für einzelne Klasse Allgemeine Java-Themen 5
M Eigenes Eventsystem Allgemeine Java-Themen 2
T Code durch eigenes Frame pausieren (ähnlich JDialog) Allgemeine Java-Themen 4

Ähnliche Java Themen

Neue Themen


Oben