Stil-und Lesbarkeit des Codes

Gucky

Top Contributor
Hallo liebe Community,
nach langer Zeit komme ich mal wieder mit einer Frage an euch heran.

Für die Schule musste ich ein Programm schreiben, welches wahlweise iterativ oder Rekursiv die Wurzel einer Zahl nach dem Heronverfahren berechnet. Die Basis sowie die Anzahl der Schritte sind frei wählbar.
Das funktioniert auch gut. Ich bin aber mit meinem Code noch nicht so ganz zufrieden und möchte euch mal fragen, ob ich an meinem Code noch etwas verändern sollte oder ob der so geht:


Java:
public class Heron{
	Hauptframe hf=null;
	String dieWuzeletc=null;//Dies ist ein Teil des Textes, der auf einem Label stehen soll, auf den auch die Wurzel kommt
	
	public void machLogik(final boolean rek, final double basis, final double schritte){//Diese Methode wird mit den entsprechenden Parametern aus der GUI-Klasse aufgerufen
		class RechenThread extends Thread implements Runnable{//Der Thread, weil bei höheren Schrittzahlen das Programm die GUI blockiert, ich diese Schrittzahlen aber dennoch zulassen möchte
			double ergebnis=0;
		
			public void run(){
				if (rek){
					ergebnis=rekHeron(basis,schritte,quadratzahlen(basis));
				} else {
					ergebnis=itHeron(basis,schritte,quadratzahlen(basis));
				}
				hf.lblDieWurzelIst.setText(dieWuzeletc+ergebnis);
			}
		}
		RechenThread rechne=null;
		rechne = new RechenThread();
		rechne.start();
	}


	private double itHeron(double basis,double schritte, int kleinereQuadratzahl){
		double zwischenergebnis=kleinereQuadratzahl;
		for (int i=0;i<schritte;i++){
			zwischenergebnis=(zwischenergebnis+(basis/zwischenergebnis))/2;
		}
		return zwischenergebnis;
	}

	private double rekHeron(double basis, double schritte, double zwischenergebnis){
		try{//Die Try-catch Umgebung, da ich einen StackOverFlowError bei zu hohen Schrittzahlen bekomme. Da ich davon ausgehe, dass diese Exception Computerspezifisch ausgelöst wird, wollte ich keine Schrittzahl vorgeben
			if (schritte>0){
				zwischenergebnis=(zwischenergebnis+(basis/zwischenergebnis))/2;
				schritte--;
				return rekHeron(basis,schritte,zwischenergebnis);
			}
			return zwischenergebnis;
		} catch (java.lang.StackOverflowError e){
			return zwischenergebnis;
		} 
		
	}

	private int quadratzahlen(double basis){
		int quadratzahl=0;
		int zähler=1;
		while (quadratzahl<basis){
			quadratzahl=zähler*zähler;
			zähler++;
		}
		return quadratzahl;
	}
	
	public Heron(Hauptframe hf, String dieWuzeletc){
		this.hf=hf;
		this.dieWuzeletc=dieWuzeletc;
	}

}
 

rme

Top Contributor
Hallo :)

Lesbarkeit:
  • Leerzeichen um Operatoren sind leserlicher, also [c]a + b[/c] und [c]a = b[/c] statt [c]a+b[/c] und [c]a=b[/c]
  • Konstruktor und public-Methoden ganz nach oben, da das die Sachen sind, die man von außen wissen möchte, wenn man die Klasse als Fremder benutzt
  • "machLogik" ist ein seltsamer Name für eine Methode, ebenso "dieWuzeletc"

Stil:
  • Heron ist eigentlich eine reine Rechenklasse - Strings, Frames und Threads haben darin nix zu suchen. Der Aufrufer kann den Thread erzeugen, in dem dann machLogik läuft. Das Ergebnis kommt über einen Listener oder ähnliches an die GUI zurück, die dann die String-Darstellung erzeugt. Die Klasse SwingWorker bietet sich dazu an, es gibt hier auch ein Tutorial von turtle dazu.
  • es ist schlechter Stil, Variablen beim Deklarieren direkt zu definieren, d.h. sowas wie [c]RechenThread rechne=null;[/c]. Den Grund habe ich hier mal beschrieben.
  • warum ist "schritte" ein double? Du benutzt das nur zum Zählen. Falls es wegen des großen Wertebereichs ist: Nimm lieber long. Wenn das nicht reicht: Zählerklasse, die einen long-Überlauf in einer zweiten long speichert. Oder BigInteger nehmen.
 
