Programm-Umstrukturierung GUI Rechnungserstellung

denis7788

Bekanntes Mitglied
Hallo!
Ich habe gerade ein kleines Programm an dem ich arbeite. Problem ist, das ich teilweise eine Vorstellung habe, wie ich es umsetzen könnte, diese mir aber sehr umständlich vorkommen. Teilweise weiß ich garnicht weiter. Ein paar Vorschläge zum logischen Aufbau würden mir bestimmt weiterhelfen.

Das Programm:
- Es ist eine Prog zum erstellen von Rechnungen
- Auf einer Benutzeroberfläche sind Buttons, neben jedem Button ein Textfeld
- Jeder Button steht für ein Produkt, jedes Textfeld für die Menge des Produktes
- Bei Klick auf den Button, erhöht sich die Anzahl des Produktes um 1
- Man wählt so alle Produkte und Mengen aus und kann dann durch Klick auf den Button "Rechnung ersstellen" eine Textdatei ausgeben lassen, die diese Artikel mit Preisen usw enthält.

Wie ich es bisher umgesetzt habe/ umsetzen wollte:

Klasse "RechnungOberfläche":
- das Fenster mit Buttons und Textfeldern wird erzeugt
- Jeder Artikel (=Button) hat die eigenen Variablen: string name; int mengeProduktX; int preisProduktX; int gesamtProduktX; und eine eigene String Variable "ausgabeProduktX", die alle diese Angaben enthält
- Bei jedem Event (Wenn der Button gedrückt wird):
Java:
button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				Menge wird um 1 erhöht;
                gesamtProduktX = mengeProduktX*preisProduktX;
			}
		});
- Zu jedem Produkt gibt es die Methode:
Java:
string schreibeAusgabefürProduktX()  { 
                         String ausgabeProduktX = "";                      
                         ausgabeProduktX = ""+name+","+menge","+preis+","+gesamt; 
                         return ausgabeProduktX;
                        }
- Methode Rechnung erstellen (bei Klick auf "Rechnung erstellen"):
String rechnung = ausgabe1+ausgabe2+ausgabe3+...
Hier sollen also die Ausgaben jedes Produktes, dessen Menge größer 0 ist zu einer
Rechnung zusammengefügt werden.
Ich hatte folgende Idee:
Java:
//wird für jedes einzelne Produkt gemacht
if (mengeProduktX != 0) {
                   String str = schreibeAusgabeFürProduktX();
                   rechnung = rechnung + str;
                }

Also so wie ich es mache, brauche ich 1mio Variablen, Methoden (die die ausgabe erzeugen) und if-Blöcke (in der Methode zur Rechnungserstellung). Möchte ich weitere Produkte hinzufügen, ist das auch aufwendig.
Hat jemand Tips, wie ich das Programm umstrukturieren könnte?
 
Zuletzt bearbeitet von einem Moderator:
so als Anfangsidee:

1) -Klasse "Produkt" erstellen mit Zähler als static

2) -Die Produkte werden in einer Liste gehalten z.B. List<Produkt>

3) -Eine Klasse (GUI-Element) erstellen die das Textfeld und die beiden Buttons enthält
mit dem konkreten Produkt als Parameter
z.B. wird im Actionlisterner dieser Parameter (das Produkt) verwendet

4) -über die Produktliste iterieren und wie in 3) GUI-Elemente erzeugen
und in in eine Oberfläche untereinander anordnen.
 
Danke erstmal!

Ich verstehe 3) und 4) nicht so ganz.
- Wenn die GUI bei jedem start dynamisch erzeugt wird, wie kann ich dann in die EventMethoden den benötigten Code schreiben? Ich muss ja für jeden einzelnen Button im zugehörigen Textfeld die Menge des Produktes inkrementieren.
- Wenn ich schon in 3) die GUI Elemente erzeuge, wieso soll ich sie dann wieder in 4) neu erzeugen?
 
Bzw. wie komme ich jetzt weiter?

Ich habe jetzt die Klasse Product, die alle Angaben als Parameter enthält.
In der Main Methode Lege alle vorhandenen Produkte an.
In der Klasse Product werden alle erstellten Produkte in einer Arraylist gespeichert.
Wie verbinde ich jetzt die GUI mit den einzelnen Produkten?

- Wäre es vieleicht sinnvoll Buttons und Textfelder für jedes Produkt in der Klasse Produkt zu erstellen? und dann in einer Klasse erstelleGUI iterativ in ein Frame zu adden?
 
Also ich habs jetzt mal so weit:

