Dynmische Textfelder erstellen

Upgrade

Mitglied
Hallo zusammen ich habe wieder mal ein Problem.=)

Ich habe ein Frame auf dem zwei JPanel liegen.
Dort sind per GridBagLayout jeweils 2 Label (Straße und Name) eingefügt.
Weiter unten ein Button.

Ziel ist es, dass man auf den Button „Neu“- klickt und dann dynamisch jeweils ein Textfeld für das Panel „Name“ und eines für das Panel „Straße“ erscheint.

Im moment klappt es nur, wenn ich in die Positionierung eine for- Schleife setze.
Das will ich aber nicht da es ja dynamisch sein soll.

Wenn ich es dynamisch versuche wird nichts angezeigt.

Ich hoffe ihr habt eine Idee.
Hier habe ich ein kleines KSKB.

Zur Info:
Die 6 Textfelder unter Name sind in der Positionierung mit einer for- Schleife eingefügt.

Vielen Dank im voraus.

Java:
package project1;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridBagConstraints;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;


public class MainDialog extends Frame
{
  private JFrame MainFrame = new JFrame();  
  private JPanel MainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT,5,5));
  private JPanel Name =new JPanel(new FlowLayout(FlowLayout.LEFT,5,5));
  private JPanel Strasse =new JPanel(new FlowLayout(FlowLayout.LEFT,5,5));  
  private JLabel lblName = new JLabel("<html><u><b>Name:</u></b></html>");
  private JLabel lblStrasse = new JLabel("<html><u><b>Straße:</u></b></html>");  
  private JButton btnNew = new JButton(" NEU ");  
  private JTextField textField = new JTextField();  
  private boolean isClicked = false;
  
  public MainDialog()
  {
    super();
    MainFrame.setMinimumSize(new Dimension(800,600));
    MainFrame.setTitle("Beispiel Programm");
 
 //Panels initialisieren   
    Name.setPreferredSize(new Dimension(125,400)); 
    Strasse.setPreferredSize(new Dimension(125,400));
  
//Labels initialisieren
    lblName.setFont(new Font("",Font.PLAIN,14));
    lblStrasse.setFont(new Font("",Font.PLAIN,14));
   
//Button initialisieren
    btnNew.setPreferredSize(new Dimension(100,30));
    btnNew.setFont(new Font("Arial",Font.BOLD,14));
    btnNew.addActionListener(new ActionListener()
                                              {
                                                public void actionPerformed(ActionEvent e) 
                                                {

                                                }         
                                              });     
      
     
//Positionierung der Panel, Label und Button mit einem GridBagLayout  
    GridBagConstraints c = new GridBagConstraints();
    GridBagConstraints gridBagConstraints;  

//Hier werden die Textfelder statisch eingefügt....    
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 0;
    c.gridy = 0;
    Name.add(lblName, c);
    MainPanel.add(Name,c);
    for (int i = 0; i < 6; i++)
     { 
       JTextField textField = new JTextField();
       textField.setPreferredSize(new Dimension(100,20));
       gridBagConstraints = new GridBagConstraints(); 
       gridBagConstraints.gridx = i;
       gridBagConstraints.gridy = 0;
       Name.add(textField);      
     }

//hier sollen die Textfelder dynamisch eingefügt werden.     
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 1;
    c.gridy = 0;
    Strasse.add(lblStrasse, c);
    MainPanel.add(Strasse,c);
 
 
 //Button positionierung   
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 2;
    c.gridy = 0;
    MainPanel.add(btnNew,c); 
    
       
    MainFrame.add(MainPanel);
    
    
    // Beenden der Applikation 
    MainFrame.addWindowListener(new WindowAdapter()
        {
          public void windowClosing(WindowEvent e)
          {          
            System.exit(0);
          }
        });
    

    MainFrame.setVisible(true);                 
  }



//------------------------------------------------------------------------------
// Hier wird das programm gestartet.
//------------------------------------------------------------------------------ 

  public static void main(String[] args)
  {
    MainDialog mainDialog = new MainDialog();
  }
}
 
Wenn ich Dich richtig verstanden habe, möchtest Du, dass bei einem Klick auf den Button "Neu" ein neues Textfeld in der Spalte "Name" und ein neues Textfeld in der Spalte "Straße" auftaucht, und nicht wie in Deinem Beispiel sechs Textfelder unter "Name" oder?​
Ich würde dazu zunächst eine Integer-Variable
Code:
rows
innerhalb deiner Klasse einführen, in der gespeichert wird, wie viele Zeilen deine Tabelle aus Textfeldern enthält. Dies würde dann Deiner Variable i aus der for-Schleife entsprechen.​
Anschließend solltest Du eine Methode definieren, die bei jedem Aufruf
Code:
rows
um 1 inkrementiert und anschließend jeweils ein Textfeld in die Spalte "Name" und in die Spalte "Stadt" einfügt:
Java:
JTextField textField = new JTextField();
textField.setPreferredSize(new Dimension(100,20));
gridBagConstraints = new GridBagConstraints(); 
gridBagConstraints.gridx = rows;
gridBagConstraints.gridy = 0;
Name.add(textField);
Diese Methode solltest Du dann aus der actionPerformed-Methode aus aufrufen.​
Abschließend würde ich mir noch Gedanken darüber machen, die erzeugten Textfelder in einer
Code:
LinkedList<JTextField>
oder ähnlichem zu speichern, damit Du anschließend auch auf sie zugreifen kannst, um ihren Text auszulesen.​
Ich habe das ganze natürlich nicht selbst probiert, aber denke, dass es so funktionieren müsste. Sollte ich Dich falsch verstanden haben oder noch irgendetwas unklar sein, einfach nachfragen.​
 
Zuletzt bearbeitet:
HI erstmal vielen Dank für die schnelle Antwort.

Ja also die 6 Textfelder füge ich ja statisch ein.

Aber wenn ich den Quellcode sehe, dann adde ich ja nur das Textfed in Name oder??
(Zeile 6)

Ich müsste es aber doch irgendwie Name und Straße übergeben oder ?
Also in etwa so: Name.add(Textfield) und Straße.add(Textfield) geht sowas??

Oder habe ich einen Gedanken fehler??

Gruß Upgrade
 
das kannst du in deinen btnNew actionlistener schreiben:

Java:
btnNew.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
				// zeile hochzählen
				currentRow++;
				// neues name-textfeld erzeugen
				JTextField nameTextField = new JTextField();
				nameTextField.setPreferredSize(new Dimension(100,20));
				// neues strasse-textfeld erzeugen
				JTextField strasseTextField = new JTextField();
				strasseTextField.setPreferredSize(new Dimension(100,20));
				
				// constraint anpassen
				c.fill = GridBagConstraints.HORIZONTAL;
				c.gridx = 1;
				c.gridy = currentRow;
				
				// name und straßetextfeld den panels hinzufügen
				Name.add(nameTextField, c);
				Strasse.add(strasseTextField,c);
				// panels aktualisieren (sonst sind die textfelder nicht direkt sichtbar)
				Name.updateUI();
				Strasse.updateUI();
			}
		});

zusätzlich brauchst du eine globale zählvariable:
Java:
	private static int currentRow = 0;

wenn du Zugriff auf die Felder brauchst, kannst du diese zusätzlich in einem Array ablegen
Java:
// globals
	private Vector<JTextField> nameFieldVector = new Vector<JTextField>();
	private Vector<JTextField> strasseFieldVector = new Vector<JTextField>();

und die Button-Action würde dann so aussehen:
Java:
		btnNew.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
				// zeile hochzählen
				currentRow++;
				// neues name-textfeld erzeugen
				nameFieldVector.add(new JTextField());
				nameFieldVector.lastElement().setPreferredSize(new Dimension(100,20));
				// neues strasse-textfeld erzeugen
				strasseFieldVector.add(new JTextField());
				strasseFieldVector.lastElement().setPreferredSize(new Dimension(100,20));
				
				// constraint anpassen
				c.fill = GridBagConstraints.HORIZONTAL;
				c.gridx = 1;
				c.gridy = currentRow;
				
				// name und straßetextfeld den panels hinzufügen
				Name.add(nameFieldVector.lastElement(), c);
				Strasse.add(strasseFieldVector.lastElement(),c);
				// panels aktualisieren (sonst sind die textfelder nicht direkt sichtbar)
				Name.updateUI();
				Strasse.updateUI();
			}
		});
 
HI ja das funktioniert ja prima vielen Dank :toll: :applaus:

Hab da aber noch eine Frage..

Ist das denn saubrer Stil ??

Oder sollman die lieberin eine eigene Funktion packen, und die dann in dem ActionListener aufrufen ??

Gruß Upgrade
 
Also dynimsch neue Textfelder erzeugen ist in einer GUI alles andere als sauberer Stil. Willst du eine mehrzeilige Texteingabe ermöglichen? Dann schau dir mal JTextArea an...
 
es ist prinzipiell nicht verkehrt, den Inhalt von actionlistenern auszulagern

derzeitige style-tools sind inzwischen soweit, dass sie 2+ zeilen duplicate code als fehler makieren
Java:
// zeile hochzählen
                currentRow++;
                // neues name-textfeld erzeugen
                JTextField nameTextField = new JTextField();
                nameTextField.setPreferredSize(new Dimension(100,20));
                // neues strasse-textfeld erzeugen
                JTextField strasseTextField = new JTextField();
                strasseTextField.setPreferredSize(new Dimension(100,20));
                
                // constraint anpassen
                c.fill = GridBagConstraints.HORIZONTAL;
                c.gridx = 1;
                c.gridy = currentRow;
                
                // name und straßetextfeld den panels hinzufügen
                Name.add(nameTextField, c);
                Strasse.add(strasseTextField,c);
                // panels aktualisieren (sonst sind die textfelder nicht direkt sichtbar)
                Name.updateUI();
                Strasse.updateUI();

würde ich so aufbrechen:
Java:
		btnNew.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e)
			{
				newBtnKlick();
			}
		});

	private void newBtnKlick()
	{
		// zeile hochzählen
		currentRow++;
		// constraint anpassen
		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridx = 1;
		c.gridy = currentRow;
		// neues name-textfeld erzeugen
		nameFieldVector.add(genTextField());
		// neues strasse-textfeld erzeugen
		strasseFieldVector.add(genTextField());
		// name und straßetextfeld den panels hinzufügen
		Name.add(nameFieldVector.lastElement(), c);
		Strasse.add(strasseFieldVector.lastElement(),c);
		// panels aktualisieren (sonst sind die textfelder nicht direkt sichtbar)
		Name.updateUI();
		Strasse.updateUI();		
	}

	private JTextField genTextField()
	{
		JTextField tmp = new JTextField();
		tmp.setPreferredSize(new Dimension(100,20));
		return tmp;
	}

und das ganze dann noch ohne magic numbers
Bsp. c.gridx = 1;
=>
private static final int DEFAULT_LAYOUT_X = 1;
c.gridx = DEFAULT_LAYOUT_X;

und mit vernümpftigen bezeichnern,
Bsp. Name => NamenFldPanel
 
Sry für den Doppelpost:

für solche Eingabemasken würde ich eine JTable in einer JScrollpane benutzen, das ist wesentlich sauberer
 
Hmmm.. ja okay dann werd ich das erstmal auslagern und wenn das alles funktioniert, kann ich mir ja mal Gedanken zu Stil machen =)

Vielen Dank an euch alle für die schnelle Hilfe :toll:

Upgrade
 

Zurück
Oben