Search code examples
javaswingjbuttonactionlistenerjtextfield

Run JButton ActionListener in different class


I'm trying to run my JButton ActionListener in a different class than my GUI. So I get the button working, but I can't "access" the TextFields, they are just "empty" when I want to access them.

So that's my GUI Class:

public class CaeserGUI extends JFrame {

    JPanel contentPane;
    private JTextField txt_input;
    private JTextField number_input;
    private JButton btn_translate;
    private JTextArea txt_output;
    private JTextField txt_input2;
    private JTextField number_input2;
    private JTextArea txt_output2;

    /**
     * Launch the application.
     * Author: Paul Viehmann
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    CaeserGUI frame = new CaeserGUI();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public CaeserGUI() {

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        txt_input = new JTextField();
        txt_input.setBounds(10, 38, 363, 20);
        contentPane.add(txt_input);
        txt_input.setColumns(10);

        number_input = new JTextField();
        number_input.setBounds(383, 38, 41, 20);
        contentPane.add(number_input);
        number_input.setColumns(10);

        JTextPane txtpnZubersetzenderSatz = new JTextPane();
        txtpnZubersetzenderSatz.setText("Zu \u00FCbersetzender Satz:");
        txtpnZubersetzenderSatz.setBounds(10, 11, 126, 20);
        contentPane.add(txtpnZubersetzenderSatz);

        JTextPane txtpnVerschiebung = new JTextPane();
        txtpnVerschiebung.setText("Verschiebung:");
        txtpnVerschiebung.setBounds(349, 11, 75, 20);
        contentPane.add(txtpnVerschiebung);

        txt_output = new JTextArea();
        txt_output.setBounds(10, 69, 414, 40);
        contentPane.add(txt_output);

        JTextPane txtpnZuDechiffrierenderSatz = new JTextPane();
        txtpnZuDechiffrierenderSatz.setText("Zu dechiffrierender Satz:");
        txtpnZuDechiffrierenderSatz.setBounds(10, 120, 126, 20);
        contentPane.add(txtpnZuDechiffrierenderSatz);

        txt_input2 = new JTextField();
        txt_input2.setColumns(10);
        txt_input2.setBounds(10, 147, 363, 20);
        contentPane.add(txt_input2);

        number_input2 = new JTextField();
        number_input2.setColumns(10);
        number_input2.setBounds(383, 147, 41, 20);
        contentPane.add(number_input2);

        JTextPane textPane_1 = new JTextPane();
        textPane_1.setText("Verschiebung:");
        textPane_1.setBounds(349, 120, 75, 20);
        contentPane.add(textPane_1);

        txt_output2 = new JTextArea();
        txt_output2.setBounds(10, 176, 414, 40);
        contentPane.add(txt_output2);

        ActionListener actionListener = new ButtonListener(number_input, number_input2, btn_translate, txt_output, txt_input, txt_input2, txt_output2);

        btn_translate = new JButton("\u00DCbersetzen");
        btn_translate.addActionListener(actionListener);
        btn_translate.setBounds(10, 227, 414, 23);
        contentPane.add(btn_translate);
    }
}

And that's my Listener class:

    public class ButtonListener implements ActionListener{

    private JTextField txt_input;
    private JTextField number_input;
    private JButton btn_translate;
    private JTextArea txt_output;
    private JTextField txt_input2;
    private JTextField number_input2;
    private JTextArea txt_output2;

    public ButtonListener(JTextField txt_input, JTextField number_input,
                            JButton btn_translate, JTextArea txt_output, 
                            JTextField txt_input2, JTextField number_input2, 
                            JTextArea txt_output2){

        this.txt_input = txt_input;
        this.number_input = number_input;
        this.btn_translate = btn_translate;
        this.txt_output = txt_output;
        this.txt_input2 = txt_input2;
        this.number_input2 = number_input2;
        this.txt_output2 = txt_output2;
    }

    public void actionPerformed(ActionEvent e){
        if(txt_input.getText().equals("")){
            System.exit(0);
        }else{
        }
    }
}

When I press the button, my program exit even when I write something in the textField.

I read a lot of other posts, but couldn't get it to work.

I appreciate every answer.


Solution

  • You seem to be passing the parameters in the incorrect order (as far as I can tell, based on your naming conventions)

    +---------------------------+--------------------------+
    | ActionListener Parameters | The Order You're Passing |
    +---------------------------+--------------------------+
    | txt_input                 | number_input             |
    | number_input              | number_input2            |
    | btn_translate             | btn_translate            |
    | txt_output                | txt_output               |
    | txt_input2                | txt_input                |
    | number_input2             | txt_input2               |
    | txt_output2               | txt_output2              |
    +---------------------------+--------------------------+
    

    This means, when you inspect the value of txt_input in your ActionListener, you're actually looking at the number_input value ... this allow screams issues to me

    My "general" recommendation would be to create an interface which provide getters and setters, with better names than "text" and "text2", so you can better differentiate their meaning. I'd have CaeserGUI implement this interface and then pass it to the ActionListener, which took a single reference to an instance of said interface

    Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify

    If you think I'm be over reactive, this is what happens when I run your code on my PC

    Bad Layout

    See how the "caret" in the second field is broken?

    I would recommend using JLabels to provide prompts to the fields instead of setting their text, because that's just confusing. See How to Use Labels for more details

    Components like JTextPane really benefit from been wrapped in a JScrollPane, this will allow the user to see the text when it expands beyond the visual boundaries of the component. See How to Use Scroll Panes for more details