Wie reicht man am Besten Zahlenwerte von der GUI zum Code, der damit arbeitet?

sceptical

Mitglied
Sorry ich habs -- fürcht ich -- aus Versehen im falschen Board gepostet. Wollte es eigentlich in Java Basics posten...

Ich habe vor einiger Zeit ein kleines Programm geschrieben, das den Gaußschen Algorithmus implementiert. Allerdings bisher ohne GUI. Bisher wurden die Zahlenwerte der Ausgangsmatrix über Konsole gelesen und damit gerechnet.

Jetzt bin ich daran auch eine simple GUI zu schreiben und diese funktioniert auch soweit wunderbar. Ich habe eine Menge Eingabefelder, die Double-Werte lesen und ich speichere diese dann in einem zweidimensionalen Array.

So sieht das aus:

gauss.png


Java:
private final static int n = 3; // Die Groeße der quadratischen Matrix. Im Moment noch hart im Code, soll dann spaeter aber eingelesen werden.
private ArrayList<ArrayList<JFormattedTextField>> fields = new ArrayList<ArrayList<JFormattedTextField>>(); // Die Eingabefelder werden in einer verschachtelten ArrayList gespeichert
private double [][] values = new double [n][n+1]; //Hier hinein speichere ich vorerst die gelesenen Werte

So speichere ich die Double-Werte aus den Eingabefeldern in das value-Array:

Java:
for (int row = 0; row < n; row++) {
    for (int col = 0; col < (n+1); col++) {
        values[row][col] = ((Number) fields.get(row).get(col).getValue()).doubleValue();
    }
}

Meine Frage ist nun: Wie bekomme ich die Daten (values[][]) aus meiner GUI-Klasse in meine Gauss-Klasse, die das eigentliche Verfahren mit den Werten durchführt?

Ich hab darüber nachgedacht, ob man einfach einen Getter schreiben sollte, womit die Gauss-Klasse das zweidimensionale Array mit den Werten erhält und dieses in ein eigenes Attribut -- ein weiteres zweidimensionales Array -- speichert. Allerdings ist das wohl kaum besonders effizient... Und man bräuchte zwei im Prinzip identische Attribute.

Ein Kommilitone von mir hat geraten das Registry-Pattern zu verwenden. Ich soll irgendwie eine HashMap, die die Werte enthält, registrieren (wo ist mir schon schleierhaft...) und kann dann von der Gauss-Klasse auf die registrierten Werte zugreifen.

Kurzum: Wie stellt man es effizient und geschickt an, die Werte von der GUI-Klasse an die Gauss-Klasse zu übertragen? Ich weiß einfach nicht so recht welcher Weg sinnvoll ist...

Tausend Dank für Hilfe!
 
Zuletzt bearbeitet:

bERt0r

Top Contributor
Wie hast du denn bisher (ohne GUI) der Gauss Klasse die Zahlenmatrix übergeben? Wenn du erst mal ein double array [][] hast, gibts eigentlich keinen Unterschied mehr zwischen GUI und Konsolenprogramm.
Da dir das aber anscheinen Probleme bereitet, ist vielleicht deine Gaussklasse nicht optimal konstruiert. Meiner Meinung nach sollte es bei deiner Gaussklasse nur eine Funktion geben, die ein double [][] Array aufnimmt und wieder ein Array zurückgibt (bzw. die Lösung gleich in das Array speichert). Diese Funktion sollte dann entweder von der GUI Klasse, oder von deiner Konsolenklasse aufgerufen werden.
 

JavaProfi

Aktives Mitglied
Hallo sceptical,

das ist ganz einfach. Das Array gehört nicht in die GUI-Klasse.
Ich gehe davon aus, beide Klassen liegen in dem selben Paket.