Zuletzt bearbeitet:

Gucky

Top Contributor
Danke. Dann werde ich mich gleich mal an daran machen deine Tipps einzubauen. Ich melde mich dann wieder. :)
 
Zuletzt bearbeitet:

rme

Top Contributor
Noch eine Kleinigkeit: Wenn man deine Klasse in der Praxis benutzen möchte, hat man keine Ahnung davon, wie genau dein Algorithmus abhängig von der Anzahl der Schritte ist. Es wäre besser, die Fehlerschranke zu übergeben, die unterschritten werden soll.

Du kannst beispielsweise recht einfach prüfen, wie genau dein Zwischenergebnis ist, indem du es quadrierst und berechnest, wie weit es von der Eingabe entfernt ist. Und diese Entfernung interessiert den Anwender - er möchte z.B., dass das Ergebnis nach dem Quadrieren nur um 0.001 vom richtigen Ergebnis abweicht. Die GUI könnte also nach der Genauigkeit fragen und am Ende die Anzahl der benötigten Schritte ausgeben, das fände ich auch didaktisch sinnvoller.
 

Gucky

Top Contributor
Hallo,
danke für deinen zweiten Tipp.
Ich habe den Listener implementiert und das Ergebnis von der Genauigkeit abhängig gemacht. Es hat auch eine kurze Zeit funktioniert, dann nicht mehr. Keine Ahnung warum. :)

Ich poste jetzt mal den gesamten Code des Projektes. Wahrscheinlich ist der Fehler zu offensichtlich.

Die GUI-Klasse:
Java:
import javax.swing.SwingUtilities;

public class Hauptframe extends JFrame implements ErgebnisGeändertEventListener {