- Klasse Product: stellt Produkte mit allen Angaben dar und erstellt zugehörigen Button+Textfeld
hier wollte ich auch umsetzen, dass bei jedem Klick auf den Button der Wert im
zugehörigen Textfeld erhöht wird; aber es wird ein Fehler der Klammerung angezeigt.
(Wenn ich das in den Konstruktor schribe wird kein Fehler angezeigt, aber dann
funktionierts logischerweise auch nicht. Habe dafür keine Lösung googlen können...😉 )
- Klasse GUI_Element: Erstellt das Fenster und füllt es mit allen Buttons und Textfeldern
- Klasse RunIt: Hier erstelle ich alle Produkte, rufe GUI auf und später dann auch die Rechnung.

Mein Problem ist jetzt in der Klasse Product eine MEthode zu schreiben, die bei jedem Klick den Wert im zugehörigen Textfeld erhöht.

Product:
Java:
package rechnungV1;

import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;



public class Product {
	
	
	public static int zaehler;
	public static List<Product> list = new ArrayList<Product>();
	
	String bezeichnung;
	double preis;
	int menge;
	double summe;
	double pfand;
	boolean hatPfand;
	
	JButton button;
	JTextField textField;
	
	
	
	public Product(int menge, String bezeichnung, double preis, double summe, double pfand, boolean hatPfand) {
		this.bezeichnung = bezeichnung;
		this.preis = preis;
		this.menge = menge;
		this.summe = summe;
		this.pfand = pfand;
		this.hatPfand = hatPfand;	
		
		zaehler++;
		list.add(this);
		
		button = new JButton(this.bezeichnung);
		button.setVisible(true);
		textField = new JTextField();
		
	}
	
	
	button.addActionListener( new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          textField.setText("hallo");
        }
      } );
	 

// ...hier folgen noch alle getter und setter....
	
}

GUI_Element:
Java:
package rechnungV1;

import java.awt.*;

import javax.swing.*;

public class GUI_Element {
	
	
	JFrame frame;
	JPanel panel;
	JButton button;
	
	public GUI_Element() {
		
		frame = new JFrame();
		frame.setSize(800,800);
		panel = new JPanel();
		panel.setLayout(new FlowLayout());
		frame.add(panel);
		panel.setVisible(true);
		frame.setVisible(true);
		button = new JButton("hallo");
		}
	
	public void erstelleGUI() {
		for(int i=0; i<Product.list.size(); i++) {
			panel.add(Product.list.get(i).button);
			panel.add(Product.list.get(i).textField);		}
		
		panel.add(button);
		
	}
	

}

RunIt:
Java:
package rechnungV1;


import java.util.ArrayList;
import java.util.List;

public class RunIt {

	public static void main(String[] args) {
		
		Product bitKasten = new Product (0, "Bitburger Kasten", 14.89, 0.00, 3.10, true);
		Product LoewenKasten = new Product (0, "Löwenbräu Kasten", 12.89, 0.00, 3.10, true);
		GUI_Element rechnung = new GUI_Element();
		rechnung.erstelleGUI();
		
		}
		
}
 
In die Klasse Produkt würde ich keinen GUI-Code reinmachen.
revidiere: Zähler als static ist in diesem Fall doch nicht passend.

Code sagt manchmal mehr als 1000 Worte deshalb mal schnell zusammengebastelt:

Java:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Test
{
	public static void main(String[] args)
	{
		final List<Produkt> liste = new ArrayList<Produkt>();
		liste.add(new Produkt(1, "A"));
		liste.add(new Produkt(2, "B"));
		liste.add(new Produkt(3, "C"));	
		//usw...
		
		JFrame  frame = new JFrame();
        frame.setSize(500,500);          
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(liste.size()+1,2));
        panel.setVisible(true);      
       
        for(Produkt p:liste)
        {
        	panel.add(new GUIElement(p));
        	
        }
     
        JButton ges = new JButton("Rechnung");
        ges.setSize(50,50);      
        ges.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) 
			{
				
				double summe = 0;
				for(Produkt p: liste)
				{
					
				   System.out.println(p.getName()+" Anz: "+p.getAnzahl()+" Summe:"+(p.getAnzahl()*p.getPreis()));  
				   summe+=(p.getAnzahl()*p.getPreis());
				}
			    System.out.println("Gesamt = "+summe);  
			}
		});
        
        panel.add(ges);      
    	frame.add(panel);     
        frame.setVisible(true);
	}		
}

class Produkt
{
	private int anzahl = 0;
	private double preis;
	private String name;	
	public Produkt(int preis, String name)
	{
		super();
		this.preis = preis;
		this.name = name;
	}	
	public void setAnzahl(int anzahl)
	{
		this.anzahl = anzahl;
	}
	
	
	public  int getAnzahl()
	{
		return anzahl;
	}
	public double getPreis()
	{
		return preis;
	}
	public String getName()
	{
		return name;
	}	
}


class GUIElement extends JPanel
{
	private JTextField textField;
	private JLabel lblNewLabel;
    private Produkt produkt;

	public GUIElement(Produkt produkt)
	{
	
		this.produkt = produkt;
		
		lblNewLabel = new JLabel(this.produkt.getName());
		add(lblNewLabel);		
		textField = new JTextField(this.produkt.getAnzahl());
		textField.setColumns(10);	
		add(textField);
		textField.setText(String.valueOf(this.produkt.getAnzahl()));
		
		JButton btnNewButton = new JButton("kaufen!");
		btnNewButton.setSize(50,50);
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) 
			{
				GUIElement.this.produkt.setAnzahl(GUIElement.this.produkt.getAnzahl()+1);
				GUIElement.this.textField.setText(String.valueOf(GUIElement.this.produkt.getAnzahl()));
			}
		});		
		add(btnNewButton);		
		this.setSize(100,50);		
		this.setVisible(true);		
	}
}
 
Danke für die ausführliche Antwort!

Werd später wenn ich Zeit hab genauer drüber schaun... Aber eine kurze Verständnisfrage:
- Du hast den den Actionlistener des Buttons, der die Menge erhöht im Konstruktor. Aber nicht jedes mal, wenn ich den Button klicke, wird der Konstruktor aufgerufen. Der inkrementiert den Wert doch dann nicht, oder? (Also bei mir hats nicht funktioniert in meiner Version). Woran liegt das?
 
Der Konstruktor wird nur einmal, beim erzeugen des GUIElement - Objektes, aufgerufen,
der ActionListener wird dort ebenfalls erzeugt und mit dem Button assoziiert.

Bei Klick auf den Button wird somit nicht der Kontruktor aufgerufen sondern die Methode
actionPerformed.
 
Danke für die Tipps. Hat mit sehr weitergeholfen. Ich habs soweit fertiggestellt (die Grundfunktionen) und erweitere es gerade. Hier mal die vier Klassen, um die es ging (vollständigkeits halber😉).
- Ich habe die ganze GUI in GUI-Element gesteckt. Fand es so übersichtlicher. Oder gibt es da Nachteile, die ich nicht sehe.
- Wenn was an der Struktur vereinfacht werden kann, wäre ich froh über weitere Tipps.

Product:
Java:
public class Product {
	
	
	public static int zaehler;
	public static List<Product> list = new ArrayList<Product>();
	
	String bezeichnung;
	double preis;
	int menge;
	double summe;
	double pfand;
	double pfandGesamt;
	boolean hatPfand;
	int warengruppe;
	
	JButton button;
	JTextField textField;
	
	
	//Produkte mit allen Angaben + Button zum inkrementieren der Menge und Textfeld, in dem die MEnge angezeigt wird
	public Product(int menge, String bezeichnung, double preis, double pfand, boolean hatPfand, int warengruppe) {
		this.bezeichnung = bezeichnung;
		this.preis = preis;
		this.menge = menge;
		this.pfand = pfand;
		this.hatPfand = hatPfand;
		this.warengruppe = warengruppe;
		summe = 0.00;
		pfandGesamt = 0.00;
		
		zaehler++;
		list.add(this);
		
		button = new JButton(this.bezeichnung);
		button.setVisible(true);
		textField = new JTextField("Menge:"+String.valueOf(this.menge));
		
		button.addActionListener( new ActionListener() {
	        public void actionPerformed(ActionEvent e) {
	        Product.this.menge = Product.this.menge + 1;
	        Product.this.textField.setText(String.valueOf(Product.this.menge));
	        Product.this.summe = Product.this.menge * Product.this.preis;
	        //Falls Getränk mit Pfand, wird die Pfandsumme errechnet 
	        if(Product.this.hatPfand == true) {
	        	Product.this.pfandGesamt = Product.this.menge * Product.this.pfand;
	        }
	        }
	      } );
		
	}

	//Getter und Setter folgen hier...
}


RunIt:
Java:
public class RunIt {
//Anlegen der Produkte und Aufruf der MEthode zur ERstellung der GUI
	
	public static void main(String[] args) {
		
		Product bitKasten = new Product (0, "Bitburger Kasten", 14.89, 3.10, true, 1);
		Product loewenKasten = new Product (0, "Löwenbräu Kasten", 12.89, 3.10, true, 1);
		Product oettiKasten = new Product (0, "Oettinger Kasten", 9.89, 3.10, true, 1);
		
		Product kaliskaya = new Product (0, "Wodka Kaliskaya 0,7", 9.99, 0.00, false, 2);
		Product absolut = new Product (0, "Wodka Absolut 1,0l", 21.99, 0.00, false, 2);
		Product jaegi = new Product (0, "Jägermeister 0,7", 15.99, 0.00, false, 2);
		Product tequilla = new Product (0, "Tequilla 0,7", 16.99, 0.00, false, 2);
		Product sevenoaks = new Product (0, "Whikey Seven Oaks 0,7", 11.99, 0.00, false, 2);
		
		
		Product bigPumpTraeger = new Product (0, "Big Pump Träger", 12.99, 3.1, true, 3);
		Product bigPumpFlasche = new Product (0, "Big Pump Flasche 1,5l", 1.99, 0.25, true, 3);
		Product clubmate = new Product (0, "Club Mate Kasten", 23.99, 3.10, true, 3);
		Product colaKasten = new Product (0, "Coca Cola Kasten", 23.88, 3.10, true, 3);
		Product colaFlasche = new Product (0, "Coca Cola Flasche 1,0l", 1.99, 0.14, true, 3);
		Product fantaFlasche = new Product (0, "Fanta Flasche 1,0l", 1.99, 0.14, true, 3);
		Product spriteFlasche = new Product (0, "Sprite Flasche 1,0l", 1.99, 0.14, true, 3);
		Product osaft = new Product (0, "O-Nektar 1,5l", 1.99, 0.00, false, 3);
		Product wasser = new Product (0, "Wasser Flasche 1,0l", 1.99, 0.00, false, 3);
		Product redbullDose = new Product (0, "Red Bull Dose 0,25l", 1.99, 0.25, true, 3);
		
		
		GUI_Element rechnung = new GUI_Element();
		rechnung.erstelleGUI();
		
		}
		
}

GUI_Element:
Java:
public class GUI_Element {
	
	
	JFrame frame;
	JPanel panel;
	JPanel panel1;
	JPanel panel2;
	JTextField textField;
	JButton buttonForum;
	JButton buttonRakete;
	JLabel labelSpirituosen;
	JLabel labelBiere;
	JLabel labelSoftdrinks;
	JLabel labelFreiraum1;
	JLabel labelFreiraum2;
	JLabel labelFreiraum3;
	JLabel labelFreiraum4;
	JLabel labelFreiraum5;
	
	public static int kunde = 0;
	
	
	public GUI_Element() {
		
		
		frame = new JFrame();
		frame.setSize(350,630);
		frame.setLayout(new BorderLayout());
		panel = new JPanel(new GridLayout(0,2));
		panel1 = new JPanel(new GridLayout(0,2));
		panel2 = new JPanel(new GridLayout(0,2));
		labelSpirituosen = new JLabel("Spirituosen");
	    labelBiere = new JLabel("Biere");
		labelSoftdrinks = new JLabel("Softdrinks");
		labelFreiraum1 = new JLabel("");
		labelFreiraum2 = new JLabel("");
		labelFreiraum3 = new JLabel("");
		labelFreiraum4 = new JLabel("");
		labelFreiraum5 = new JLabel("");
		frame.add(panel, BorderLayout.PAGE_START);
		frame.add(panel1, BorderLayout.CENTER);
		frame.add(panel2, BorderLayout.PAGE_END);
		panel.setVisible(true);
		frame.setVisible(true);
		buttonForum = new JButton("Rechnung Forum");
		buttonRakete = new JButton("Rechnung Rakete");
		
		//Menu wird erstellt und in der Klasse Menu der frame hinzugefügt
		Menu menu = new Menu(frame);
		
		//Für jeden Kunden ein Button zum Erstellen der Rechnung
		buttonForum.addActionListener( new ActionListener() {
	        public void actionPerformed(ActionEvent e) {
	        	kunde = 1;
	        	RechnungErstellen.erstelleString();
	        	frame.dispose();
	        	System.exit(0);
	        }
	      } );
		
		buttonRakete.addActionListener( new ActionListener() {
	        public void actionPerformed(ActionEvent e) {
	        	kunde = 2;
	        	RechnungErstellen.erstelleString();
	        	frame.dispose();
	        	System.exit(0);
	        }
	      } );
		
		}
	
