user163505
user163505

Reputation: 499

Java: How do I pass variables from JButton ActionListener to main class?

I am trying to make a program that generates a random number when a button is clicked and then the output is displayed on the screen. However, I can't pass the variable that holds the random number into the class with the JLabel so that it can be used in that class. I wrote a program that is as simple as I could make it to demonstrate:

import java.awt.BorderLayout;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

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

public class Main{
    public static void main(String[] args){

    JFrame mainFrame = new JFrame("Experiment");
    mainFrame.setSize(500,500);
    mainFrame.setVisible(true);

    Panel panel = new Panel();
    mainFrame.getContentPane().add(panel);

    JLabel output = new JLabel("This is where the result from the num variable in the numGenerator class would go"); 
    panel.add(output); 

    JButton numGenerator = new JButton("Generate Number");
    panel.add(numGenerator);
    numGenerator.addActionListener(new numGenerator());

    }

static class numGenerator implements ActionListener{
    public void ActionPerfomed (ActionEvent e){

        int num; //This is the variable I want to be passed to the
                 //Main class so it can be displayed in the "output" Jlabel.

        Random dice = new Random();
        num = dice.nextInt(3);

    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub

    }
}
}

I saw other help online to create an object of the class and then use that in the class you want the variable to be in, but I couldn't get that to work in this situation.

Upvotes: 2

Views: 14677

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347204

There are a number of methods that you could use to accomplish this...

You Could...

Make a class, instance variable available for the numGenerator to access directly...

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

    // This variable will be visible to the inner class numGenerator
    private JLabel output;

    public Main() {
        JFrame mainFrame = new JFrame("Experiment");
        mainFrame.setSize(500,500);
        mainFrame.setVisible(true);

        Panel panel = new Panel();
        mainFrame.getContentPane().add(panel);

        output = new JLabel("This is where the result from the num variable in the numGenerator class would go"); 
        panel.add(output); 

        JButton numGenerator = new JButton("Generate Number");
        panel.add(numGenerator);
        numGenerator.addActionListener(new numGenerator());
    }

    public class numGenerator implements ActionListener{
        public void actionPerformed(ActionEvent e){

            Random dice = new Random();
            int num = dice.nextInt(3);
            output.setText(Integer.toString(num));

        }
    }
}

This tightly couples you action with your label, making the code less reusable...

You could...

Pass a reference of the label to be changed to the numGenerator...

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

    public Main() {
        JFrame mainFrame = new JFrame("Experiment");
        mainFrame.setSize(500,500);
        mainFrame.setVisible(true);

        Panel panel = new Panel();
        mainFrame.getContentPane().add(panel);

        JLabel output = new JLabel("This is where the result from the num variable in the numGenerator class would go"); 
        panel.add(output); 

        JButton numGenerator = new JButton("Generate Number");
        panel.add(numGenerator);
        numGenerator.addActionListener(new numGenerator(output));
    }

    public class numGenerator implements ActionListener{
        private JLabel label;

        public numGenerator(JLabel label) {
            this.label = label;
        }

        public void actionPerformed(ActionEvent e){

            Random dice = new Random();
            int num = dice.nextInt(3);
            if (label != null) {
                label.setText(Integer.toString(num));
            }

        }
    }
}

This makes the numGenerator more reusable, as it's not reliant on a single instance of the JLabel

You Could...

Use a Observer style pattern that could tell some interested party that a new number has being generated...

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

    public Main() {
        JFrame mainFrame = new JFrame("Experiment");
        mainFrame.setSize(500,500);
        mainFrame.setVisible(true);

        Panel panel = new Panel();
        mainFrame.getContentPane().add(panel);

        final JLabel output = new JLabel("This is where the result from the num variable in the numGenerator class would go"); 
        panel.add(output); 

        JButton numGenerator = new JButton("Generate Number");
        panel.add(numGenerator);
        numGenerator.addActionListener(new numGenerator(new NumberGeneratorListener() {
            public void numberGenerated(int number) {
                output.setText(Integer.toString(number));
            }
        }));
    }

    public interface NumberGeneratorListener {
        public void numberGenerated(int number);
    }

    public class numGenerator implements ActionListener{
        private NumberGeneratorListener listener;

        public numGenerator(NumberGeneratorListener listener) {
            this.listener = listener;
        }

        public void actionPerformed(ActionEvent e){

            Random dice = new Random();
            int num = dice.nextInt(3);
            if (listener != null) {
                listener.numberGenerated(num);
            }

        }
    }
}

This not only decouples the numGenerator from the rest of the code, as it's not reliant on any other part of the code, it makes it extremely reusable, as it doesn't care where the number goes or how it is used, that's up to the observer/listener to decide...

Side notes...

You might also want to have a read through...

Upvotes: 5

nachokk
nachokk

Reputation: 14413

First of all, if u want access to the JLabel must be in LEVEL CLASS declaration or pass by parameter in the actionListener, cause ur label reference only lives in the main context.

public class Main{
    public static void main(String[] args){

    JFrame mainFrame = new JFrame("Experiment");
    mainFrame.setSize(500,500);
    mainFrame.setVisible(true);

    Panel panel = new Panel();
    mainFrame.getContentPane().add(panel);

    JLabel output = new JLabel("This is where the result from the num variable in the numGenerator class would go"); 
    panel.add(output); 

    JButton numGenerator = new JButton("Generate Number");
    panel.add(numGenerator);
    numGenerator.addActionListener(new NumGenerator(output));

    }

private class NumGenerator implements ActionListener{
    private final JLabel label;

     public NumGenerator(final JLabel label){
         this.label=label;       
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        int num; 
        Random dice = new Random();
        num = dice.nextInt(3);
        label.setText(num); 
    }
}
}

OR u can do something like this

public class Main{
    //if u want to hold all at class level properties but u really only interested in JLabel
 private JFrame mainFrame;
 private JPanel panel;
 private JLabel label;
 private JButton numGenerator;

//add Constructor
public Main(){
  mainFrame = new JFrame("Experiment");
  mainFrame.setSize(500,500);
  mainFrame.setVisible(true);

panel = new JPanel();
mainFrame.getContentPane().add(panel);
output = new JLabel(); 
panel.add(output); 

numGenerator = new JButton("Generate Number");
panel.add(numGenerator);
numGenerator.addActionListener(new NumGenerator(output));

}

public static void main(String[] args){
  /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
             new Main().mainFrame.setVisible(true);
        }
    });


}

private class NumGenerator implements ActionListener{

   @Override
    public void actionPerformed(ActionEvent arg0) {
        int num; 
        Random dice = new Random();
        num = dice.nextInt(3);
        label.setText(num); // now u have access
    }
}
}

Upvotes: 2

Related Questions