(1) Implementiere weder Datenstrukturen, noch Funktionalität in die GUI-Klasse!
(2) Deklariere deine GUI-Control-Variablen (JTextFields) als protected
(3) Implementiere die Datenstruktur in die Gaus-Klasse.
(4) Schreibe eine actionlistener für den Button Start in der Gaus-Klasse
(5) Registriere den Actionlistener beim Button in der GUI-Klasse (dazu muss die Gaus-Klasse eine Referenz auf die GUI-Klasse besitzen)
(6) Das Füllen des Arrays erfolgt in der actionPerformed-Methode des Actionlisteners. Dazu fragst du die GUI-Controls der Reihe nach ab. (Du holst dir also aus der GUI die Daten zur Verarbeitung in der Gaus-Klasse)

Damit ist gewährleistet, dass alle Rechenoperationen in der Gaus-Klasse ablaufen.

Gruß
Der JAva Profi.
 

sceptical

Mitglied
Nunja, dass meine Gauss-Klasse nicht gerade toll konstruiert ist, kann durchaus gut sein... Ich programmiere noch nicht lange in Java und das war quasi mein erstes etwas ernsteres Programm.

Die Gauss-Klasse hat sich vor der GUI um alles gekümmert. Sie war die einzigste Klasse, die es überhaupt gab...
Sie hat keine Werte in einem Array oder so übergeben bekommen, sondern die einzelnen Werte selbst durch readDouble()-Methoden von der Konsole eingelesen und eben dann die Berechnungen durchgeführt.

(4) Schreibe eine actionlistener für den Button Start in der Gaus-Klasse
(5) Registriere den Actionlistener beim Button in der GUI-Klasse (dazu muss die Gaus-Klasse eine Referenz auf die GUI-Klasse besitzen)

Diese Schritte sind mir nicht ganz klar... Den Actionlistener hatte ich davor in der GUI-Klasse. Ich hab ihn jetzt wie du sagst in die Gauss-Klasse verschoben:

Gauss-Klasse:
Java:
public class Matrix implements ActionListener { // = Gauss-Klasse
private double[][] values = new double[n][n + 1];
[...]
/** Behandlung der Action-Events **/
public void actionPerformed(ActionEvent e) {
	if (e.getActionCommand() == "AC_START") {
		for (int row = 0; row < n; row++) {
			for (int col = 0; col < (n + 1); col++) {
                                //Hier kracht's: Wie soll ich auf die Eingabefelder aus der GUI-Klasse zugreifen?
				entry[row][col] = ((Number) fields.get(row).get(col).getValue()).doubleValue();
			}
		}
		double tmp = this.entry[0][1];
		System.out.println("Wert [0][1]:\t" + tmp);
	}
}

GUI-Klasse
Java:
public class GUI extends JPanel {
    protected ArrayList<ArrayList<JFormattedTextField>> fields = new ArrayList<ArrayList<JFormattedTextField>>();
[...]
/** Konstruktor **/
public GUI() {
       super(new BorderLayout());
        UIManager.put("swing.boldMetal", Boolean.FALSE);
        setUpFormat();
        
        // Eingabefelder und zugehoeriges Panel erstellen
        createFields();
        JPanel fieldPanel = createFieldPanel();
        
        //Button
        JPanel buttonPanel = new JPanel(new FlowLayout()); 
        JButton go = new JButton("Start");
        // Und hier kracht's ein zweites mal. Wie füge ich jetzt dem Button den ActionListener in der Gauss-Klasse zu?
        go.addActionListener(this);
        go.setActionCommand("AC_START");
        buttonPanel.add(go);        

        // Den JFrame zusammensetzen
        setBorder(BorderFactory.createEmptyBorder(15, 15, 5, 15));
        this.add(fieldPanel, BorderLayout.CENTER);
        this.add(buttonPanel, BorderLayout.SOUTH);
    }
 
Zuletzt bearbeitet:

JavaProfi

Aktives Mitglied
Mache dich mal mit dem MVC vertraut, wenn du professionellen Code schreiben willst. Aber du bist methodisch genau auf dem Weg dahin.

Die Console ist ein UI (user interface)!!
Du ersetzt nur ein UI durch ein anderes UI, in diesem Fall eine GUI.

Das was du bei der Console gemacht hast, musst du jetzt mit der GUI ebenso machen.
Die GUI dient der Anzeige der Daten, der Eingabe von Benutzerdaten und dem Empfangen von Benutzeraktionen (events). Mehr soll sie nicht machen.

Nun zum Kern deiner Frage:
Wer erzeugt denn bei das GUI-Objekt? Die Gaus-Klasse oder hast du eine aufrufende Klasse oder ein aufrufendes Objekt?
Nehmen wir an, die Gaus-Klasse erzeugt das GUI-Objekt.

Java:
GausGUI myGUI = new GausGUI();
myGUI.setVisible(true);

Damit verfügt das Gaus-Objekt mit "myGUI" über eine Referenz auf das GUI-Objekt.
Jetzt kannst du auf protected oder public definierte Elemente des GUI-Objektes zugreifen.

Beispiel um eine Listener an dem Button zu registrieren.:
Java:
myGUI.ButtonStart.addActionlistener(new ButtonStartActionlistener());

oder um eine Wert aus einem JTextField zu lesen:

Java:
String input = myGUI.Field1.getText().trim();

Dabei sollen "Field1" ein JTextField sein und "ButtonStart" der Bezeichner für den Button.
"ButtonStartActionlistener" ist der Bezeichner der inneren Klasse für den Actionlistener.

Du musst natürlich die Objektvariablen (Eingabefelder und Button) in deiner GUI-Klasse auch objektweit als "protected" oder "public" deklarieren!

Hier mal ein kleines Beispiel wie man von einer Controller-Klasse auf eine GUI-Klasse zugreift.
Ich hoffe das hilft dir weiter.


Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;


public class GausController {