	//GUI Elemente werden den Panels hinzugefügt, für jede Kategorie ein eigenes Panel
	public void erstelleGUI() {
		
		panel.add(labelBiere);
		panel.add(labelFreiraum1);
		panel1.add(labelSpirituosen);
		panel1.add(labelFreiraum2);
		panel2.add(labelSoftdrinks);
		panel2.add(labelFreiraum3);
		for(int i=0; i<Product.list.size(); i++) {
			
			if(Product.list.get(i).warengruppe == 1) {
			 panel.add(Product.list.get(i).button);
			 panel.add(Product.list.get(i).textField);	
			}
			if(Product.list.get(i).warengruppe == 2) {
				 panel1.add(Product.list.get(i).button);
				 panel1.add(Product.list.get(i).textField);	
				}
			if(Product.list.get(i).warengruppe == 3) {
				 panel2.add(Product.list.get(i).button);
				 panel2.add(Product.list.get(i).textField);	
				}
		}
		
		panel2.add(labelFreiraum4);
		panel2.add(labelFreiraum5);
		panel2.add(buttonForum);
		panel2.add(buttonRakete);
	}
	

}

RechnungErstellen:
Java:
//Klasse, die die Rechnung in Tabellenform und mit richtigem Header als String erzeugt und in einer Textdatei ausgibt
public class RechnungErstellen {
	
	static String str = "";
	String kunde;
	static double gesamtSumme;
	
	public static void erstelleString() {
		
		DecimalFormat df = new DecimalFormat( "0.00" );
		//String s = df.format( myDouble );
		if (GUI_Element.kunde == 1) {
		str = str + " Forum                                         ALK        \r\n";
		str = str + " Straße                                         Sansibarstraße 6 \r\n";
		str = str + " Stadt                                          556436 Buxtehude";
		str = str + "\r\n \r\n \r\n \r\n";
		}
		
			if (GUI_Element.kunde == 2) {
				str = str + " Rakete                                       ALK \r\n";
				str = str + " Straße                                        Sansibarstraße 6 \r\n";
				str = str + " Stadt                                         556436 Buxtehude";
				str = str + "\r\n \r\n \r\n \r\n";                                                
			}
		
		
		str = str + "Menge";
		for(int i = 0; i < 2; i++){ str = str+" ";}
		str = str + "| Bezeichnung";
		for(int i = 0; i < 32; i++){ str = str+" ";}
		str = str +"| Preis";
		for(int i = 0; i < 6; i++){ str = str+" ";}
		str = str + "| Summe \r\n";
		str = str + "------------------------------------------------------------------------- \r\n";
		str = str + "       |                                            |            | \r\n";
		
		
		
		for (Product p: Product.list) {
			if(p.menge != 0){
				int meng = 1;
				if(p.menge > 9) {meng = 2;}
				if(p.menge > 99) {meng = 3;}
				int ersteSpalte = 7-meng;
				int bez = p.bezeichnung.length();
				int zweiteSpalte = 43-bez;
				int pr = 3;
				if(p.preis > 9.99) {pr = 4;}
				int dritteSpalte = 10 - pr;
			
				int pf = 3;
				if(p.pfand > 9.99) {pf = 4;}
				int pfandSpalte = 10 - pf;
			
				str = str + p.menge;
				for(int i = 0; i < ersteSpalte; i++){ str = str+" ";}
				str = str + "| "+p.bezeichnung;
				for(int i = 0; i < zweiteSpalte; i++){str = str+" ";}
				str = str +"| " + df.format(p.preis);
				for(int i = 0; i < dritteSpalte; i++){str = str+" ";}
				str = str + "| " + df.format(p.summe) + "\r\n";
		    
				if(p.hatPfand == true){
					str = str + p.menge;
					for(int i = 0; i < ersteSpalte; i++){ str = str+" ";}
					str = str + "| Pfand";
					for(int i = 0; i < 38; i++){ str = str+" ";}
					str = str + "| " + df.format(p.pfand);
					for(int i = 0; i < pfandSpalte; i++){ str = str+" ";}
					str = str + "| " + df.format(p.pfandGesamt) + "\r\n";
		    	
					gesamtSumme += p.pfandGesamt;
				}
				gesamtSumme += p.summe;
			}
		}
		
		str = str + "       |                                            |            | \r\n";
		str = str + "------------------------------------------------------------------------- \r\n";
		for(int i = 0; i < 65; i++){ str = str+" ";}
		str = str +"| "+ df.format(gesamtSumme);
		
		System.out.println(str);
	
	try{ 
        PrintWriter pWriter = new PrintWriter(new FileWriter("Rechnung.txt")); 
        pWriter.println(str); 
        pWriter.flush(); 
    }catch(IOException ioe){ 
        ioe.printStackTrace(); 
    } 
		
		
	}

}
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben