# Button einfügen



## EvilFairy1001 (9. Apr 2012)

Ich will eine ToDo-Liste zur Übung programmieren. Dazu habe ich das Hauptfenster frame erstellt, das einen Button enthält, mit dem man neue Aufgabe erstellen können soll. Wird der Button gedrückt öffnet sich ein zweites Fenster, das auch einen Button enthält. Wird der Button im zweiten Fenster gedrückt soll sich das zweite Fenster schließen und ein neuer Button ins Hauptfenster eingefügt werden. Das Fenster schließt sich zwar, aber der Button erscheint nicht. 
Fehlermeldungen gibt's keine.

Hier mal der Code:

```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ToDoListe {
	
	JFrame frame;
	JFrame popupframe;
	JPanel Background;
	JPanel popupBackground;
	JTextField Name;
	JLabel task;
	
	
	public String name;
		
	public static void main (String [] args) {
		ToDoListe list= new ToDoListe();
		//list.buildGUI();
	} //close main()
	
	public ToDoListe() {
		frame = new JFrame("ToDo Liste");
		frame.setSize(300, 400);
		frame.setVisible(true);

		Background = new JPanel();
		frame.getContentPane().add(BorderLayout.CENTER, Background);
				
		JButton addTask = new JButton ("Neue Aufgabe hinzufügen");
		addTask.addActionListener(new Task());
		frame.getContentPane().add(BorderLayout.SOUTH, addTask);
	} //close buildGUI()
	
	public void addingTask() {
		popupframe= new JFrame();	

		popupBackground = new JPanel();	
		
		JLabel AufgabenName= new JLabel("Aufgabe:");
		popupBackground.add(AufgabenName);
		
		Name= new JTextField(20);
		Name.setText("Bitte eingeben.");
		popupBackground.add(Name);		
		
		popupframe.getContentPane().add(BorderLayout.NORTH, popupBackground);	
		
		JButton saveTask= new JButton("Aufgabe speichern");
		saveTask.addActionListener(new TaskSave());

		popupframe.getContentPane().add(BorderLayout.SOUTH, saveTask);		
		popupframe.setSize(400,200);
		popupframe.setVisible(true);		
	} //close addingTask()
	
	public void savingTask() {
		popupframe.setVisible(false);
		popupframe.dispose();
		
		task= new JLabel("test");
		Background.add(task);
		

	} //close savingTask()
	
	class Task implements ActionListener {
		public void actionPerformed (ActionEvent event) {
			addingTask();
		} //close actionPerformed()
	} //close Task
	
	class TaskSave implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			savingTask();
		} //close actionPerformed()
	} //close TaskSave
} //close ToDoListe
```

Das was momentan im constructor von ToDoListe ist, hatte ich auch schon in einer Methode, die dann über die instance list der class ToDoListe aufgerufen wird, führt zum gleichen Ergebnis.

Wie müsste der Code lauten um durch das Klicken auf den Button im zweiten Fenster, einen neuen Button ins Hauptfenster einzufügen und das zweite Fenster zu schließen?

Schon mal vielen Dank für die Hilfe

LG EvilFairy1001


----------



## Fab1 (9. Apr 2012)

Hallo,

du musst nach dem Hinzufügen des Komponente noch validate() aufrufen. Dann funktioniert es. Mehr dazu hier: http://www.java-forum.org/bilder-gui-damit-zusammenhaengt/57543-jcomponent-wichtige-methoden.html

Außerdem solltest du die Close-Variante deines Main-Frames ändern. Ich habs mal auf EXIT_ON_CLOSE geändert, sonst läuft der Prozess im Hintergrund nämlich ewig.

Des Weiteren ist es zu empfehlen Konventionen einzuhalten. Variablen sollte man klein und im LowerCamelCase schreiben. Klassen Groß und im HigherCamelCase.

Ansonsten sollte es passen. Ich hab den Klassennamen bei dem Beispiel bei mir geändert, nicht, dass du dich wunderst warum alles Rot wird 


Spoiler:  Der Code





```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
 
public class Test {
    
    JFrame frame;
    JFrame popupframe;
    JPanel Background;
    JPanel popupBackground;
    JTextField Name;
    JLabel task;
    
    
    public String name;
        
    public static void main (String [] args) {
        Test list= new Test();
        //list.buildGUI();
    } //close main()
    
    public Test() {
        frame = new JFrame("ToDo Liste");
        frame.setSize(300, 400);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // sonst wird der Prozess nicht beendet.
        
        Background = new JPanel();
        frame.getContentPane().add(BorderLayout.CENTER, Background);
               
        JButton addTask = new JButton ("Neue Aufgabe hinzufügen");
        addTask.addActionListener(new Task());
        frame.getContentPane().add(BorderLayout.SOUTH, addTask);
    } //close buildGUI()
    
    public void addingTask() {
        popupframe= new JFrame();   
 
        popupBackground = new JPanel(); 
        
        JLabel AufgabenName= new JLabel("Aufgabe:");
        popupBackground.add(AufgabenName);
        
        Name= new JTextField(20);
        Name.setText("Bitte eingeben.");
        popupBackground.add(Name);      
        
        popupframe.getContentPane().add(BorderLayout.NORTH, popupBackground);   
        
        JButton saveTask= new JButton("Aufgabe speichern");
        saveTask.addActionListener(new TaskSave());
 
        popupframe.getContentPane().add(BorderLayout.SOUTH, saveTask);      
        popupframe.setSize(400,200);
        popupframe.setVisible(true);        
    } //close addingTask()
    
    public void savingTask() {
        popupframe.setVisible(false);
        popupframe.dispose();
        
        task= new JLabel(Name.getText());
        Background.add(task);
        Background.validate();
        
 
    } //close savingTask()
    
    class Task implements ActionListener {
        public void actionPerformed (ActionEvent event) {
            addingTask();
        } //close actionPerformed()
    } //close Task
    
    class TaskSave implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            savingTask();
        } //close actionPerformed()
    } //close TaskSave
} //close ToDoListe
```


