JTextField erstellen und löschen

newprogrammer

Grünschnabel
Hallo an alle, zu allererst möchte ich sagen, dass ich die Suchfunktion genutzt aber nichts entsprechendes für mein Problem finden konnte. :)

Hier zu meinem Problem... ich möchte aus Testzwecken eine Endlosschleife errichten in der:

erstens: Label "one" und TextField 1, sobald TextField1 mit enter bestätigt wurde kommt ->
zweitens: Label "two" und TextField 2, sobald TextField2 mit enter bestätigt wurde kommt ->
drittens: Button, sobald Button gedrückt wurde kommt wieder erstens.

Zwischen den drei Teilschritten soll alles gelöscht werden.
Einfache Aufgabenstellung doch ich schaff es nicht sie einwandfrei zu lösen...
Hier mein Code:

Code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;


public class Test extends JFrame implements ActionListener{
	
	JTextField tf2 = new JTextField();
	JTextField tf1 = new JTextField();
	JLabel one = new JLabel("one");
	JButton b = new JButton("Again!");
	JLabel two = new JLabel("two");
	Test()
	{
		this.setLayout(new GridLayout(2,1));
		
		add(one);
		setSize(200, 200);
		add(tf1);
		pack();
		tf1.addActionListener(this);
		setVisible(true);
		
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		
		String cmd = e.getActionCommand();
		if(e.getSource() == tf1)
		{
			remove(one);
			remove(tf1);
			tf1.removeActionListener(this);
			
			add(two);
			add(tf2);
			tf2.setText("");
			tf2.addActionListener(this);
			tf2.requestFocus();
			pack();
			System.out.println("TF1 removed, TF2 added");
		}
		
		if(e.getSource() == tf2)
		{
			tf2.removeActionListener(this);
			remove(tf2);
			remove(two);
			add(b);
			b.addActionListener(this);
			b.requestFocus();
			pack();
			System.out.println("TF2 removed, b added");

		}
		if(e.getSource() == b)
		{
			remove(b);
			add(one);
			tf1.addActionListener(this);
			add(tf1);
			tf1.setText("");
			tf1.requestFocus();
			pack();
			System.out.println("b removed, TF1 added");

		}
			
		
	}

}


Vielen Dank für eure Mühe****** :)
 

hendl

Erfahrenes Mitglied
Wie siehts mit dem aus? :D

Java:
package helper_tut2;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.*;
 
 
public class Test extends JFrame implements ActionListener{
    
    JTextField tf2 = new JTextField();
    JTextField tf1 = new JTextField();
    JLabel one = new JLabel("one");
    JButton b = new JButton("Again!");
    JLabel two = new JLabel("two");
    Test()
    {
        this.setLayout(new GridLayout(2,1));
        
        add(one);
        setSize(200, 200);
        add(tf1);
        pack();
        tf1.addActionListener(this);
        setVisible(true);
        
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        
        String cmd = e.getActionCommand();
        if(e.getSource() == tf1)
        {
            remove(one);
            remove(tf1);
            tf1.removeActionListener(this);
            
            add(two);
            add(tf2);
            tf2.setText("");
            tf2.addActionListener(this);
            tf2.requestFocus();
            revalidate();
        	repaint();
            System.out.println("TF1 removed, TF2 added");
        }
        
        if(e.getSource() == tf2)
        {
            tf2.removeActionListener(this);
            remove(tf2);
            remove(two);
            add(b);
            b.addActionListener(this);
            b.requestFocus();
            revalidate();
           	repaint();
            System.out.println("TF2 removed, b added");
 
        }
        if(e.getSource() == b)
        {
            remove(b);
            add(one);
            tf1.addActionListener(this);
            add(tf1);
            tf1.setText("");
            tf1.requestFocus();
            revalidate();
        	repaint();
            System.out.println("b removed, TF1 added");
 
        }
            
        
    }
    public static void main(String arg[]){
    	new Test();
    }
 
}

Lg hendl
 
Zuletzt bearbeitet:

newprogrammer

Grünschnabel
WOW danke Hendl!
Also optisch genau das was ich gesucht habe! Optimal!
aber...
im Programm selber läuft das ganze noch immer nicht ganz flüssig... je öffter ich die Schleife durchlaufe desto öffter bekommt er eine Source...
Ich habe in jeder IF-Bedingung beim ActionPerformed eine println mit dem jeweiligen Text was getan wurde... und hier mal ein Ausdruck von mir wenn ich ein paar mal durch das Programm gehe:

"
TF1 removed, TF2 added
TF2 removed, b added
b removed, TF1 added
TF1 removed, TF2 added
TF2 removed, b added
b removed, TF1 added
b removed, TF1 added
TF1 removed, TF2 added
TF1 removed, TF2 added
TF2 removed, b added
TF2 removed, b added
b removed, TF1 added
b removed, TF1 added
b removed, TF1 added
b removed, TF1 added
TF1 removed, TF2 added
TF1 removed, TF2 added
TF1 removed, TF2 added
TF1 removed, TF2 added
TF2 removed, b added
TF2 removed, b added
TF2 removed, b added
TF2 removed, b added"

In dem richtigen Programm in dem ich das zum laufen bringen möchte bricht mir genau dieses Phänomen das Genick...

Danke schonmal! :)
 

hendl

Erfahrenes Mitglied
Ich sehe eigentlich keine Fehler im direkten Code, da es erst ab dem 2 Buttonclick zu buggen beginnt und vorher nicht

Lg hendl
 

Writtscher

Mitglied
Wie wärs mit sowas:

Code:
public class WizardFrame extends JFrame {
    private JTextField first = new JTextField();
    private JTextField second = new JTextField();
    private JButton third = new JButton();

    private Wizard wizard = WizardConfigurer.newConfigForFrame(this)
            .first(first)
                .next(second)
                .next(third)
            .end();

    public WizardFrame(String title, int width, int height) {
        super(title);
        setMinimumSize(new Dimension(width, height));
        setVisible(true);
        wizard.start();
    }

}

Code:
public class WizardConfigurer {
    private JFrame frame;
    private List<JComponent> steps = new ArrayList<>();

    private WizardConfigurer(JFrame frame) {
        this.frame = frame;
    }

    public static WizardConfigurer newConfigForFrame(JFrame frame) {
        return new WizardConfigurer(frame);
    }

    public WizardConfigurer first(JComponent jComponent) {
        this.steps.clear();
        this.steps.add(jComponent);
        return this;
    }

    public WizardConfigurer next(JComponent jComponent) {
        this.steps.add(jComponent);
        return this;
    }

    public Wizard end() {
        return new Wizard(frame, steps);
    }
    
}

Code:
public class Wizard {

    private final ActionListener actionListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            frame.remove(currentActiveComponent);

            if (stepIndex == steps.size()) {
                stepIndex = 0;
            }

            exchangeComponent();
        }
    };

    protected final JFrame frame;
    protected final List<JComponent> steps;

    private JComponent currentActiveComponent;
    private int stepIndex = 0;

    public Wizard(JFrame frame, List<JComponent> steps) {
        this.frame = frame;
        this.steps = steps;
    }

    public void start() {
        configureComponents();
        exchangeComponent();
    }

    private void configureComponents() {
        for (JComponent jComponent : steps) {
            if (jComponent instanceof JTextField) {
                ((JTextField) jComponent).addActionListener(actionListener);
            } else if (jComponent instanceof JButton) {
                ((JButton) jComponent).addActionListener(actionListener);
            }
        }

    }

    private void exchangeComponent() {
        currentActiveComponent = steps.get(stepIndex);
        frame.add(currentActiveComponent);
        currentActiveComponent.requestFocus();
        stepIndex++;
        frame.pack();
        frame.repaint();
    }
}

Code:
public class Start{

    public static void main(String arg[]){
        new WizardFrame("Wizard", 500, 500);
    }

}

Das ist jetzt nur eine Idee und nicht ganz ausgereift funktioniert aber. Ist aber auf jeden Fall optimierungsbedürftig.
 
Zuletzt bearbeitet:

hendl

Erfahrenes Mitglied
Hi ist jetzt nicht die schönste Lösung aber auf jeden Fall die einfachste :D
Java:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.*;
 
 
public class Test extends JFrame implements ActionListener{
    
    JTextField tf2 = new JTextField();
    JTextField tf1 = new JTextField();
    JLabel one = new JLabel("one");
    JButton b = new JButton("Again!");
    JLabel two = new JLabel("two");
    private String last="";
    Test()
    {
        this.setLayout(new GridLayout(2,1));
        
        add(one);
        setSize(400, 400);
        add(tf1);
        pack();
        tf1.addActionListener(this);
        setVisible(true);
        
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        
        String cmd = e.getActionCommand();
        if(e.getSource() == tf1&&!"tf1".equals(last))
        {
            remove(one);
            remove(tf1);
            tf1.removeActionListener(this);
            
            add(two);
            add(tf2);
            tf2.setText("");
            tf2.addActionListener(this);
            tf2.requestFocus();
            revalidate();
        	repaint();
            System.out.println("TF1 removed, TF2 added");
            last="tf1";
        }
        else
        if(e.getSource() == tf2&&!"tf2".equals(last))
        {
            tf2.removeActionListener(this);
            remove(tf2);
            remove(two);
            add(b);
            b.addActionListener(this);
            b.requestFocus();
            revalidate();
           	repaint();
            System.out.println("TF2 removed, b added");
            last="tf2";
 
        }
        else
        if(e.getSource() == b&&!"b".equals(last))
        {
            remove(b);
            add(one);
            tf1.addActionListener(this);
            add(tf1);
            tf1.setText("");
            tf1.requestFocus();
            revalidate();
        	repaint();
            System.out.println("b removed, TF1 added");
            last="b";
 
        }
            
        
    }
    public static void main(String arg[]){
    	new Test();
    }
 
}
 

newprogrammer

Grünschnabel
ok hab mir das mim Wizard mal angeschaut doch mir fehlt da zuviel wissen darüber... mit dem lastString hab ichs jetzt auch zum laufen gebracht... frag mich nur wieso der so oft in die Methoden gesprungen ist und es nicht auch ohne gegangen wär... naja!
Danke euch****** :)
 

Improof

Erfahrenes Mitglied
Ich kann dir schon sagen, warum er die Methoden so oft aufruft.
Also ich hab den Code von hendl jetzt nur überflogen, aber mir ist der Fehler gerade zu ins Auge gesprungen: Der ActionListener wird bei jedem Aufruf der actionPerformed-Methode erneut hinzugefügt, was aber nicht heißt, dass er überschrieben wird, sondern einfach, dass er dann zweimal verknüpft ist.

Das führt dementsprechend natürlich dazu, dass der Listener auch zweimal aufgerufen wird - und wieder hinzugefügt wird, diesmal zweimal.
Ergebnis: 4 registrierte Listener -> 4 Aufrufe -> 4mal hinzufügen -> 8 Listener ... usw.

Im zweiten Code wurde das (evtl.) behoben durch den Aufruf von removeActionListener(this); allerdings hab ichs jetzt nicht getestet, inwiefern da doch Fehler auftreten könnten.


Tipp meinerseits: ActionListener (und allgemein Listener) immer da hinzufügen, wo das Objekt instanziert (also gebaut) wird. Ist das im ActionListener der Fall, dann ist es ja ok, den Listener da hinzuzufügen, aber nur, weil das Objekt anschließend wieder gelöscht wird. Aber wenn du deine Objekte (insbesondere AWT/Swing-Komponenten) außerhalb instanzierst und du das Objekt nicht mehr löscht (was bei GUI-Komponenten sowieso nicht allzu sinnvoll ist) solltest du auch direkt den ActionListener an dieser Stelle hinzufügen (einfach Fragen, falls das jetzt zu kompliziert war).

Das ganze hat einfach folgenden Hintergrund: Da sich die anzahl der Listener immer verdoppelt, verdoppelt sich natürlich auch die Anzahl der Aufrufe des ActionListeners. Bei dem Klick auf einen Button scheint das erst, keine allzu großen Auswirkungen zu haben, solange du in einem kleinen Rahmen bleibst, so wie bei diesem Programm.
Machst du allerdings eine Datenbankabfrage über den Button, dann wirds dir schon anders, wenn plötzlich 64 Datenbank-Calls auf einmal ausgeführt werden. Das lastet die Datenbank, also den Datenbankserver und deinen PC enorm aus.


So und falls das jetzt doch zu viel war, kannst du gern nochmal genauer nachfragen, was du ncht verstanden hast ode rne PN an mich schicken, dann erklär ichs dir nochmal ganz genau ;)

Gruß
Improof