Accessing Variable within JButton ActionListener - java

This seems like a very simple problem, but I'm having a lot of trouble figuring out how to deal with it.
Sample Scenario:
final int number = 0;
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setSize(400, 400);
final JTextArea text = new JTextArea();
frame.add(text, BorderLayout.NORTH);
JButton button = new JButton(number + "");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
number++; // Error is on this line
text.setText(number + "");
}});
frame.add(button, BorderLayout.SOUTH);
I really have no idea where to go.

If you declared number as final, you cannot modified its value. You must remove the final modificator.
Then, you can access to that variable via:
public class Scenario {
private int number;
public Scenario() {
JButton button = new JButton(number + "");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Scenario.this.number++;
text.setText(Scenario.this.number + "");
}
});
}
}
The notation "ClassName.this" allow you to access to the object of a class where you are in.
Keep atention in when you use "number" first time, -new JButton(number)-, you can access to number directly, because you are in Scenario scope. But when you use it inside your ActionListener, you are in your ActionListener scope instead of Scenario scope. That is why you cannot see the variable "number" directly inside of your action listener and you have to access to the instance of Scenario where you are in. This can be done by Scenario.this

The fastest solution would be to declare number as static, and reference it using the name of your class.
Alternatively you can make a class that implements ActionListener, and pass number and text into it's constructor.

Related

Using Java Swing, how do you take an input from a user and store it for later use?

I am currently writing a program which takes an input from a user which is a file, and an integer. Both of these fields are entered into the gui, and then when the user clicks the button I prompt them on screen with, the program should then store the two inputs into variables for later use when it comes to searching the file. The issue is that for swing, there needs to be an
ActionListener which is formatted like this:
0 JButton okButton = new JButton("OK");
1 okButton.addActionListener(new ActionListener() {
2 public void actionPerformed(ActionEvent e) {
3 //(WHERE I'M HAVING THE ISSUE)
4 }
5 });
My issue is that the user's click is registered, and then the code within the actionPerformed function (line 2-3) executes, but since it is in its own function, it cannot save to any variables which are made outside of it (which would be above line 0). It also cannot return any values since actionPerformed's return is supposed be void. Not only this, but you can't fully alter the gui inside of this function, so I cannot write the rest of the code inside of it. Is there any way for me to store the two inputs the user puts into my gui as variables which I can use for the rest of my program? For clarification, this is what I want to happen:
String userInput = null;
JButton okButton = new JButton("OK");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//userInput = (the string the user submitted)
}
});
mainFrame.add(okButton);
mainFrame.setVisible(true);
//(And from here on use the updated user input as I need)
Overall I don't understand how to take information from a user input in my gui and store it for later.
ActionListener is a functional interface which means that, since JDK 8, you can implement it with a method reference.
Declare the GUI components, that the user uses to enter the file and the integer, as class member variables so that you can reference them from the method that implements ActionListener, for example:
public class Gui {
private javax.swing.JTextField fileTextField;
private javax.swing.JSpinner integerSpinner;
private void createAndDisplayGui() {
javax.swing.JButton button = new javax.swing.JButton("Hit me!");
button.addActionListener(this::performAction);
}
// 'ActionListener' implementation.
private void performAction(java.awt.event.ActionEvent event) {
String file = fileTextField.getText();
}
}
The name of the method that implements ActionListener interface can be any name you like. It just has to take the same parameters (as method actionPerformed) and return the same value, i.e. void in the case of method actionPerformed which is the sole method in interface ActionListener. Also note that the method need not be public.
If it were me, I'd use a JPanel and JOptionPane
JPanel p = new JPanel();
JTextField tf = new JTextField(); // For the file name. You can use a JFileChooser also
JTextField tf2 = new JTextField(); // For the number;
p.setLayout(new GridLayout(1,2));
p.add(tf);
p.add(tf2);
int result = JOptionPane.showConfirmDialog(null, p);
String fileName = null;
if (result == JOptionPane.OK_OPTION) {
fileName = tf.getText();
}

Java Swing Access Class Variables From Button

So in my Java Swing application, I need a button ActionListener to be able to access variables outside of its scope like so:
int x = 13;
JButton btn = new JButton("New Button");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(x);
}
});
but I get a variable out of scope error. How can I access it?
The action listener is an anonymous inner class. This means that it can only use final variables from an outer scope. So, either declare x as final or pass it into the class some other way.
This should work:
final int x = 13;
JButton btn = new JButton("New Button");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(x);
}
});
Alternatively, see Pass variables to ActionListener in Java for some other options.

Netbeans Swing jButton

I have two buttons and in the second one I want to use a variable made in the first button. So Netbeans is generating code of the button. ActionEvent generated by netbeans is
"private void buttonActionPerformed(java.awt.event.ActionEvent evt)"
and I cant change it. I tried to change button to public in button setting. I changed it to public but in code it is still private. I dont know what to do. Anyone know where the problem might be?
Thanks.
What you want to do is, there is a blank line above the private void buttonActionPerformed(ActionEvent evt) you create your variable in that line the example: int a; now the a will turn green. This is called a global variable
JFrame jtfMainFrame;
JButton jbnButton1, jbnButton2;
JTextField jtfInput;
JPanel jplPanel;
//Declaring the string variable setText
String setText;
public JButtonDemo2() {
jtfMainFrame = new JFrame("Which Button Demo");
jtfMainFrame.setSize(50, 50);
jbnButton1 = new JButton("Button 1");
jbnButton2 = new JButton("Button 2");
jtfInput = new JTextField(20);
jplPanel = new JPanel();
jbnButton1.setMnemonic(KeyEvent.VK_I); //Set ShortCut Keys
jbnButton2.setMnemonic(KeyEvent.VK_I);
jbnButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Setting the setText variable
setText = "Do whatever you want";
}
});
jbnButton2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Displaying the setText variable
jtfInput.setText(setText);
}
});
jplPanel.setLayout(new FlowLayout());
jplPanel.add(jtfInput);
jplPanel.add(jbnButton1);
jplPanel.add(jbnButton2);
jtfMainFrame.getContentPane().add(jplPanel, BorderLayout.CENTER);
jtfMainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jtfMainFrame.pack();
jtfMainFrame.setVisible(true);
}
Simply declare it as a global means when the class definition starts at that time declare the variable which you want to use at the two buttons click and change the value of variable according to your use.
No need to change the ActionPerformed(). All you have to do is declare the variable as a global variable and then do whatever the task inside the button's ActionPerformed().