	GausGUI gui;
	
	public GausController(){
		this.gui = new GausGUI();
		gui.setVisible(true);
		gui.ButtonStart.addActionListener(new ButtonStartActionListener());
	}	
		
	class ButtonStartActionListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			String input = gui.Field1.getText().trim();
			String result = "Ihre Eingabe war: ".concat(input);
			JOptionPane.showMessageDialog(null ,result);
		}
	}

	public static void main(String[] args) {
		new GausController();
	}
}

Java:
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;

import javax.swing.WindowConstants;
import javax.swing.SwingUtilities;


public class GausGUI extends javax.swing.JFrame {
	protected JButton ButtonStart;
	private JLabel Field1Lable;
	protected JTextField Field1;

	public GausGUI() {
		super("TEST");
		initGUI();
		setLocationRelativeTo(null); 
	}
	
	private void initGUI() {
		try {
			setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			getContentPane().setLayout(null);
			{
				ButtonStart = new JButton();
				getContentPane().add(ButtonStart);
				ButtonStart.setText("Start");
				ButtonStart.setBounds(157, 210, 88, 21);
			}
			{
				Field1 = new JTextField();
				getContentPane().add(Field1);
				Field1.setBounds(129, 138, 156, 21);
			}
			{
				Field1Lable = new JLabel();
				getContentPane().add(Field1Lable);
				Field1Lable.setText("Eingabe:");
				Field1Lable.setBounds(129, 113, 156, 14);
			}
			pack();
			setSize(400, 300);
		} catch (Exception e) {
		    //add your error handling code here
			e.printStackTrace();
		}
	}
}




Gruss
Der JavaProfi
 
Zuletzt bearbeitet:

bERt0r

Top Contributor
Also diese Liste von Punkten vom "JavaProfi" würde ich so nicht unterschreiben. Deine Klasse soll eine Matrix-Rechenoperation ausführen. Um diese Berechnung auszuführen sollte sie eine Matrix erhalten. Diese Matrix zu erstellen ist - wenn wir schon beim MVC sind - Aufgabe des Controllers. In deinem Fall - wie in den meisten GUI Beispielen mit MVC - ist der Controller der ActionListener deines Buttons. Der sorgt dafür, dass die Daten der View (die TextFields) in eine Datenstruktur kommen, die das Model (deine Berechnungsklasse) verstehet.
Wenn du unbedingt Model, Controller und View in verschiedene Klassen trennen willst ist das kein Problem. Falls doch, poste wo deine Schwierigkeiten liegen.
 

