How to pass JTextField from JFrame into another JFrame?

1.1k Views Asked by At

I have two JFrame (JFrame1 and JFrame2) with two JTextField1 and JTextField2. My question is when I write "Hello world " on JTextField2 from Jframe2 and then click on OK button, I see "Hello world " on JTextField1 on Jframe1 class.

How can I do this? I'm sorry if this is a newbie question but I'm learning..

Here is my code:

JFrame2:

private JFrame1 jf1;
private void btn2ActionPerformed(java.awt.event.ActionEvent evt) {                                     
    jf1.setjTextField1(this.jTextField2);
} 
3

There are 3 best solutions below

6
On BEST ANSWER

You could use an Observer Pattern or Producer/Consumer Pattern to solve the problem.

The basic idea is, you have something that generates a value and something that either wants to be notified or consume the generated value.

One of the other prinicples you should take the time to learn is also Code to interface (not implementation). This sounds stranger then it is, but the the idea is to reduce the unnecessary exposure of your objects (to unintended/controlled modifications) and decouple your code, so you can change the underlying implementation without affecting any other code which relies on it

Given the nature of your problem, an observer pattern might be more suitable. Most of Swing's listener's are based on the same principle.

We start by defining the contract that the "generator" will use to provide notification of changes...

public interface TextGeneratorObserver {

    public void textGenerated(String text);
}

Pretty simple. This means we can safely provide an instance of any object that implements this interface to the generator and know that it won't do anything to our object, because the only thing it knows about is the textGenerated method.

Next, we need something that generates the output we are waiting for...

public class GeneratorPane extends JPanel {

    private TextGeneratorObserver observer;
    private JTextField field;
    private JButton button;

    public GeneratorPane(TextGeneratorObserver observer) {
        this.observer = observer;

        field = new JTextField(10);
        button = new JButton("OK");

        ActionListener listener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                observer.textGenerated(field.getText());
            }
        };

        button.addActionListener(listener);
        field.addActionListener(listener);

        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = GridBagConstraints.REMAINDER;
        gbc.insets = new Insets(2, 2, 2, 2);

        add(field, gbc);
        add(button, gbc);
    }

}

This is just a simple JPanel, but it requires you to pass a instance of TextGeneratorObserver to it. When the button (or field) triggers the ActionListener, the ActionListener calls the textGenerated to notify the observer that the text has been generated or changed

Now, we need someone to observer it...

public class ObserverPanel extends JPanel implements TextGeneratorObserver {

    private JLabel label;

    public ObserverPanel() {
        label = new JLabel("...");
        add(label);
    }

    @Override
    public void textGenerated(String text) {
        label.setText(text);
    }

}

This is a simple JPanel which implements the TextGeneratorObserver interface and updates it's JLabel with the new text

Then, we just need to plumb it together

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                ObserverPanel op = new ObserverPanel();
                op.setBorder(new CompoundBorder(new LineBorder(Color.RED), new EmptyBorder(10, 10, 10, 10)));
                GeneratorPane pp = new GeneratorPane(op);
                pp.setBorder(new CompoundBorder(new LineBorder(Color.GREEN), new EmptyBorder(10, 10, 10, 10)));

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridLayout(2, 1));
                frame.add(pp);
                frame.add(op);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

Observer

5
On

This is a complete working example I just coded out:

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

class FrameRunner
{
    public static void main(String[] args){
        MyFrame f1 = new MyFrame("Frame 1");
        MyFrame f2 = new MyFrame("Frame 2");

        f1.addRef(f2);
        f2.addRef(f1);                  
    }       
}

class MyFrame extends JFrame{

    JTextField txt = new JTextField(8);
    JButton btn = new JButton("Send");
    MyFrame f = null;   

    public MyFrame(String title){
        super(title);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setLayout(new FlowLayout());
        setPreferredSize(new Dimension(400, 300));
        setVisible(true);
        add(btn);
        add(txt);
        pack();
        setLocationRelativeTo(null);
        init();         
    }

    public void addRef(MyFrame f){
        this.f = f; 
    }

    public void init(){
        btn.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                f.update(txt.getText());
            }
        });     
    }

    public void update(String str){
        txt.setText(str);
    }   
}

In order to make the code short and easier for you to understand. Many of the things I did not following the conventions and I did not modularize the codes. But this should give you a very good idea of how you can pass in the reference of another JFrame.

This code shows an example of how Frame1 has a reference on Frame2. Yet Frame2 also has a reference on Frame1.

Whatever things you type in JFrame1 can be send to JFrame2's textfield. Same for the other way round.

7
On

What you are doing there is actually sending the reference to the actual JTextField from one frame to the other one.

That's probably not a good idea cause both frames would be end up referencing the same visual component.

What you probably want is to keep all visual components separate, but make the text of the second text field equal to the text in the first one.

Something like this:

private void btn2ActionPerformed(java.awt.event.ActionEvent evt) {                                     
    jf1.getjTextField1().setText(this.jTextField2.getText());
}