	private static final long serialVersionUID = 1L;
	private JPanel jContentPane = null;
	private JTextField textFieldBasis;
	private JTextField textFieldGenauigkeit;
	private ButtonGroup btnGroup;
	private Heron her=new Heron();
	private JTextField textFieldErgebnis;
	private JTextField textFieldZeit;
	private RechenThread rech;
	private JRadioButton rdbtnRekursiv;
	private JTextField textFieldSchrittzahl;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				Hauptframe thisClass = new Hauptframe();
				thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				thisClass.setVisible(true);
			}
		});
	}
	
	
	@Override
	public void ergebnisGeändert(ErgebnisGeändertEvent e) {
		textFieldErgebnis.setText(""+e.getErgebnis());
		textFieldSchrittzahl.setText(""+e.getSchritte());
	}
	
	private class RechenThread extends Thread implements Runnable{
		public void run(){
			long zeit = System.currentTimeMillis();
			her.rechneWurzel(rdbtnRekursiv.isSelected(), Double.parseDouble(textFieldBasis.getText()),
				Double.parseDouble(textFieldGenauigkeit.getText()));
			textFieldZeit.setText(""+(System.currentTimeMillis() - zeit));
		}
	}
	

	/**
	 * This is the default constructor
	 */
	public Hauptframe() {
		super();
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(438, 167);
		this.setContentPane(getJContentPane());
		this.setTitle("Heron");
		this.setLocationRelativeTo(null);
		this.her.addErgebnisGeändertListener(this);
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(null);
			
			btnGroup=new ButtonGroup();
			
			rdbtnRekursiv = new JRadioButton("Rekursiv");
			rdbtnRekursiv.setBounds(6, 32, 86, 23);
			rdbtnRekursiv.setSelected(true);
			jContentPane.add(rdbtnRekursiv);
			btnGroup.add(rdbtnRekursiv);
			
			JLabel lblBerechnungsmethodenwhlen = new JLabel("Berechnungsmethode w\u00E4hlen");
			lblBerechnungsmethodenwhlen.setBounds(6, 11, 150, 14);
			jContentPane.add(lblBerechnungsmethodenwhlen);
			
			JRadioButton rdbtnIterativ = new JRadioButton("Iterativ");
			rdbtnIterativ.setBounds(6, 58, 89, 23);
			jContentPane.add(rdbtnIterativ);
			btnGroup.add(rdbtnIterativ);
			
			textFieldBasis = new JTextField();
			textFieldBasis.setBounds(188, 33, 86, 20);
			jContentPane.add(textFieldBasis);
			textFieldBasis.setColumns(10);
			
			JLabel lblBasis = new JLabel("Basis");
			lblBasis.setBounds(215, 11, 46, 14);
			jContentPane.add(lblBasis);
			
			JLabel lblGenauigkeit = new JLabel("Genauigkeit");
			lblGenauigkeit.setBounds(301, 11, 69, 14);
			jContentPane.add(lblGenauigkeit);
			
			textFieldGenauigkeit = new JTextField();
			textFieldGenauigkeit.setBounds(284, 33, 86, 20);
			jContentPane.add(textFieldGenauigkeit);
			textFieldGenauigkeit.setColumns(10);
			
			textFieldErgebnis = new JTextField("");
			textFieldErgebnis.setEditable(false);
			textFieldErgebnis.setBounds(280, 83, 132, 14);
			jContentPane.add(textFieldErgebnis);
			
			
			JButton btnBerechnen = new JButton("Berechnen");
			btnBerechnen.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					System.out.println("Befehl zum Rechnen wird gesendet");
					bereinigeTextfelder();
					textFieldErgebnis.setText("Die Wurzel wird berechnet");
					rech = null;
					rech = new RechenThread();
					rech.start();
				}

				private void bereinigeTextfelder() {
					String basis=textFieldBasis.getText();
					String schritte=textFieldGenauigkeit.getText();
					
					if ("".equals(basis)){
						textFieldBasis.setText("0");
					}
					if ("".equals(schritte)){
						textFieldGenauigkeit.setText("0");
					}
					
					if (basis.charAt(0)=='0'){
						textFieldBasis.setText(basis.replaceAll("[^0-9.]", ""));
					} else {
						textFieldBasis.setText("0"+basis.replaceAll("[^0-9.]", ""));
					}
					if (schritte.charAt(0)=='0'){
						textFieldGenauigkeit.setText(schritte.replaceAll("[^0-9.]", ""));
					} else {
						textFieldGenauigkeit.setText("0"+schritte.replaceAll("[^0-9.]", ""));
					}
				}
			});
			btnBerechnen.setBounds(6, 88, 104, 23);
			jContentPane.add(btnBerechnen);
			
			JLabel lblTextDieWurzelIst = new JLabel("Die Wurzel ist ungef\u00E4hr:");
			lblTextDieWurzelIst.setBounds(124, 83, 137, 14);
			jContentPane.add(lblTextDieWurzelIst);
			
			JLabel lblBerechnungsdauer = new JLabel("Berechnungsdauer in ms:");
			lblBerechnungsdauer.setBounds(123, 101, 151, 14);
			jContentPane.add(lblBerechnungsdauer);
			
			JLabel lblNewLabel_1 = new JLabel("");
			lblNewLabel_1.setBounds(215, 101, 46, 14);
			jContentPane.add(lblNewLabel_1);
			
			textFieldZeit = new JTextField();
			textFieldZeit.setEditable(false);
			textFieldZeit.setBounds(280, 101, 132, 14);
			jContentPane.add(textFieldZeit);
			textFieldZeit.setColumns(10);
			
			JLabel lblBentigteSchritte = new JLabel("Ben\u00F6tigte Schritte");
			lblBentigteSchritte.setBounds(124, 67, 137, 14);
			jContentPane.add(lblBentigteSchritte);
			
			textFieldSchrittzahl = new JTextField("");
			textFieldSchrittzahl.setEditable(false);
			textFieldSchrittzahl.setBounds(280, 67, 132, 14);
			jContentPane.add(textFieldSchrittzahl);
		}
		return jContentPane;
	}
}

Die Klasse Heron:
Java:
public class Heron extends Object{
	private ErgebnisGeändertEventMulticaster egem = new ErgebnisGeändertEventMulticaster();
	
	private double ergebnis;
	private long schritte;
		
	public Heron(){
		ergebnis = 0;
		schritte = 0;
	}
	
	public void addErgebnisGeändertListener(ErgebnisGeändertEventListener egel){
		egem.add(egel);
	}
	
	public void removeErgebnisGeändertListener(ErgebnisGeändertEventListener egel){
		egem.remove(egel);
	}
	
	private void processGeändertesErgebnis(){
		egem.ergebnisGeändert(new ErgebnisGeändertEvent(this, ergebnis, schritte));
	}
	
	public void rechneWurzel(boolean rek, double basis, double genauigkeit){//basis und schritte sind bekannt
		ergebnis = 0;
		schritte = 0;
		if (rek){
			System.out.println("Die Wurzel wird rekursiv berechnet");
			rekHeron(basis,genauigkeit,quadratzahlen(basis),0);
		} else {
			System.out.println("Die Wurzel wird iterativ berechnet");
			itHeron(basis,genauigkeit,quadratzahlen(basis));
		}
	}
	
	private void itHeron(double basis,double genauigkeit, int kleinereQuadratzahl){
		double zwischenergebnis=kleinereQuadratzahl;
		long schrittzahl = 0;
		
		while(entfernung(zwischenergebnis, quad(zwischenergebnis))>genauigkeit){
			schrittzahl++;
			zwischenergebnis = (zwischenergebnis + (basis / zwischenergebnis)) / 2;
		}
		this.ergebnis = zwischenergebnis;
		this.schritte=schrittzahl;
		processGeändertesErgebnis();
	}
	
	
	private void rekHeron(double basis, double genauigkeit, double zwischenergebnis,long schrittzahl){
		try{
			if (entfernung(zwischenergebnis, quad(zwischenergebnis))>genauigkeit){
				zwischenergebnis = (zwischenergebnis + (basis / zwischenergebnis)) / 2;
				schrittzahl++;
				rekHeron(basis,genauigkeit,zwischenergebnis,schrittzahl);
			} else {
				this.ergebnis = zwischenergebnis;
				this.schritte=schrittzahl;
				processGeändertesErgebnis();
			}
		} catch (java.lang.StackOverflowError e){
			this.ergebnis = zwischenergebnis;
			this.schritte = schrittzahl;
			processGeändertesErgebnis();
		}
	}
	
	
	private int quadratzahlen(double basis){
		int quadratzahl=0;
		int zähler=1;
		while (quadratzahl<basis){
			quadratzahl=zähler*zähler;
			zähler++;
		}
		return quadratzahl;
	}
	
	private double quad(double paramDouble){
		return paramDouble*paramDouble;
	}
	
	private double entfernung(double basis, double entfernungsZahl){
		double entfernung=basis-entfernungsZahl;
		
		if (entfernung<0)return -entfernung;
		else return entfernung;
	}
}

Die Klasse ErgebnisGeändertEvent:
Java:
import java.util.EventObject;

@SuppressWarnings("serial")
public class ErgebnisGeändertEvent extends EventObject {
	protected double ergebnis;
	protected long schritte;
	

	public ErgebnisGeändertEvent(Object source, double ergebnis, long schritte) {
		super(source);
		this.ergebnis=ergebnis;
		this.schritte=schritte;
	}

	double getErgebnis(){
		return ergebnis;
	}
	
	long getSchritte(){
		return schritte;
	}

}

Das Interface ErgebnisGeändertEventListener:
Java:
import java.util.EventListener;

public interface ErgebnisGeändertEventListener extends EventListener {
	public void ergebnisGeändert(ErgebnisGeändertEvent e);
}

Die Klasse ErgebnisGeändertEventMulticaster:
Java:
import java.util.ArrayList;


public class ErgebnisGeändertEventMulticaster implements ErgebnisGeändertEventListener {
	ArrayList<ErgebnisGeändertEventListener>listener=new ArrayList<ErgebnisGeändertEventListener>();
	
	public ErgebnisGeändertEventMulticaster(){
		
	}
	
	public void add(ErgebnisGeändertEventListener egl){
		listener.add(egl);
	}
	
	public void remove (ErgebnisGeändertEventListener egl){
		listener.remove(egl);
	}

	@Override
	public void ergebnisGeändert(ErgebnisGeändertEvent e) {
		for (ErgebnisGeändertEventListener egvl:listener){
				egvl.ergebnisGeändert(e);
		}
	}
	
}


So. Das ist wahrscheinlich der längste Post, den die Welt je gesehen hat. :D

Es ist wirklich sehr wichtig, dass das Programm noch dieses Wochenende läuft. Deshalb bitte ich um schnelle Hilfe. :)
 
Zuletzt bearbeitet:

rme

Top Contributor
Bitte lade das mal als ZIP oder so hoch, das Rauskopieren zum Testen ist mir gerade zu mühsam. Ansonsten werden jetzt mehrere Sachen sichtbar:

  • das mit SwingUtilities.invokeLater brauchst du nicht. Das muss man erst machen, sobald setVisible gemacht wurde. Du machst es genau richtig, in main die GUI zu erzeugen und zuletzt setVisible aufzurufen - durch diese Vorgehensweise kann man auf das invokeLater verzichten und es ganz normal machen.
  • "Berechnungsmethode w\u00E4hlen" deutet darauf hin, dass dein Editor nicht auf Unicode gestellt ist, sonst hättest du den Umlaut direkt verwenden können. Pass deinen Editor an Java an, statt Java an deinen Editor anzupassen ;)
  • mit setLayout(null) verwendest du das sogenannte NullLayout - das sollte man nicht machen, denn so kann das Fenster nicht sinnvoll in der Größe geändert werden. Mein Monitor hat z.B. eine Auflösung von 1600x1200, darauf wäre mir deine Anwendung mit ihren 400 Pixeln in der Breite viel zu winzig, aber ich könnte sie nicht vergrößern. Langfristig solltest du die Benutzung von Layouts lernen.
  • Zeitmessung mit currentTimeMillis ist keine gute Idee, siehe hier
  • Die Umsetzung mit den Events und dem Multicaster ist natürlich cool, für so ein kleines Projekt aber vermutlich übertrieben - bei uns gab's immer Ärger, wenn man sich an solchen Feinheiten verbissen hat, statt nur die eigentliche Aufgabe zu lösen :)
 
Zuletzt bearbeitet:

Gucky

Top Contributor
Das mit invokeLater hat mir eclipse so hingebastelt. Da hab ich nichts dran getan. :)
Den Unicode habe ich umgestellt.
Den Umgang mit LayoutManagern kann ich schon mehr oder weniger. Ich kenne nur kein Passendes Layout für meine Anordnung gefunden.
Die Zeitmessung ist angepasst.
Wie würdest du es denn stattdessen machen? Ich habe die Events hier her. Wegen dem Wort "Listener" habe ich sofort an Events gedacht.

Im Anhang ist der Code einmal als eclipse Projekt und nur als Text.

Anhang anzeigen Code.zip

Anhang anzeigen Heron.zip
 

rme

Top Contributor
Super, dass du es als Eclipse-Projekt hochgeladen hast, so kann ich es mir direkt anschauen :)

Als ersten Eindruck der Probleme des Null-Layouts mal ein Screenshot, wie es bei mir aussieht. Beachte auch die Feinheiten wie die Höhe des Buttons usw. Am Code habe ich nix geändert, das Null-Layout ist eben nicht geeignet, um damit irgendwas zu machen :/
 

Anhänge

  • Screen Shot 2013-12-14 at 20.14.49.png
    Screen Shot 2013-12-14 at 20.14.49.png
    40,5 KB · Aufrufe: 31

Gucky

Top Contributor
Ok. Da hast du wohl recht. Dann werde ich das mal anpassen. Kannst du trotzdem etwas zum Code und den Problemen darin sagen?
 

rme

Top Contributor
Ja, das Problem habe ich herausgefunden: Du rechnest ja in einem eigenen Thread, damit die GUI weiterläuft. Es ist in Swing aber verboten, aus einem eigenen Thread heraus GUI-Elemente zu ändern. Da du das machst, siehst du die Änderungen manchmal nicht. Betroffen sind die Methode "ergebnisGeändert", denn die wird via Listener aus dem Rechenthread aufgerufen, beheben z.B. so:

Java:
@Override
public void ergebnisGeändert(final ErgebnisGeändertEvent e) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            textFieldErgebnis.setText(""+e.getErgebnis());
            textFieldSchrittzahl.setText(""+e.getSchritte());
        }
    });
}

Das gleiche im run() des RechenThread, da dort das Feld mit der Zeit gesetzt wird.

Weitere Probleme: Wenn man Felder frei lässt, gibt's eine Exception in der Konsole statt eine Fehlermeldung in der GUI. Die Verwendung von eigenen Methoden für quad() und entfernung() finde ich übertrieben. quad(x, x) kann man direkt als x * x schreiben, entfernung(a, b) als Math.abs(a - b). Der letzte Punkt ist allerdings Geschmacksache, kann man auch durchaus so lassen.
 