JavaProfi

Aktives Mitglied
Also diese Liste von Punkten vom "JavaProfi" würde ich so nicht unterschreiben. Deine Klasse soll eine Matrix-Rechenoperation ausführen. Um diese Berechnung auszuführen sollte sie eine Matrix erhalten. Diese Matrix zu erstellen ist - wenn wir schon beim MVC sind - Aufgabe des Controllers. In deinem Fall - wie in den meisten GUI Beispielen mit MVC - ist der Controller der ActionListener deines Buttons. Der sorgt dafür, dass die Daten der View (die TextFields) in eine Datenstruktur kommen, die das Model (deine Berechnungsklasse) verstehet.
Wenn du unbedingt Model, Controller und View in verschiedene Klassen trennen willst ist das kein Problem. Falls doch, poste wo deine Schwierigkeiten liegen.

Das hilft dem Rookie "sceptical" natürlich ungemein weiter.
Solche Beiträge nach dem Motto "Hallo Herr Lehrer ich weiss was" die den Fragesteller nicht ein bisschen weiter bringen kann ich nicht leiden.

Natürlich gehört die Geschäftslogik bei MVC in den Controller. Gut aufgepasst "bERtOr".
Aber lasse "sceptical" doch erst mal sein Problem lösen aus einem Objekt auf ein anderes Objekt zuzugreifen. Da ist es vollkommen belanglos, dass controller und model in einer Klasse implementiert sind.
Du willst ihm sofort das MVC in Reinkultur (und lass dir gesagt sein, dass es da sehr viele Derivate gibt) beibringen. Hurra!! Das ist so als wenn man das Bergsteigen auf dem Mount Everest erlernen will.

Also wenn man Beiträge postet, dann sollte man dem Fragenden etwas ERKLÄREN und postet nicht einfach nur euer Wissen!

Der Java Profi
(professional coder since 1983)
 
Zuletzt bearbeitet:

bERt0r

Top Contributor
Also ich weis ja nicht, aber wenn ich mir den Thread hier so ansehe, warst du derjenige der mit der MVC Geschichte überhaupt angefangen hat. Der TO hat ein sehr konkretes Problem gepostet: Er hat eine GUI mit einer Matrix aus Textfeldern. Er kann aus den Werten der Textfelder ein Array auslesen. Nur weis er nicht, wie er dieses Array an die Klasse schickt, die damit eine Rechennoperation durchführt.
Die lösung ist so einfach, dass man da von MVC usw. noch gar nicht anfangen muss, nämlich eine Funktion mit einem Array als parameter zu schreiben, die diese Berechnung durchführt.
Für mich sieht es so aus, als hättest du den TO derartig verwirrt dass er aus seiner Gaussklasse einen Controller gemacht hat, die aber eigentlich das Model wäre.
@ Sceptical:
Alles was du brauchst ist folgendes:
Klasse GaussBerechnung:
Java:
public void berechneGauss(double[][] array)
{
//Mach die Berechnung und speichere das Ergebnis in array
}
Klasse GUI:
Java:
//Konstruktor
GUI()
{
//Erstelle GUI Komponenten und JButton but, ein Array aus JTextFields
but.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
//Lies die Werte aus den Textfields in ein double[][] array ein
GaussBerechnung gauss=new GaussBerechnung();
gauss.berechne(array);
//Schreib die werte aus array in die Textfelder
}
}
 
Zuletzt bearbeitet:
B

...ButAlive

Gast
Das Einzige was ich bERt0r noch hinzufügen würde, in ursprüglich geposteten Code hast du das Array als Instanz-Variable, das brauchst du nicht, es reicht, wenn das Array nur lokal für das einsammeln der Werte, für die Übergabe an die berechnen-Methode und das zurückschreiben da ist. Am Besten schreibst du noch zwei zusätzliche Methoden:

Eine zum Einsammeln der Werte:

