Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Gibt es in Java die Möglichkeit einen Listener für Variablen (boolsche Variablen) zu benutzen der anschlägt, wenn sich der Wert der Variable ändert oder muss man mit einer Endlosschleife immer abfragen?
(Variable aus anderer Klasse)
so, jetzt muss ich n kurzes Lob an dich und ans Forum loswerden.
Echt cool, so schnell eine Antwort zu haben und die Tatsache dass man im Forum dann auch schnell eine detailierte Beschreibung für das Listener schreiben findet, finde ich echt gut!
jetzt muss ich nur noch probieren ob ich das auch hinbekomm...
Im Prinzip ist die Sache ganz einfach. Du kannst auch Klassen wie zB das AbstractTableModel als Vorbild nehmen, da sie im Prinzip nicht viel anderes macht als Events zu feuern.
also das heißt (edit: bezogen auf erste Antwort von Wildcard), dass man den Listener nicht an die boolsche Variable hängt,
sondern an ein Objekt einer eigenen Klasse ObservedBoolean oder ähnliches,
dann kann man für Benachrichtigung sorgen:
privale boolean value;
public void setValue(boolean newValue) {
this.value = newValue;
// inform all registered Listeners
}
Also ich hab mir jetzt mal hier gelesen und des so mehr oder weniger abgeschrieben wie ichs verstanden hab und wie ichs für einen BooleanValueListener wohl brauche:
Code:
public interface BooleanValueListener {
public abstract booleanValueChanged(ChangeEvent);
}
Code:
public ChangeEvent {
public ChangeEvent() {
}
}
Code:
public class ObservedBoolean {
private Vector changeRecipients; // die Liste der Listener!
public ObservedBoolean() {
changeRecipients = new Vector();
}
public void addBooleanValueListener(BooleanValueListener listener) {
changeRecipients.add(listener);
}
public void removeBooleanValueListener(BooleanValueListener listener) {
changeRecipients.remove(listener);
}
public void fireChangeUpdate(ChangeEvent chEv) {
Iterator recIt = changeRecipients.iterator();
while(recIt.hasNext()) {
((ChangeListener)recIt.next()).changeHappened(chEv);
}
}
}
Mit anderen Worten ich habs nich richtig verstanden
was hast du nicht verstanden? sieht doch schon gut aus,
fehlt natürlich noch der boolean, die set-Operation und jemand der sich als Listener registeriert,
wenn du aber z.B. noch nie einen ActionListener bei einem Button eingesetzt hast,
dann ist das Prinzip wirklich nicht leicht zu verstehen
ich hab jetzt die 3 Klassen nochmal verändert und in ein package getan.
Code:
package BooleanListener;
import java.util.EventListener;
public interface BooleanListener extends EventListener {
public abstract void booleanValueChanged(ChangeEvent e);
}
Code:
package BooleanListener;
public class ChangeEvent {
boolean b;
public ChangeEvent(boolean b) {
this.b = b;
}
public boolean getValue(){
return b;
}
}
Code:
package BooleanListener;
import java.util.Vector;
import java.util.Iterator;
public class ObservedBoolean {
private Vector changeRecipients;
private boolean b;
public ObservedBoolean(boolean b) {
changeRecipients = new Vector();
this.b = b;
}
public void addBooleanListener(BooleanListener listener) {
changeRecipients.add(listener);
}
public void removeBooleanListener(BooleanListener listener) {
changeRecipients.remove(listener);
}
public void fireChangeUpdate(ChangeEvent chEv) {
Iterator recIt = changeRecipients.iterator();
while(recIt.hasNext()) {
((BooleanListener)recIt.next()).booleanValueChanged(chEv);
}
}
public void setValue(boolean newValue){
this.b = newValue;
}
}
Wenn ich das letztere allerdings compilieren will, kommt die Meldung:
Note: ObservedBollean.java uses unchecked or unsafe Operations.
Note: Recompile with -Xlint:unchecked for details.
(was ist Xlint:unchecked? ...Google brachte nichts)
Unter der Annahme das das mit dem Compilieren nun gegangen wäre, ist der Listener jetzt soweit in Ordung, dass man ihn etwa so verwenden könnte:
Code:
ObservedBoolean b1 = new ObservedBoolean();
ObservedBoolean b2 = new ObservedBoolean();
b1.addBooleanListener(this);
b2.addBooleanListener(this);
public void booleanValueChanged(ChangeEvent e){
if(e.getSource().equals(b1)) System.out.println("changed: " + b1);
if(e.getSource().equals(b2)) System.out.println("changed: " + b2);
}
das ChangeEvent solltest du leer lassen, dessen Aufgabe ist nur, zu übermitteln, dass sich was getan hat,
allein dass ein Event kommt, reicht
getSource() wäe tatsächlich eine passende Erweiterung, die hat den ChanceEvent noch nicht!
um dann den aktuellen Wert zu bekommen müsste man bei getSource() den Value nachfragen
so würde das eine ChangeEven in beliebigen Oberserved funktionieren, auch ObserveredString, ObserveredInt usw.
--------
wo werden hier die Listener über eine Änderung informiert?
welche bereits vorhandene Operation musst du hier wohl aufrufen, damit die Informierung ihren Lauf nimmt?
Das ist lediglich eine Warnung das du keine Generics verwendest, die Liste also nicht typsicher ist. Das kannst du ignorieren, oder Generics einbauen. Die Funktionalität ist davon nicht beeinträchtigt.
Code:
public void setValue(boolean newValue){
this.b = newValue;
}
Hier müsstest du noch die fire Methode aufrufen um die Listener zu benachrichtigen (und eventuell vorher überprüfen ob nicht versucht wird den gleichen Wert erneut zu setzen, dann braucht man nämlich kein Event zu feueren.
besser new ChangeEvent(this), denn this ist der Button,
noch besser ist in diesem Fall vielleicht fireValueUpdate(); ohne Parameter,
das simple new ChangeEvent(this) kann fireValueUpdate(); selber erstellen
-----
da das Event so allgemein ist, könnte der Listener übrigens auch ganz allgemein
ChangeListener oder so heißen, muss nicht nur für Boolean ausgelegt sein
besser new ChangeEvent(this), denn this ist der Button,
noch besser ist in diesem Fall vielleicht fireValueUpdate(); ohne Parameter,
das simple new ChangeEvent(this) kann fireValueUpdate(); selber erstellen
-----
da das Event so allgemein ist, könnte der Listener übrigens auch ganz allgemein
ChangeListener oder so heißen, muss nicht nur für Boolean ausgelegt sein
> source ist also ein Boolean, true oder false? ...
ich versteh nich ganz was du damit meint. Dass ich source nicht als Object sondern als boolean deklarisieren soll? Ich hab halt gedacht sie Quelle is ja ein Objekt:"ObservedBoolean"
fireValueUpdate ohne parameter geht nicht...
ich nehm mal an du meintest statt
fireValueUpdate(new ChangeEvent(...)) soll ich einfaches n neues ChangeEvent(ChangeEvent c = new ChangeEvent...?) erzeugen was dann von selbst das fireValueUpdate aufruft...?
Sorry für die vielen Fragen, aber ich bin halt neu in Java und hab auch sonst keine Programmiererfahrung...
ich hab nun versucht ein Testprogramm zu schreiben, aber:
Code:
import BooleanListener.*;
public class test{
ObservedBoolean b1 = new ObservedBoolean(true);
b1.addBooleanListener(this);
ObservedBoolean b2 = new ObservedBoolean(true);
b2.addBooleanListener(this);
public static void main(String args[]){
b1.setValue(false);
//...
b2.setValue(false);
//...
}
public void booleanValueChanged(ChangeEvent e){
if(e.getSource().equals(b1)) System.out.println("1");
if(e.getSource().equals(b2)) System.out.println("2");
}
}
lässt sich nicht kopieren, da bei addBooleanListener jeweils ein <identifier> expected wird. Das ein Kistener schreiben solang dauern kann ... *müdegrins*
Ich bräuchte schon wieder Hilfe mit einem Listener :-(
Und zwar habe ich nun eine Instanz einer Klasse MathVector und bräuchte nun einen Listener der auf eine Änderung von mathVetor.getNorm() reagiert und irgendwie hab ichs bisher nicht geschafft so einen selber zu schreiben :-(
Ich hab mehrere Sachen probiert, ich stell hier mal kurz meinen letzten Versuch rein:
Code:
package ValueListener;
import java.util.EventListener;
public interface ValueListener extends EventListener {
public abstract void valueChanged(ChangeEvent e);
}
Code:
package ValueListener;
public class ChangeEvent {
protected Object source;
public ChangeEvent(Object obj) {
source = obj;
}
public Object getSource() {
return source;
}
}
Code:
package ValueListener;
import java.util.Vector;
import java.util.Iterator;
import MathVec.MathVector;
public class ObservedVector extends MathVector{
private Vector<ValueListener> changeRecipients;
private int dirX;
private int dirY;
private double norm;
public ObservedVector(MathVector vector) {
changeRecipients = new Vector<ValueListener>();
this.dirX = vector.getDirX();
this.dirY = vector.getDirY();
this.norm = vector.getNorm();
}
public ObservedVector(int dirX, int dirY) {
super(dirX, dirY);
}
public void addValueListener(ValueListener listener) {
changeRecipients.add(listener);
}
public void removeValueListener(ValueListener listener) {
changeRecipients.remove(listener);
}
public void fireValueUpdate() {
ChangeEvent chEv = new ChangeEvent(this);
Iterator recIt = changeRecipients.iterator();
while(recIt.hasNext()) {
((ValueListener)recIt.next()).valueChanged(chEv);
}
}
public void setValue(double newNorm){
if(getNorm() != newNorm){
setNorm(newNorm);
fireValueUpdate();
}
}
}
Also die klasse an ders hängt ist ObservedVector, ich denke nicht dass die andern 2 falsch sind (oder...?).
Ich hoff hier kann mir jemand helfen!
Also ich hab jetzt weiterprogrammiert und das mal weggelassen und stehe nun vor einem ähnlichen Problem.
Ich beschreib es jetzt einfach mal vereinfacht und wie ich mir einen möglichen Lösungsweg vorstelle (so mehr oder weniger):
Ich habe eine Klasse die ein Component (ich nenn es hier mal DrawComponent) erzeugt, auf dem der Benutzer eine Linie malen kann / soll und eine Klasse die ein Component (ich nenn es hier mal DisplayComponent) erzeugt, das nachher die Länge ausgeben soll. Die Eingabe einer Länge ist hier auch möglich wobei sich dann wieder die Linienlänge des Malfeldes ändern soll. Beide Klassen verfügen über jeweils eine set und get Methode um die aktuelle Länge zu erhalten und einzustellen. Jetzt muss ich halt noch die Interaktion zwischen beiden regeln. Ich bin der Ansicht das hier wohl auch das Observer Pattern verwenden muss.
Jetzt habe ein Interface eines Listener, ein einfaches Event und brauche nun noch das Objekt, welches den Listener erhält.
Für dieses Objekt schreibe ich eine Unterklasse zu DrawComponent und eine Unterklasse zu DisplayComponent, die dann alle Methoden etc erben und füge noch die Methoden: addListener, removeListener, fireValueUpdate, und setValue (in der ich dann fireValueUpdate aufrufe) hinzu.
Nun verwende ich bei der erstellung meines GUIs einfach die Unterklassen von DrawComponent und DisplayComponent, statt ebendiesen beiden.
So in etwa stell ichs mir vor, stimmt das soweit?
Wenn ja: Ich versteh die setValue Methode nicht ganz. Letzendlich soll fireValueUpdate ja aufgerufen werden, sobald sich zB ObservedDrawComponent.getLength() ändert.
Funktioniert das ganze dann wenn die Methode so aussieht:
Code:
double length = getLength();
public void setValue(double newLength){
if(length != newLength){
setLength(newLength);
fireValueUpdate();
}
}
Ich frage das ganze weil ich heut nun schon ewig an dem (und dem oben genannten Problem sitze und es bisher noch nicht funktioniert.
Danke für jede Hilfe!
> habe ich ja geschrieben... nur anscheinend falsch, da es nicht funktioniert
?
1. ist im obigen Post nix von setValue() zu sehen, und
2. wenn du damit Probleme hast, dann musst du die beschreiben..
> So in etwa stell ichs mir vor, stimmt das soweit?
ich habe in 5 Jahren das System 1-2x eingesetzt, du 2x innerhalb einer Woche,
wahrscheinlich alles unnötig
> Ich versteh die setValue Methode nicht ganz.
tolle Problembeschreibung..
> Funktioniert das ganze dann wenn die Methode so aussieht:
so was zu fragen ist nicht völlig falsch, aber ich schlage dir mal was effives vor:
du programmierst alleine und wenn was nicht geht, dann sagst du Bescheid
und benennst genau die Probleme
DerMeinung bin ich auch deshalb hab ich in meinem Post vorher ja beschrieben was ich programmieren will. Wenns da ne andere Möglichkeit gibt wär ich froh...
zu setValue() nochmal ich meinte die Methode in dem letzten Code 2 Beiträge von mir hier drüber in Z. 42
Und ein Problem näher zu beschreiben ist halt schwierig wenn man codet etc compilieren geht nur der Listener funktioniert nicht so wie man es erwartet. Ich hab ja nicht gleich hier ins Forum geschrieben, sondern erst mal noch 2 stunden rumprogramiert und im INeT gesucht. Hier hab ich das ganze halt nochmal geschrieben in der Hoffnung das euch spontan was auffällt oder so..
naja ich seh ein das man mit der Problembeschreibung schwer helfen kann, auch wenn ich nicht in der Lage bin es grad besser zu beschreiben.
> zu setValue() nochmal ich meinte die Methode in dem letzten Code 2 Beiträge von mir hier drüber in Z. 42
wenn die schon immer da war, dann bin ich blind, sorry,
dadrin wird getNorm() benutzt, ist das überhaupt definiert?
und so schwer kann das ja nicht zu verfolgen sein,
überall System.out.prinltn() a la
'Wert geändert',
'informiere x Listener'
'Listener y enthält Event'
usw,
dann siehst du ja, wo die Liste unterbrochen ist