Enable/Disable button of a form from another class

Hello my problem is: I am not able to enable a button of a form, from another class. My form class is
public class FileSending {
//Function for enabling the button
public void activate_btnSEND (boolean flag) {
SendFile.setEnabled(flag);
}
}
And the class from where i am calling this function is as follows :
public class SMS {
Public void split(){
if(check_string.equalsIgnoreCase("0001")) {
JOptionPane.showMessageDialog(null, " Recepient Has Accepted The" +
" Request.Connection Has Been Established :) ");
FileSending setBtn = new FileSending();
setBtn.activate_btnSEND(true);
}
}
}
I debugged the code to check the value that is being passed to flag and the value is "True". It also goes inside the if condition but the Button is not enabled. I don't understand what is happening here !!
Some points in your code:
First, you are enabling/disbaling, you making it visible if flag is true. You should use setEnabled(b), So SendFile.setVisible(true); will become SendFile.setEnabled(true);
Never compare boolean like this if(flag == true), it should be just if(flag)
And your methhod should be something like this:
public void changeStateOfButton (boolean flag) {
//now what ever you pass will decide whether to enable or disable the button.
myButton.setEnabled(flag);
}
Or more better you should use JToggleButton for such things.
Also improve your variable naming skills.
A small example of what I'm saying:
public class TestButtonEnable {
public static void main(String[] args) {
JFrame frame = new JFrame("TestButtonEnable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setLayout(new BorderLayout());
JButton button = new JButton("Enable that button");
final MyPanel panel = new MyPanel();
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Some message. :)");
panel.changeStateOfButton(true); // call second class method here
}
});
frame.add(button, BorderLayout.NORTH);
frame.add(panel, BorderLayout.SOUTH);
frame.setVisible(true);
}
}
And second class containing jbutton:
class MyPanel extends JPanel {
private JButton button;
public MyPanel() {
button = new JButton("Enable me");
button.setEnabled(false); // disabled by default
this.add(button);
}
public void changeStateOfButton (boolean flag) {
button.setEnabled(flag);
}
}
check if you are not creating more then one object of FileSending class ....
you must not create more then one object of that class...
check if one object is created as part of your GUI class and another is as part of SMS class..
use only one object of FileSending class

Java: Using an actionlistener to call a function in another class on an object from that class

Basically what I want to do is get a start button to initiate a method running in another class and acting on another object.
My code for the listener:
button1a.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent event) {
// Figure out how to make this work
//sim.runCastleCrash();
}
} );
My code for the other class:
public static void main(String[] args) {
CastleCrash sim;
sim = new CastleCrash();
}
and
public void runCastleCrash() {
System.out.println("Castle Crash is beginning...");
//Other method parts here to be added
}
I get the feeling this can't be too hard, but I'm missing a piece.
One way to reference things in an anonymous class is using the final keyword:
public static void main(String[] args) {
final Object thingIWantToUse = "Hello";
JButton button = new JButton("Click");
button.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
System.out.println(thingIWantToUse);
}
});
JFrame frame = new JFrame();
frame.setLayout(new FlowLayout());
frame.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
Alternatively, you can access members (variables or methods) of an enclosing type:
public class ActionListenerDemo2 {
private final JFrame frame = new JFrame();
private Object thingIWantToUse = "Hello";
public ActionListenerDemo2() {
JButton button = new JButton("Click");
button.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
thingIWantToUse = "Goodbye";
System.out.println(thingIWantToUse);
}
});
frame.setLayout(new FlowLayout());
frame.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new ActionListenerDemo2().frame.setVisible(true);
}
}
I've had the same problem like you and this is how i solved it.
You can either make your object final (final CastleCrash sim = new CastleCrash();), but i didn't want to do that, or you can make something like a setter method to run the method in your other class:
My code for the listener class:
button1a.addActionListener(new ActionListener()
{
public void actionPerformed (ActionEvent event)
{
//How to make this work ?
//Like this:
runCC();
}
});
public void runCC()
{
CastleCrash sim = new CastleCrash();
sim.runCastleCrash();
}
My code for the other class:
public void runCastleCrash()
{
System.out.println("Castle Crash is beginning...");
//Other method parts here to be added
}
Hope this is helpful, good luck ! :)
McDowell already answers practically with good examples on how to access variables from event listeners (or anonymous inner classes in general). There is however a more general Sun resource on Event Listeners in Swing that is canonical and a good overview of all the caveats to take into account when writing them.
Somehow you need a reference to your CastleCrash object available to call from your actionListener.
You probably want to subclass JFrame, or whatever is containing your JButton such that it has your both your main method and a CastleCrash property that can then be referenced from your anonymous inner class Actionlistener.
BUT - be careful, you look like you are calling what will be a long running method from within the GUI event thread (where the action listener will called). This is generally a bad idea, you will case your GUI to become unresponsive.
See http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html especially the bit on SwingWorker class for ideas on how to avoid that problem.

Categories

Resources