Actionlistener java - java

For my class I need to use my ActionListener. I am having trouble adding my ActionListener to my buttons. I have to use the word "this" like this.buttons to add my ActionListener but Im having trouble doing that. I will get to my actionPerformed method later but my main problem is my ActionListener.
public class TextButtonsHW extends JFrame implements ActionListener {
private JButton[] buttons; //Do not change
private JTextArea textArea; //Do not change
//Assign values for these constants in the constructor
private final int ENTER; //Index of Enter button in buttons
private final int SPACE; //Index of Space button in buttons
private final int CLEAR; //Index of Clear button in buttons
/**
* Set up this frame and its contents.
* #param title Title to appear in JFrame title bar
*/
public TextButtonsHW(String title) {
super(title); //call parent JFrame constructor to set the title
buttons = new JButton[] { new JButton("A"), new JButton("B"), new JButton("C"),
new JButton("1"), new JButton("2"), new JButton("3"),
new JButton("X"), new JButton("Y"), new JButton("Z"),
new JButton("Enter"), new JButton("Space"), new JButton("Clear")};
ENTER = buttons.length-3;
SPACE = buttons.length-2;
CLEAR = buttons.length-1;
textArea = new JTextArea(15, 5);
textArea.setEditable(false);
this.buttons[0].addActionListener(I dont know what to put right here);
//TODO: instantiate all JButtons, add them to the buttons array,
// and register "this" as the ActionListener for each button.
//DONE
//TODO: assign values to ENTER, SPACE, and CLEAR constants to
// indicate the indexes of those buttons in the buttons array
//DONE
//TODO: create the JTextArea textArea
//TODO: set its "editable" property to false
//DONE
//Create a TextButtonsHWPanel to display the buttons and textArea
TextButtonsHWPanel mainPanel = new TextButtonsHWPanel(buttons, textArea);
this.getContentPane().add(mainPanel);
this.pack();
}
public void actionPerformed(ActionEvent e) {
//TODO: update the text of textArea according to which
// button generated the ActionEvent.
}
public static void main(String[] args) {
final TextButtonsHW f = new TextButtonsHW("Text Buttons");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null); //centers frame on screen
f.setVisible(true);
}
}

buttons[0].addActionListener(this);

Since you have 12 buttons you could also go for a for-loop to add ActionListener to all your buttons i.e.
for(int i=0; i<12; i++)
{
buttons[i].addActionListener(this);
}
Instead of a long code i.e.
buttons[0].addActionListener(this);
buttons[1].addActionListener(this);
........................

Though buttons[0].addActionListener(this); will work well, From design perspective I will suggest to have separate class (may be inner class) which implements ActionListner and pass its object reference to the method.
the whole point of Object Oriented programming is to delegate different responsibilities to different Objects(classes), so code becomes more maintainable and reusable.

Related

How to access variable from action listener/class constructor to use in main method in java

I have a frame with a combo box that displays different shapes and a button, for the button I added an action listener which will get the selected item from the combo box and store it as a string which i declared as a public class variable, in my main method i want to access this string to make a finch robot draw that shape but I can't seem to access it no matter what I try
public class DrawShape
{
private JFrame frame;
private String[] choices = {"circle", "square", "triangle", "rectangle", "quit"};
public String choice = "";
//class constructor
public DrawShape()
{
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
JPanel p = new JPanel();
final JComboBox cb = new JComboBox(choices);
JButton button = new JButton("Done");
p.add(cb);
p.add(button);
frame.add(p);
//create an action listener that, when button is clicked, gets the selected choice and stores it to
//the string variable 'choice'
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
choice = (String)cb.getSelectedItem();
}
}) ;
frame.pack();
}
public static void main(String[] args)
{
new DrawShape();
System.out.println(choice);
}
}
I wouldn't recommend the use of non-private variables. However, you need to keep a reference to the object you created and then access the fields through that reference as if you were calling methods on an object.
DrawShape draw = new DrawShape();
System.out.println(draw.choice);
However, you should see null as this is called immediately after you construct the object rather than from the listener.
You probably want the code executed from the listener. So either put the print code in the listener, or have the listener call another method with that in.
GUI programming tends to be event driven. Don't expect to be able to sequence the user interaction - the user drives.
you should use getters/setters in this case. Your action listener would call the getter method which would in turn get what is in the combobox.
Here is an example of how that works: https://www.codejava.net/coding/java-getter-and-setter-tutorial-from-basics-to-best-practices
Hope this helps.

int and boolean not changing after action performed