----------



## L-ectron-X (9. Apr 2012)

Fab1 hat gesagt.:


> du musst nach dem Hinzufügen des Komponente noch validate() aufrufen.


Die setVisible()-Methode ist aus Zeile 25 in die Zeile 32 zu verlegen. Also in die letzte Zeile des Konstruktors.


----------



## EvilFairy1001 (9. Apr 2012)

Müsste man dann nicht immer validate() benutzen?
Laut der geposteten Übersicht ist die Aufgabe von validate: Sicherstellen, dass die Kinder eine optimale Position und Grösse haben, und rekursiv dafür sorgen, dass die Kinder ihrerseits validate ausführen.

Mit Kinder sind (denk ich mal) die subclasses von JComponent gemeint.
Dann wäre es doch logisch mit validate immer für optimale Position und Größe zu sorgen, oder?
Und was hat validate (also die optimale Position und Größe) mit meinem Problem zu tun?


----------



## L-ectron-X (9. Apr 2012)

Normalerweise wird man für diese Aufgabe eine JList benutzen. Wenn du die Aufgaben löschen oder editieren willst, wird's mit deiner Lösung schon umständlich.
Dein Code ein wenig umgeschrieben kann so aussehen und funktionieren. 

```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ToDoListe {

    private JFrame frame;
    private JDialog popupDialog;
    private JPanel background;
    private JPanel popupBackground;
    private JTextField nameField;
    private JLabel task;
    private Box verticalBox;

    private String name;

    public static void main (String [] args) {
        ToDoListe list = new ToDoListe();
        //list.buildGUI();
    } //close main()

    public ToDoListe() {
        frame = new JFrame("ToDo Liste");
        frame.setSize(300, 400);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        background = new JPanel();
        background.setLayout(new BoxLayout(background, BoxLayout.Y_AXIS));
        verticalBox = Box.createVerticalBox();
        background.add(verticalBox);
        
        frame.add(BorderLayout.CENTER, background);

        JButton addTask = new JButton ("Neue Aufgabe hinzufügen");
        addTask.addActionListener(new Task());
        frame.add(BorderLayout.SOUTH, addTask);
        frame.setVisible(true);
    } //close buildGUI()

    public void addingTask() {
        popupDialog = new JDialog(frame, "Neue Aufgabe", true);

        popupBackground = new JPanel();
        popupBackground.add(new JLabel("Aufgabe:"));

        nameField = new JTextField("Bitte eingeben!", 20);
        popupBackground.add(nameField);

        popupDialog.add(BorderLayout.NORTH, popupBackground);

        JButton saveTask = new JButton("Aufgabe speichern");
        saveTask.addActionListener(new TaskSave());

        popupDialog.add(BorderLayout.SOUTH, saveTask);
        popupDialog.setSize(400,200);
        popupDialog.setLocationRelativeTo(frame);
        popupDialog.setVisible(true);
    } //close addingTask()

    public void savingTask() {
        popupDialog.setVisible(false);
        popupDialog.dispose();

        task = new JLabel(nameField.getText().trim());
        task.setAlignmentX(JLabel.CENTER_ALIGNMENT);
        verticalBox.add(task);
        background.validate();
    } //close savingTask()

    class Task implements ActionListener {
        public void actionPerformed (ActionEvent event) {
            addingTask();
        } //close actionPerformed()
    } //close Task

    class TaskSave implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            savingTask();
        } //close actionPerformed()
    } //close TaskSave
} //close ToDoListe
```
Aber wie gesagt, eine JList wäre wesentlich effektiver. Umbauen/verbessern darfst du nun.


----------



## EvilFairy1001 (10. Apr 2012)

Die Antworten auf diese Fragen würden mich immer noch interessieren:


EvilFairy1001 hat gesagt.:


> Müsste man dann nicht immer validate() benutzen?
> Laut der geposteten Übersicht ist die Aufgabe von validate: Sicherstellen, dass die Kinder eine optimale Position und Grösse haben, und rekursiv dafür sorgen, dass die Kinder ihrerseits validate ausführen.
> 
> Mit Kinder sind (denk ich mal) die subclasses von JComponent gemeint.
> ...




Und für was ist die "Box"? Sorgt die in dem geposteten Code einfach nur dafür das die ganzen Elemente vertikal angeordnet werden? (bzw. horizontal wenn's HorizontalBox ist?)


----------



## L-ectron-X (10. Apr 2012)

EvilFairy1001 hat gesagt.:


> Müsste man dann nicht immer validate() benutzen?


Nein, nur wenn zur Laufzeit neue Komponenten auf der GUI verankert wurden.
validate() beauftragt die VM die GUI neu zu berechnen und zu zeichnen.



EvilFairy1001 hat gesagt.:


> Und für was ist die "Box"? Sorgt die in dem geposteten Code einfach nur dafür das die ganzen Elemente vertikal angeordnet werden? (bzw. horizontal wenn's HorizontalBox ist?)


Box ist eine Komponente, die bereits das BoxLayout besitzt. In ihr werden die Komponenten entsprechend der für die Box eingestellten Layout-Strategie angeordnet.

Siehe auch FAQ. http://www.java-forum.org/bilder-gui-damit-zusammenhaengt/117293-boxlayout.html


----------