Zuletzt bearbeitet:

rme

Top Contributor
Ich würde die Klasse ungefähr so implementieren (nur als Anregung gemeint, ich hab's nicht weiter getestet oder so):
Java:
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

public class Heron {
    private final Set<HeronListener> listeners;
    private double basis, ergebnis, genauigkeit;
    private long anzahlSchritte;

    public Heron() {
        // für Listener ein CopyOnWriteArraySet nehmen, weil es sonst nicht funktioniet,
        // dass ein Listener sich als Ergebnis eines Events abmeldet
        listeners = new CopyOnWriteArraySet<>();
    }

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

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

    public double getBasis() {
        return basis;
    }

    public double getErgebnis() {
        return ergebnis;
    }

    public long getAnzahlSchritte() {
        return anzahlSchritte;
    }

    public void rechneWurzel(boolean rek, double basis, double genauigkeit) {
        // warum als Parameter übergeben, wenn wir es in der Klasse speichern können?
        this.basis = basis;
        this.genauigkeit = genauigkeit;

        if (rek) {
            System.out.println("Die Wurzel wird rekursiv berechnet");
            rekHeron(kleinsteQuadratZahlUnterhalb(basis), 0);
        } else {
            System.out.println("Die Wurzel wird iterativ berechnet");
            itHeron(kleinsteQuadratZahlUnterhalb(basis));
        }
    }

    private void itHeron(int kleinereQuadratzahl) {
        double zwischenergebnis = kleinereQuadratzahl;
        long schrittzahl = 0;

        while (Math.abs(basis - zwischenergebnis * zwischenergebnis) > genauigkeit) {
            schrittzahl++;
            zwischenergebnis = (zwischenergebnis + (basis / zwischenergebnis)) / 2;
        }
        ergebnisFertig(zwischenergebnis, schrittzahl);
    }

    private void rekHeron(double zwischenergebnis, long schrittzahl) {
        try {
            if (Math.abs(basis - zwischenergebnis * zwischenergebnis) > genauigkeit) {
                zwischenergebnis = (zwischenergebnis + (basis / zwischenergebnis)) / 2;
                schrittzahl++;
                rekHeron(zwischenergebnis, schrittzahl);
            } else {
                ergebnisFertig(zwischenergebnis, schrittzahl);
            }
        } catch (java.lang.StackOverflowError e) {
            // letztes Zwischenergebnis als Endergebnis ausgeben
            ergebnisFertig(zwischenergebnis, schrittzahl);
        }
    }

    private int kleinsteQuadratZahlUnterhalb(double basis) {
        int quadratzahl = 0;
        int zähler = 1;
        while (quadratzahl < basis) {
            quadratzahl = zähler * zähler;
            zähler++;
        }
        return quadratzahl;
    }

    private void ergebnisFertig(double ergebnis, long schritte) {
        this.ergebnis = ergebnis;
        this.anzahlSchritte = schritte;
        for (HeronListener listener : listeners) {
            listener.ergebnisFertig(this);
        }
    }
}

Wobei das Interface einfach so ist:
Java:
public interface HeronListener {
    // der Listener bekommt die Information, dass die Quelle ein neues
    // Ergebnis hat. Das Ergebnis kann sich der Listener dort selbst abholen.
    void ergebnisFertig(Heron quelle);
}
 
Zuletzt bearbeitet:

Gucky

Top Contributor
Vielen Dank. Du hast mir gerade den Tag gerettet. :toll::toll:
Dafür bekommst du einen Riesenhaufen Dankes.
Sowas muss man aber auch echt wissen. :D

Das es dafür schon fertige Methoden gibt, wusste ich zwar nicht, hätte ich mir aber denken können. Ich war aber schon immer ein Freund vom Selberschreiben. Dann weiß ich wenigstens genau, was meine Methode tut und in welcher Reihenfolge. Dessen, dass die Methoden von Sun/Oracle wahrscheinlich in vielerlei Hinsicht besser sind, bin ich mir bewusst. :)

Ein Problem habe ich aber noch: Wenn ich Iterativ anklicke, geht er in eine Endlosschleife direkt in der itHeron() Methode, obwohl die Differenz zwischen dem Quadrat des Zwischenergebnisses und der Basis kleiner als die geforderte Genauigkeit ist. Er geht davon aus, dass die Entfernung mit der Methode berechnet 90 beträgt. Hast du da eine Idee, warum dem so ist?



Du hast jetzt den Multicatster und das Event zusammen in die Heron Klasse getan.
Ja so hätte man es auch tun können. Jetzt änder ich es aber nicht mehr. Trotzdem danke. :D
 
Zuletzt bearbeitet:

rme

Top Contributor
Hm, sehe gerade auf Anhieb keine Ursache. Lass dir mal das Zwischenergebnis innerhalb der Schleife ausgeben, damit du siehst, was da passiert :)
 

Gucky

Top Contributor
Das hier ist eine Ausgabe aus der Schleife:
Code:
Genauigkeit: 0.1 Zwischenergebnis: 10.0 Schrittzahl: 401249 Entfernung: 90.0
 

rme

Top Contributor
War die Eingabe 100? Dann sieht es so aus, als ob du die Entfernung zur Eingabe und nicht zum Quadrat der Eingabe berechnest, kann das sein?

Nachtrag: Du scheinst die Entfernung vom Zwischenergebnis zum Quadrat des Zwischenergebnis zu bestimmen. Überleg dir mal genau, ob das sinnvoll ist und ob es die Genauigkeit unterschreiten kann ;)
 
Zuletzt bearbeitet:

Gucky

Top Contributor
Mann bin ich :bloed:. Ja natürlich geht das nicht und es muss die Entfernung vom Quadrat des Zwischenergebnisses zur BASIS sein.
Vielen Dank.
 

Gucky

Top Contributor
Moin ich bin es noch mal,
mein Programm funktioniert jetzt. Ein paar kleinere Fehler habe ich noch bereinigt. Aber jetzt ist es wieder so wie vorher, dass bei größeren Werten in der Basis die GUI blockiert wird, obwohl ich einen Thread benutze.
Ich hoffe, du findest meinen Fehler. Hier ist noch mal das neue Projekt.

Gruß
Gucky
 

Anhänge

  • Heron.zip
    15,7 KB · Aufrufe: 3

rme

Top Contributor
Dein Rechenthread ruft sofort invokeLater auf, damit wird alles wieder im Swing-Thread ausgeführt und blockiert die GUI ;) Der Trick ist es, invokeLater nur zum Setzen des Ergebnisses zu verwenden, also insbesondere her.rechneWurzel noch vor dem invokeLater zu machen. Nur das "setText" ist das Verbotene, das innerhalb von invokeLater passieren muss.
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
S Interface Welchen Interface Stil favorisiert ihr? (usability) Allgemeine Java-Themen 17
P guter Stil? Allgemeine Java-Themen 7
S besserer Stil ? Allgemeine Java-Themen 5
T [Konvention/Stil] PropertyChangeEvent vorher oder nachher? Allgemeine Java-Themen 2
M Stil-Frage: this-Referenz Allgemeine Java-Themen 38
Monokuma Lesbarkeit von Streams Allgemeine Java-Themen 6
K Lesbarkeit von Streams Allgemeine Java-Themen 5
mihe7 Lesbarkeit von Streams Allgemeine Java-Themen 5
parrot Verständnis des Codes Allgemeine Java-Themen 3
N Neustarten des Codes nach der Fehlermeldung Allgemeine Java-Themen 17
D Bezüglich Design meines Codes Allgemeine Java-Themen 1
B Ungewollte mehrmalige ausführung des codes Allgemeine Java-Themen 10
C QR-Codes erzeugen. Allgemeine Java-Themen 43
x22 Unterstreichen eines Consolen-codes Allgemeine Java-Themen 6
X [Java] Internationalisierung / Language codes bestimmen Allgemeine Java-Themen 4
V Eclipse braucht ewig zum Starten meines Codes Allgemeine Java-Themen 21
H Speicherstruktur für beliebige Bit-Codes Allgemeine Java-Themen 2
K umwandeln des codes um eine .jar datei zu erstellen(am bsp.) Allgemeine Java-Themen 10
H teile eines codes überspringen Allgemeine Java-Themen 4
M Problem mit bestimmten ASCII Codes Allgemeine Java-Themen 3

Ähnliche Java Themen

Neue Themen


Oben