Java Arbeiten mit Klassen

bawde

Lt. Commander
Registriert
Juli 2006
Beiträge
1.175
Hallo,

ich habe wieder mal ein grundsätzliches Problem mit Java :(

es geht um dieses Tutorial: StoppUhr

Mein Problem damit ist, alle Klassen sind in der Hauptklasse StoppUhr verschachtelt. Ich möchte aber alle Klassen "abgeschottet" benutzen, nur bekomme ich das nicht hin. Wenn ich von der Hauptklasse Stoppuhr Instanzen in den anderen Klassen erstelle, damit diese z.b. mit dem boolean "running" arbeiten können, funktionier das Programm nicht mehr.

Könnt ihr mir da weiterhelfen?


Der Code von mir probeweise abgeändert:
import java.awt.*;
import java.awt.event.*;

public class Stoppuhr extends Frame {

private Button start;
private Button stop;
public Label ausgabe;
public boolean running = false;

public Stoppuhr(){
super();
setLayout(null);
setTitle("Stoppuhr");
setResizable(false);
start = new Button("Start");
stop = new Button("Stop");
ausgabe = new Label();

start.setBounds(100,100,100,50);
stop.setBounds(220, 100, 100, 50);
ausgabe.setBounds(130, 175, 250, 50);

add(start);
add(stop);
add(ausgabe);
ausgabe.setFont(new Font(Font.SERIF,Font.PLAIN, 35));

start.addActionListener(new ButtonListenerStart());
stop.addActionListener(new ButtonListenerStop());

addWindowListener(new WindowLauscher());

}

public static void main(String[] args) {
Stoppuhr uhr = new Stoppuhr();
uhr.setBounds(0, 0, 500, 300);
uhr.setVisible(true);
}
}


class ButtonListenerStart implements ActionListener{

public void actionPerformed(ActionEvent e){
Stoppuhr uhr1 = new Stoppuhr();
boolean running = uhr1.running;

if(!running){
running = true;
UhrzeitThread uhr = new UhrzeitThread();
uhr.start();
}
}
}

class ButtonListenerStop implements ActionListener{
public void actionPerformed(ActionEvent e){
Stoppuhr uhr1 = new Stoppuhr();
boolean running = uhr1.running;

running = false;
}
}

class WindowLauscher extends WindowAdapter{
public void windowClosing(WindowEvent e){
Stoppuhr uhr1 = new Stoppuhr();
boolean running = uhr1.running;
running = false;
System.exit(0);
}
}

class UhrzeitThread extends Thread{
Stoppuhr uhr1 = new Stoppuhr();
boolean running = uhr1.running;

private int HS = 0;
private int sek = 0;
private int min = 0;
private int h = 0;

public void run(){
while(running){
try{Thread.sleep(9);}catch(Exception e){}
if(HS <= 99){
HS++;
} else {
HS = 0;
if(sek <= 59){
sek++;
}else {
sek = 0;
if(min <= 59){
min++;
} else {
min = 0;
h++;
}
}
}
uhr1.ausgabe.setText(h + " : " + min + " : " + sek + " : " + HS);
}
}
}
 
Zuletzt bearbeitet:
Ständig neue Instanzen der Stoppuhr erzeugen wird nicht funktionieren, das sollte klappen:

Code:
import java.awt.*;
import java.awt.event.*;

public class Stoppuhr extends Frame {

	private Button start;
	private Button stop;
	public Label ausgabe;
	public boolean running = false;

	public Stoppuhr(){
		super();
		setLayout(null);
		setTitle("Stoppuhr");
		setResizable(false);
		start = new Button("Start");
		stop = new Button("Stop");
		ausgabe = new Label();

		start.setBounds(100,100,100,50);
		stop.setBounds(220, 100, 100, 50);
		ausgabe.setBounds(130, 175, 250, 50);

		add(start);
		add(stop);
		add(ausgabe);
		ausgabe.setFont(new Font(Font.SERIF,Font.PLAIN, 35));

		start.addActionListener(new ButtonListenerStart(this));
		stop.addActionListener(new ButtonListenerStop(this));
		addWindowListener(new WindowLauscher(this));
	}

	public static void main(String[] args) {
		Stoppuhr uhr = new Stoppuhr();
		uhr.setBounds(0, 0, 500, 300);
		uhr.setVisible(true);
	}
}

class ButtonListenerStart implements ActionListener {
	Stoppuhr stoppuhr;
	public ButtonListenerStart(Stoppuhr stoppuhr) {
		this.stoppuhr = stoppuhr;
	}

	public void actionPerformed(ActionEvent e) {
		if(!stoppuhr.running){
			stoppuhr.running = true;
			UhrzeitThread uhr = new UhrzeitThread(stoppuhr);
			uhr.start();
		}
	}
}

class ButtonListenerStop implements ActionListener {
	Stoppuhr stoppuhr;
	public ButtonListenerStop(Stoppuhr stoppuhr) {
		this.stoppuhr = stoppuhr;
	}

	public void actionPerformed(ActionEvent e) {
		stoppuhr.running = false;
	}
}

class WindowLauscher extends WindowAdapter{
	Stoppuhr stoppuhr;
	public WindowLauscher(Stoppuhr stoppuhr) {
		this.stoppuhr = stoppuhr;
	}

	public void windowClosing(WindowEvent e){
		stoppuhr.running = false;
		System.exit(0);
	}
}

class UhrzeitThread extends Thread{
	private int HS = 0;
	private int sek = 0;
	private int min = 0;
	private int h = 0;

	Stoppuhr stoppuhr;
	public UhrzeitThread(Stoppuhr stoppuhr) {
		this.stoppuhr = stoppuhr;
	}

	public void run(){
		while(stoppuhr.running){
			try{Thread.sleep(9);}catch(Exception e){}
			if(HS <= 99){
				HS++;
			}
			else {
				HS = 0;
				if(sek <= 59){
					sek++;
				}else {
					sek = 0;
					if(min <= 59){
						min++;
					} else {
						min = 0;
						h++;
					}
				}
			}
			stoppuhr.ausgabe.setText(h + " : " + min + " : " + sek + " : " + HS);
		}
	}
}
 
Das Feld running sollte hier aber unbedingt volatile sein, sonst kann es (sehr wahrscheinlich) dazu führen, dass der Thread endlos läuft.
 
Wie ist das im realen Leben? Kaufst Du da jedes Mal eine neue Stoppuhr, wenn Du wissen willst, wieviel Zeit seit einem bestimmten Zeitpunkt vergangen ist? Wohl gemerkt, die Stoppuhr ist nagelneu und fängt wieder bei Null an! Wohl kaum! Entweder müssen dann alle Stoppuhren auf magische Weise voneinander wissen und sich selbstständig synchronisieren (das ließe sich tatsächlich abbilden). Oder aber Du verwendest genau eine Stopuhr. So wie im Original-Code.

Swing-Code gehört übrigens immer in den EDT. Der Code in der main()-Methode macht da keine Ausnahme.
 
Vielleicht meinst Du das Richtige. Es geht hier darum, dass der Zustand eines Objektes sich (normalerweise) nur auf dieses Objekt bezieht. Wenn Du zwei Objekte A und B hast, A änderst, hat das keine Auswirkungen auf B.

Wie im richtigen Leben. Wenn Du Stoppuhr 1 startest, später Stoppuhr 2, kannst Du bei 1 nicht ablesen, wieviel Zeit bei 2 vergangen ist. Wenn Du 1 anhältst, läuft 2 trotzdem weiter etc.

Die Lösung hier war das Objekt Stoppuhr den Listenern bekannt zu machen, damit diese dessen Zustand abfragen/ändern können. So wie das im Ursprungscode auch der Fall war.
 
bawde schrieb:
achso, das ist dann praktisch die wiederbenutzung von programmcode einer objektorientierten programmiersprache.

Nicht ganz, es wird nur eine Instanz der Stoppuhr wiederverwendet, dieser Code würde auch funktionieren:

Code:
import java.awt.*;
import java.awt.event.*;

public class Stoppuhr extends Frame {
	private Button start;
	private Button stop;
	public static Label ausgabe;
	public static boolean running = false;

	public Stoppuhr(){
		super();
		setLayout(null);
		setTitle("Stoppuhr");
		setResizable(false);
		start = new Button("Start");
		stop = new Button("Stop");
		ausgabe = new Label();

		start.setBounds(100,100,100,50);
		stop.setBounds(220, 100, 100, 50);
		ausgabe.setBounds(130, 175, 250, 50);

		add(start);
		add(stop);
		add(ausgabe);
		ausgabe.setFont(new Font(Font.SERIF,Font.PLAIN, 35));

		start.addActionListener(new ButtonListenerStart());
		stop.addActionListener(new ButtonListenerStop());
		addWindowListener(new WindowLauscher());
	}

	public static void main(String[] args) {
		Stoppuhr uhr = new Stoppuhr();
		uhr.setBounds(0, 0, 500, 300);
		uhr.setVisible(true);
	}
}

class ButtonListenerStart implements ActionListener {
	public void actionPerformed(ActionEvent e) {
		if(!Stoppuhr.running){
			Stoppuhr.running = true;
			new UhrzeitThread().start();
		}
	}
}

class ButtonListenerStop implements ActionListener {
	public void actionPerformed(ActionEvent e) {
		Stoppuhr.running = false;
	}
}

class WindowLauscher extends WindowAdapter {
	public void windowClosing(WindowEvent e){
		Stoppuhr.running = false;
		System.exit(0);
	}
}

class UhrzeitThread extends Thread {
	private int HS = 0;
	private int sek = 0;
	private int min = 0;
	private int h = 0;

	public void run(){
		while(Stoppuhr.running){
			try{Thread.sleep(9);}catch(Exception e){}
			if(HS <= 99){
				HS++;
			}
			else {
				HS = 0;
				if(sek <= 59){
					sek++;
				}else {
					sek = 0;
					if(min <= 59){
						min++;
					} else {
						min = 0;
						h++;
					}
				}
			}
			Stoppuhr.ausgabe.setText(h + " : " + min + " : " + sek + " : " + HS);
		}
	}
}

Dann wäre aber wirklich nur eine Stoppuhr möglich, würde man dann z.B testweise:
Code:
	public static void main(String[] args) {
		Stoppuhr uhr = new Stoppuhr();
		uhr.setBounds(0, 0, 500, 300);
		uhr.setVisible(true);

		Stoppuhr uhr2 = new Stoppuhr();
		uhr2.setBounds(500, 0, 500, 300);
		uhr2.setVisible(true);
	}
schreiben, würden beide Start & Stop-Buttons die selbe Stoppuhr starten/stoppen und die Zeit würde nur in einem Label angezeigt.
 
@Lynx: Und running sollte nach wie vor volatile sein.

Und statics würde ich ganz schnell in die Tonne kloppen... dann bitte lieber verschachtelte Klassen.

Und wenn wir schon bei Stil sind: Wenn der Thread schon ne eigene Klasse ist, warum muss der dann wissen, dass mit einem Label gearbeitet wird? Und der Zugriff auf das Label erfolgt aus dem falschen Thread heraus...

also ich würde in die Richtung gehen ...

Code:
public class Stoppuhr extends Frame {
	private Button start;
	private Button stop;
	private Label ausgabe;
	private volatileboolean running = false;

	public Stoppuhr(){
		super();
		setLayout(null);
		setTitle("Stoppuhr");
		setResizable(false);
		start = new Button("Start");
		stop = new Button("Stop");
		ausgabe = new Label();

		start.setBounds(100,100,100,50);
		stop.setBounds(220, 100, 100, 50);
		ausgabe.setBounds(130, 175, 250, 50);

		add(start);
		add(stop);
		add(ausgabe);
		ausgabe.setFont(new Font(Font.SERIF,Font.PLAIN, 35));

		start.addActionListener(new ButtonListenerStart());
		stop.addActionListener(new ButtonListenerStop());
		addWindowListener(new WindowLauscher());
	}

	public static void main(String[] args) {
 		javax.swing.SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
			Stoppuhr uhr = new Stoppuhr();
			uhr.setBounds(0, 0, 500, 300);
			uhr.setVisible(true);
            }
        });	
	}

	class ButtonListenerStart implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if(!running){
				running = true;
				new UhrzeitThread().start();
			}
		}
	}
	
	
	class ButtonListenerStop implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			running = false;
		}
	}
	
	class WindowLauscher extends WindowAdapter {
		public void windowClosing(WindowEvent e){
			running = false;
			System.exit(0);
		}
	}
	
	class UhrzeitThread extends Thread {
		private int HS = 0;
		private int sek = 0;
		private int min = 0;
		private int h = 0;
	
		public void run(){
			while(running){
				try{Thread.sleep(9);}catch(Exception e){}
				if(HS <= 99){
					HS++;
				}
				else {
					HS = 0;
					if(sek <= 59){
						sek++;
					}else {
						sek = 0;
						if(min <= 59){
							min++;
						} else {
							min = 0;
							h++;
						}
					}
				}
				
		 		javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
		ausgabe.setText(h + " : " + min + " : " + sek + " : " + HS);
            }
        });	
			}
		}
	}
}
 
Zuletzt bearbeitet:
Zurück
Oben