I copied all of the relevant code below, and my problem is that after running the action performed (which is connected to a button) the values I tried to change in the action performed didn't actually change.
I put a sout(ques) at the end of the action performed and I can see the change in value but when I move outside of it, it reverts back to the 0;
public class GameRunner extends JPanel implements ActionListener{
private int x=50,y=600;
private Ball b = new Ball(x,y);
private Timer timer;
private boolean correct , incorrect;
private JButton button;
private JTextField f;
private int ques = 0;
private String[][] math = {{"2X^2","4x"},{"q2","a2"},{"q3","a3"},{"q4","a4"},{"q5","a5"},
{"q6","a6"},{"q7","a7"},{"q8","a8"}};
public void actionPerformed(ActionEvent actionEvent) {
if (f.getText().equals(math[ques][1])) {
correct = true;
} else {
incorrect = true;
}
f.setText("");
if(ques<7)
ques++;
else
ques = 0;
System.out.println(ques);
//I can see the change here
}
public void paint(Graphics g){//called whenever refreshed...
System.out.println(ques);
// But now outside of the action performed the ques and the correct incorrect do not change
if(correct)
b.move();
if(incorrect)
b.move2();
}
public static void main(String[] args) {
GameRunner gui = new GameRunner ();
gui.go();
}
public void go(){
button = new JButton("Guess");
f = new JTextField(15);
button.addActionListener(this);
JFrame frame = new JFrame("Derivative Game");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(700, 700));
JPanel pan = new JPanel(new BorderLayout());
JPanel pan2 = new GameRunner();
JPanel pan3 = new JPanel();
pan3.add( f);
pan3.add(button);
pan3.setBackground(new Color(80, 218, 213));
pan.add( pan3,BorderLayout.CENTER);
pan.setBackground(new Color(80, 218, 213));
frame.add(pan2);
frame.getContentPane().add(BorderLayout.SOUTH, pan);
frame.setSize(700, 760);
frame.setVisible(true);
frame.setResizable(false);
}
}
The basic problem is that you've actually got two instances of GameRunner here: the one you create in main(), and another one that you add to the JFrame. Since you only call go() on the one not in the JFrame, that instance's paint() method will never be called.
You need to refactor your code to eliminate that second stray GameRunner instance. While you're at it, you should also use paintComponent() instead of paint(), and you should take any "business logic" (like those calls to move()) out of your painting code.
In other words, get rid of this line:
JPanel pan2 = new GameRunner();
Since you're already "in" an instance of GameRunner, you shouldn't be creating another one. Then to use the "current" instance of GameRunner, you can use the this keyword:
frame.add(this);
Edit- You also aren't telling your GameRunner JPanel to repaint itself after the button is clicked. You might want to add a call to repaint() in your actionPerformed() method.

JTextField.setText() does not work in method as an array

new Java programmer here so I might have a basic question here. I am making an array of JTextFields. I want to use setText outside of the class in a public method but it does not work. However, I am able to use setText in the class (not in a method). I am not sure why. Here is some code as a SSCCE to show what I am experiencing.
import java.awt.BorderLayout;
import javax.swing.*;
public class testSetText extends JFrame
{
private JPanel panel;
private JTextField[] arrayField;
private JTextField singleField;
public testSetText()
{
// Specify an action for close button
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Make a panel
panel = new JPanel();
// Make array of JTextField components
JTextField[] arrayField = new JTextField[2];
for (int i = 0; i < 2; i++)
{
arrayField[i] = new JTextField(10);
arrayField[i].setEditable(false);
arrayField[i].setText("<>!");
panel.add(arrayField[i]);
}
// Make just one JTextField component
singleField = new JTextField(10);
singleField.setText("Works here");
panel.add(singleField);
// Add to panel to frame
add(panel);
// Pack the contents of the window and display it
pack();
setVisible(true);
// This will work!
arrayField[0].setText("Array index in class");
// This won't? Why?
setInMethodWithArray();
// Is this a problem with JTextField itself? Let me try a single element
setInMethodWithSingleElement();
// Hmmm so an element in an array of JTextFields can be addressed with setText in a class but not
// in a method in same class with same statement. But a single JTextField can be used in a method
// by that same class. Why do arrays behave so differently?
// EDIT: So I misunderstood, it does not work with a non array as well either!!
}
public void setInMethodWithArray()
{
arrayField[1].setText("This text will never show up");
}
public void setInMethodWithSingleElement()
{
//singleField.setText("Works here as non-array"); <--- before edit
singleField.setText("nevermind, it does not work here either");
}
public static void main(String[] args)
{
new testSetText();
}
}
you should declare arrayField[] in class area so array Field is accessible from setInMethodWithArray() method.
JTextField[] arrayField = new JTextField[2]; //class area
in constructor initial it
arrayField[i]= new JTextField(10);
arrayField[i].setEditable(false);
yes this is work
arrayField[0].setText("Array index in class");
because arrayField in the constructor scope ..and you are accessing arrayField Within constructor .so it works..
This won't? Why?
setInMethodWithArray();
because method setInMethodWithArray() can't access arrayField[] because it's not in method scope or in class scope.that's because you have declare it in the constructor so after constructor code block execute arrayField doesn't exist .it's reference lost because it's local variable ..
public void setInMethodWithArray()
{
arrayField[1].setText("This text will never show up");
}
now set can access arratField[] so now your code will work
import java.awt.BorderLayout;
import javax.swing.*;
public class testSetText extends JFrame
{
private JPanel panel;
private JTextField singleField;
// Make array of JTextField components
private JTextField[] arrayField = new JTextField[2];
public testSetText()
{
// Specify an action for close button
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Make a panel
panel = new JPanel();
for (int i = 0; i < 2; i++)
{
arrayField[i] = new JTextField(10);
arrayField[i].setEditable(false);
arrayField[i].setText("<>!");
panel.add(arrayField[i]);
}
// Make just one JTextField component
singleField = new JTextField(10);
singleField.setText("Works here");
panel.add(singleField);
// Add to panel to frame
add(panel);
// Pack the contents of the window and display it
pack();
setVisible(true);
// This will work!
arrayField[0].setText("Array index in class");
// This won't? Why?
setInMethodWithArray();
// Is this a problem with JTextField itself? Let me try a single element
setInMethodWithArray();
// Hmmm so an element in an array of JTextFields can be addressed with setText in a class but not
// in a method in same class with same statement. But a single JTextField can be used in a method
// by that same class. Why do arrays behave so differently?
}
public void setInMethodWithArray()
{
arrayField[1].setText("This text will never show up");
}
public void setInMethodWithSingleElement()
{
singleField.setText("Works here as non-array");
}
public static void main(String[] args)
{
new testSetText();
}
}
output>>

Trouble with java GUI. I can't get JRadioButtons to display in JLabel

I am new to Java; but I'm having a blast. I feel like I'm missing something really simple; but I can't figure it out.
I want the RadioButtons to be displayed inside the JFrame."
public class HelloWorldFrame extends JFrame
{
private TitledBorder title;
public HelloWorldFrame()
{
super("Hello World! ");
JFrame helloWorld = new JFrame();
JLabel label = new JLabel();
title = BorderFactory.createTitledBorder("Language");
title.setTitleJustification(TitledBorder.LEFT);
label.setBorder(title);
add(label);
setSize(300, 200);
JRadioButton button1 = new JRadioButton("English");
JRadioButton button2 = new JRadioButton("French");
JRadioButton button3 = new JRadioButton("Spanish");
ButtonGroup bG = new ButtonGroup();
bG.add(button1);
bG.add(button2);
bG.add(button3);
label.add(button1);
label.add(button2);
label.add(button3);
helloWorld.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
//The main class starts here
public class HelloWorldApp
{
public static void main(String[] args)
{
JFrame helloWorld = new HelloWorldFrame();
helloWorld.setVisible(true);
}
}
The first question is why? Why do you want to add the radio buttons to a JLabel?
Having said that, you can set the labels layout manager to something other then it's default value of null...
label.setLayout(new FlowLayout());
label.add(button1);
label.add(button2);
label.add(button3);
Next...your class extends from JFrame, but in your constructor, you are creating another JFrame, this means that when you do...
JFrame helloWorld = new HelloWorldFrame();
helloWorld.setVisible(true);
Nothing will be displayed, because nothing has been added to the frame.
Instead, make your class extend from something like JFrame and then add that to your JFrame in main
Updated
I just did some testing and doing this (adding buttons to a label) won't work well, as the JLabel calculates it's preferred size based on the text and icon, not it's contents (like something like JPanel would)...just saying...

ActionListener on a JButton does not perform any action

I have a slight issue with my Actionlistener, when i click button nothing happens ?? I do not see where the problem is, so another pair of eyes could help me out :)
public class GameOptions extends JPanel implements ActionListener{
public GameOptions(){
System.out.println("GameOptions Class test blabla");
easyButton().addActionListener(this);
mediumButton().addActionListener(this);
hardButton().addActionListener(this);
JPanel center = new JPanel(new GridLayout(4,1,10,10));
center.add(new JLabel("Chose Difficulty Level"));
center.add(easyButton());
center.add(mediumButton());
center.add(hardButton());
this.add(center, BorderLayout.CENTER);
this.setPreferredSize(this.getPreferredSize());
this.setFocusable(true);
this.requestFocusInWindow();
}
private JButton easyButton(){
JButton levelEasy = new JButton("Easy");
return levelEasy;
}
private JButton mediumButton(){
JButton levelMedium = new JButton("Medium");
return levelMedium;
}
private JButton hardButton(){
JButton levelHard = new JButton("Hard");
return levelHard;
}
#Override
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if(src == easyButton()){
System.out.println("Easy");
}
else if(src == mediumButton()){
System.out.println("Medium");
}
else if(src == hardButton()){
System.out.println("Hard");
}
else{
}
}
}
Your xxxButton() methods create new JButtons each time, and so you add the ActionListener to a newly created JButton and then discard the button, and then add a completely different JButton, one without the ActionListener to the GUI.
Suggestion: create your JButtons, set a variable to them, add your ActionListener, and add the same button to the GUI.
So instead of this:
easyButton().addActionListener(this); // creates one JButton
center.add(easyButton()); // creates a completey different JButton
do this:
JButton easyButton = easyButton();
easyButton.addActionListener(this);
center.add(easyButton);
Note, if this were my code, I'm not sure that I'd use JButtons at all. Instead perhaps I'd use either JRadioButtons or a JComboBox.
You're creating each JButton with a function. And later you try to add it like center.add(easyButton()); but the one you added a ActionListener isn't the same button as this one. You're creating each one with new, so the reference isn't the same.
You should do it like this:
JButton buttonEasy = easyButton();
buttonEasy.addActionListener(this);
center.add(buttonEasy);

Categories