Java:
private double[][] sammelWerte(){

   double values[][] = new double[n][n+1]; //Was n ist weiß ich nicht, hab ich aus deinem Code übernommen
   for (int row = 0; row < n; row++) 
       for (int col = 0; col < (n+1); col++) {
           values[row][col] = ((Number) fields.get(row).get(col).getValue()).doubleValue();
       }
   }
   
  return values;
}

Eine zum Schreiben des Ergebnis:

Java:
private void schreibeWerte(double[][] values){

   for (int row = 0; row < n; row++) {
       for (int col = 0; col < (n+1); col++) {
           fields.get(row).get(col).setValue(values[i][j]);
       }
   }
}
Ich hab nur deinen Code als Basis genommen, ob er funktioniert weiß ich nicht ;). Wollte eigentlich nur zeigen, dass du die Instanz-Variable nicht brauchst.

Der Aufruf sieht dann so aus:

Java:
double [][] values = sammelWerte();
berechneGauss(values);
schreibeWerte(values);

Zwar bist du mit der Lösung weit weg von MVC, aber näher an sauberen Code als mit der Lösung von JavaProfi. MVC wäre in deinem Beispiel auch mit Kanonen auf Spatzen geschossen.

P.S.: Lass dich nicht von so Sachen wie "(professional coder since 1983)" beeindrucken, wir kochen alle nur mit Wasser.
 

sceptical

Mitglied
Sorry für die späte Antwort, aber ich war jetzt zwei Tage vom Internet abgeschnitten bei der Verwandtschaft unterwegs.

Vielen Dank auf jeden Fall für die vielen Ratschläge! Ich werd jetzt in den nächsten Tagen versuchen das umzusetzen und melde mich nochmals falls ich an irgend einer Stelle so gar nicht weiterkomme.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
V Java Heap Size -Xmx1024m reicht nicht! Allgemeine Java-Themen 14
B Volatile Frage: Reicht es nur den Singleton als volatile zu deklarieren? Allgemeine Java-Themen 4
B Mit welchen Datentypen und Strukturierung am Besten dutzende Baccaratspiele Shcritt für Schritt durchsimulieren? Allgemeine Java-Themen 26
ZH1896ZH Best Practice Wie erstellt man am besten einen Kalender? Allgemeine Java-Themen 3
W Updates - wie am Besten verteilten? Allgemeine Java-Themen 9
L Schlüsselworte Wie kann ich am Besten ein LocalDate zwischen Anfangs und EndDate checken Allgemeine Java-Themen 10
MiMa Wie sollte am besten ein Datum gespeichert werden? Allgemeine Java-Themen 8
B Wie kann ich meine Pläne am besten umsetzen? Allgemeine Java-Themen 2
D Best Practice Login-Daten: Wie am besten abrufen? Allgemeine Java-Themen 6
O OOP Wie macht man das am besten OO? Allgemeine Java-Themen 8
Thallius Wie verstecke ich meinen private Key am besten im Code? Allgemeine Java-Themen 10
A Datentypen Generics: Wie am besten auf Typparameter zugreifen Allgemeine Java-Themen 2
Joew0815 Best Practice Wie am besten Plugin-System erstellen? Allgemeine Java-Themen 12
M interaktive grafische Oberfläche - wie mach ich das am Besten Allgemeine Java-Themen 4
C Hilfe bei Adressbuch-Programmierung, wie am Besten mit JList implementieren Allgemeine Java-Themen 2
B Wie Duration am besten abbilden Allgemeine Java-Themen 2
N unzählige Werte am besten speichern(?) Allgemeine Java-Themen 2
A Wie am besten Daten auslagern um heap zu schonen Allgemeine Java-Themen 4
X JDK updaten - wie am besten vorgehen? Allgemeine Java-Themen 5
L Wie kann man dieses "Table" Problem am besten löse Allgemeine Java-Themen 8
N Wie sortiere ich String Arrays am besten Allgemeine Java-Themen 5
D wie gliedere ich dieses programm am besten? dringend! Allgemeine Java-Themen 3
E Code für Tabulator (am besten ne komplette Übersicht) Allgemeine Java-Themen 2
S Zahlenwerte in Intervall einschränken Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben