This question already has answers here:
Why are only final variables accessible in anonymous class?
(15 answers)
Closed 7 years ago.
I have a very simple GUI app. It only consists of a button and a label to display how many times that button has been clicked. I implemented it as follows:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Scratch {
public static void main(String[] args) {
JFrame frame = new JFrame("Click Counter");
frame.setSize(400,250);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JButton button = new JButton("Click Here");
final int count = 0;
final JLabel label = new JLabel("Click Count: 0");
panel.add(button);
panel.add(label);
frame.add(panel):
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
count++; // Error
String s = label.getText();
label.setText("Click Count: " + count);
}
});
frame.setVisible(true);
}
}
The problem is with the count variable. If I don't declare it as final, I cannot access it inside the anonymous class. If I do however, I cannot modify it. So what do I do? I really prefer creating actionlistener classes as anonymous classes as opposed to creating multiple classes in a single .java file.
declare variable outside function as a class variable
private static int count = 0;
public static void main(String[] args) {
JFrame frame = new JFrame("Click Counter");
frame.setSize(400,250);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JButton button = new JButton("Click Here");
final JLabel label = new JLabel("Click Count: 0");
panel.add(button);
panel.add(label);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
count++;
String s = label.getText();
s = s.substring(0, s.length()-1);
label.setText(s + count);
}
});
frame.setVisible(true);
}
Related
This question already has answers here:
Java anonymous class that implements ActionListener?
(6 answers)
Closed 6 years ago.
how do i access the variable 'button' from the actionlistner method?
i am trying to get the program to print 'button clicked' (System.out.println("")) to the console whenever the button is clicked. how do i do that?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Game implements ActionListener
{
public static void main(String[] args)
{
new Game().buildframe();
}
public void buildframe()
{
//making the frame
JFrame frame = new JFrame("Game");
GridLayout table = new GridLayout(5,1);
frame.setLayout(table);
//creating the labels and textfields
JLabel usernameLabel = new JLabel("Username;");
JTextField username = new JTextField("");
JLabel passwordLabel = new JLabel("Password:");
JTextField password = new JTextField("");
//create the button and action listener
JButton button = new JButton();
button.setText("Login");
button.addActionListener(this);
//adding the components
frame.add(usernameLabel);
frame.add(username);
frame.add(passwordLabel);
frame.add(password);
frame.add(button);
//sdets the size of the Jframe
frame.setSize(300, 150);
//puts the JFrame in the midle of the screen
frame.setLocationRelativeTo(null);
//setws the default operation when the user tries to close the jframe
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent evt)
{
if(evt.getSource() == button)
{
}
}
}
Make button a class variable (so called field) instead of a local variable in the buildframe() method.
Here's a little example for you:
class MyClass {
Object myField;
void aMethod() {
myField = new Object();
}
void anotherMethod() {
myField.aMethod();
}
}
I am trying to make my program so that an integer value entered in a JTextfield can be stored into a variable. Then, when a JButton is clicked, this variable can tell a JSlider to move it's head to that of the integer value stored in the variable. My class name is Camera.Java
Code is showing no errors, however if I click my JButton, nothing happens, instead I see this error in the console:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:504)
at java.lang.Integer.parseInt(Integer.java:527)
at Camera.main(Camera.java:67)
My code:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Hashtable;
import java.util.Scanner;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JPanel;
import javax.swing.*;
public class Camera {
static JButton addtolist;
static Scanner input = new Scanner(System.in);
static JSlider cam = new JSlider();
static JTextField enterval = new JTextField();
static int x ;
public static void main (String args[]){
JFrame myFrame = new JFrame ("Matthew Damon on Mars");
myFrame.setSize(300, 600);
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JLabel userinp = new JLabel("Enter input: ");
cam = new JSlider(0, 15, 0);
cam.setPaintLabels(true);
enterval.setPreferredSize(new Dimension(100,80));
addtolist = new JButton("Enter");
addtolist.setPreferredSize(new Dimension(50,20));
JTextField enterval1 = new JTextField();
panel.add(addtolist);
Hashtable<Integer, JLabel> table = new Hashtable<Integer, JLabel>();
table.put(0, new JLabel("0"));
table.put(1, new JLabel("1"));
table.put(2, new JLabel("2"));
table.put(3, new JLabel("3"));
table.put(4, new JLabel("4"));
table.put(5, new JLabel("5"));
table.put(6, new JLabel("6"));
table.put(7, new JLabel("7"));
table.put(8, new JLabel("8"));
table.put(9, new JLabel("9"));
table.put(10, new JLabel("A"));
table.put(11, new JLabel("B"));
table.put(12, new JLabel("C"));
table.put(13, new JLabel("D"));
table.put(14, new JLabel("E"));
table.put(15, new JLabel("F"));
cam.setLabelTable(table);
myFrame.add(cam, BorderLayout.SOUTH);
myFrame.add(userinp, BorderLayout.NORTH);
myFrame.add(enterval1, BorderLayout.NORTH);
myFrame.add(panel, BorderLayout.CENTER);
myFrame.setVisible(true);
buttonAction();
}
public static void buttonAction() {
addtolist.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
int x = Integer.parseInt(enterval.getText());
cam.setValue(x);
} catch (NumberFormatException npe) {
// show a warning message
}
}
});
}
}
Your setting x on program creation before the user has had any chance to change its value. Get the text value from within the actionPerformed method which should be after the user has already selected a value, parse it into a number and set the slider with that value.
public void actionPerformed(ActionEvent e) {
try {
int x = Integer.parseInt(enterval.getText());
cam.setValue(x);
} catch (NumberFormatException npe) {
// show a warning message
}
}
Then get rid of all that static nonsense. The only method that should be static here is main, and it should do nothing but create an instance and set it visible.
Note that better than using a JTextField, use a JSpinner or a JFormattedTextField or if you're really stuck, a DocumentFilter to limit what the user can enter
Again, you should put most everything into the instance realm and out of the static realm. This means getting most of that code outside of the main method and into other methods and constructors, that means not trying to access fields or methods from the class, but rather from the instance. For instance, your main method should only create the main instances, hook them up and set them running and that's it. It should not be used to build the specific GUI components. For example:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class CameraFoo extends JPanel {
// only static field here is a constant.
private static String TEXTS = "0123456789ABCDEF";
private JSpinner spinner = new JSpinner();
private JSlider slider = new JSlider(0, 15, 0);
public CameraFoo() {
List<Character> charList = new ArrayList<>();
Hashtable<Integer, JLabel> table = new Hashtable<>();
for (int i = 0; i < TEXTS.toCharArray().length; i++) {
char c = TEXTS.charAt(i);
String myText = String.valueOf(c);
JLabel label = new JLabel(myText);
table.put(i, label);
charList.add(c);
}
SpinnerListModel spinnerModel = new SpinnerListModel(charList);
spinner.setModel(spinnerModel);
slider.setLabelTable(table);
slider.setPaintLabels(true);
JPanel topPanel = new JPanel();
topPanel.add(spinner);
topPanel.add(new JButton(new ButtonAction("Press Me")));
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(slider);
}
private class ButtonAction extends AbstractAction {
public ButtonAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
char ch = (char) spinner.getValue();
int value = TEXTS.indexOf(ch);
slider.setValue(value);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
private static void createAndShowGui() {
CameraFoo mainPanel = new CameraFoo();
JFrame frame = new JFrame("CameraFoo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
I'm starting my adventure with programming and I've got one problem. I try make a simple calculator using awt. I can't go further because I don't know, how to change one variable - textField initialized in MainFrame. I want to change it in actionPerformed. Here's my code and I'll be grateful if You'll give me some guidance. Thanks!
package starter;
import java.awt.EventQueue;
public class Starter {
public Starter () {
EventQueue.invokeLater(new Runnable (){
#Override
public void run () {
new MainFrame();
System.out.println();
}
});
}
public static void main(String[] args) {
new Starter();
}
}
MainFrame
package starter;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class MainFrame extends JFrame {
private JTextField textField = new JTextField();
DigitActionListener digitPressed = new DigitActionListener();
public MainFrame() {
super("Calculator");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setResizable(true);
setSize(350, 400);
setLayout (new GridLayout (6, 4, 3, 3));
JButton buttonClear = new JButton("Clear"); buttonClear.addActionListener(digitPressed);
JButton button0 = new JButton ("0"); button0.addActionListener(digitPressed);
JButton button1 = new JButton ("1"); button1.addActionListener(digitPressed);
JButton button2 = new JButton ("2"); button2.addActionListener(digitPressed);
JButton button3 = new JButton ("3"); button3.addActionListener(digitPressed);
JButton button4 = new JButton ("4"); button4.addActionListener(digitPressed);
JButton button5 = new JButton ("5"); button5.addActionListener(digitPressed);
JButton button6 = new JButton ("6"); button6.addActionListener(digitPressed);
JButton button7 = new JButton ("7"); button7.addActionListener(digitPressed);
JButton button8 = new JButton ("8"); button8.addActionListener(digitPressed);
JButton button9 = new JButton ("9"); button9.addActionListener(digitPressed);
JButton multiplicationButton = new JButton ("*"); multiplicationButton.addActionListener(digitPressed);
JButton divisionButton = new JButton ("/"); divisionButton.addActionListener(digitPressed);
JButton additionButton = new JButton ("+"); additionButton.addActionListener(digitPressed);
JButton substructionButton = new JButton ("-"); substructionButton.addActionListener(digitPressed);
JButton equalsButton = new JButton ("="); equalsButton.addActionListener(digitPressed);
JButton commaButton = new JButton ("."); commaButton.addActionListener(digitPressed);
add (buttonClear);
add (new JLabel (""));
add (new JLabel (""));
JPanel textPanel = new JPanel();
textPanel.setLayout(new BorderLayout());
textPanel.add(textField, BorderLayout.CENTER);
this.add(textPanel);
add(button7);
add(button8);
add(button9);
add(divisionButton);
add(button4);
add(button5);
add(button6);
add(multiplicationButton);
add(button1);
add(button2);
add(button3);
add(additionButton);
add(commaButton);
add(button0);
add(equalsButton);
add(substructionButton);
}
public JTextField getTextField() {
return textField;
}
public void setTextField(String text) {
textField.setText(text);
}
}
DigitActionListener
package starter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.JTextField;
class DigitActionListener implements ActionListener {
int size = 0;
char[] tab = new char[size];
public void pain (Graphics g, String s){
g.drawString(s, 20, 10);
}
#Override
public void actionPerformed(ActionEvent e) {
//Object source = e.getSource();
String command = e.getActionCommand();
if ("button0".equals(command)) {
tab[size] = 0;
String eq = String.valueOf(tab[size]);
MainFrame mainFrame = new MainFrame();
mainFrame.setTextField(eq);
size++;
}
}
}
Your problem is here:
if ("button0".equals(command)) {
tab[size] = 0;
String eq = String.valueOf(tab[size]);
MainFrame mainFrame = new MainFrame();
mainFrame.setTextField(eq);
size++;
}
You're creating a new MainFrame object and changing its state, but understand that this will have no effect on the completely distinct displayed MainFrame object and will not change its state whatsoever (will not change what is displayed within its JTextField). There are a variety of possible solutions, but it all boils down to understanding what Java references are, and calling methods on the appropriate reference, here the appropriate MainFrame object. A simple solution could be for to pass the MainFrame object into your listener via a listener constructor, and then call the methods on this reference.
For example:
class DigitActionListener implements ActionListener {
private MainFrame mainFrame;
int size = 0;
char[] tab = new char[size];
public DigitActionListener(MainFrame mainFrame) {
this.mainFrame = mainFrame;
}
public void pain (Graphics g, String s){
g.drawString(s, 20, 10);
}
#Override
public void actionPerformed(ActionEvent e) {
//Object source = e.getSource();
String command = e.getActionCommand();
if ("button0".equals(command)) {
tab[size] = 0;
String eq = String.valueOf(tab[size]);
// MainFrame mainFrame = new MainFrame(); // **** no, don't do this
mainFrame.setTextField(eq);
size++;
}
}
}
and then within MainFrame itself, do something like:
// pass *this* or the current MainFrame instance, into the DigitalActionListener
DigitActionListener digitPressed = new DigitActionListener(this);
Other issues -- learn to use and then use arrays and ArrayLists, as this can help you simplify your code, and thus make program improvement and debugging much easier.
my first post after long time lurking.
I'm trying to write a java program to train my calculation skills as Khan academy removed the never-ending mode on sum, subtraction, etc.
I somehow managed to write the skeleton but I got stuck when I had to implement listeners: if I create a class that implements ActionListener everything works. But when I try to use a sublass that implements ActionListener the code breaks. I'd like to figure out why.
I have 3 classes.
Question: generates 2 random int
public class Question {
public int rand1;
public int rand2;
public Question (){
rand1 = (int) (100 +(Math.random()*900)); // to be sure I have at least 3 digits. See AnswerV2.generate()
rand2 = (int) (100 + (Math.random()*900));
}
}
Answersv2: takes the 2 random int
from Question, sums them, create 3 different answers switching
digits, adds the right answer and shuffles them.
import java.util.ArrayList;
import javax.swing.JButton;
import java.util.Collections;
public class Answersv2 {
public ArrayList Answer_list = new ArrayList();
public int int1;
public int int2;
String uno;
public Answersv2 (int a, int b) {
int1 = a;
int2 = b;
}
public void generate (){
StringBuilder due = new StringBuilder();
StringBuilder tre = new StringBuilder();
StringBuilder quattro = new StringBuilder();
uno = Integer.toString(int1+int2); // create the string version of int1+int2
ArrayList <Character> first_answer = new ArrayList<Character>(); // create an arraylist of char to store the chars
for (char c : uno.toCharArray()) {
first_answer.add(c);
}
Collections.swap(first_answer,first_answer.size()-2,first_answer.size()-1); // switch tens with units
for (char c : first_answer) {
due.append(c);
}
String dueString = due.toString();
Collections.swap(first_answer,first_answer.size()-3,first_answer.size()-2); // switchs hundres with tens
for (char c : first_answer) {
tre.append(c);
}
String treString = tre.toString();
Collections.swap(first_answer,first_answer.size()-2,first_answer.size()-1); // switch tens with units
for (char c : first_answer) {
quattro.append(c);
}
String quattroString = quattro.toString();
add(uno,dueString,treString,quattroString);
}
public void add (String one,String two,String three,String four){
Answer_list.add(one);
Answer_list.add(two);
Answer_list.add(three);
Answer_list.add(four);
shuffle();
}
public void shuffle() {
Collections.shuffle(Answer_list);
}
public void stampa (){ // command code line version to test the program, ignore this
System.out.println("--------------------------------");
System.out.println(int1 + " + " + int2 + " = : ");
System.out.println("A " + Answer_list.get(0));
System.out.println("B " + Answer_list.get(1));
System.out.println("C " + Answer_list.get(2));
System.out.println("D " + Answer_list.get(3));
}
public class CoolButton extends JButton{
public CoolButton(String answer) {
setText(answer);
}
public boolean checkme() { // method to check if the button pressed was the one with the right answer. I still haven't implemented this properly, ignore this too
if (getText() == uno) {
return true;
} else {
return false;
}
}
}
}
3 QuizV2: Creates the GUI and starts the program.
Now... I created a StartListener subclass of QuizV2 in order to make the buttons being able to read the 4 answers from the answer object created in the QuizV2's main and use it to
setText() and to change label text, etc.
Here is the code (Quizv2) with the subclass:
import java.util.ArrayList;
import java.util.Collections;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class Quizv2{
public MyLabel label = new MyLabel("Click Start");
JButton button = new JButton("Start");
Answersv2 pinolo;
Question domanda;
Answersv2.CoolButton button1;
Answersv2.CoolButton button2;
Answersv2.CoolButton button3;
Answersv2.CoolButton button4;
public static void main (String [] args) {
Quizv2 quiz = new Quizv2();
quiz.go();
}
public void go () {
Question domanda = new Question();
Answersv2 pinolo = new Answersv2(domanda.rand1,domanda.rand2);
pinolo.generate();
button1 = pinolo.new CoolButton(pinolo.Answer_list.get(0));
button1.setAlignmentX(Component.CENTER_ALIGNMENT);
button2 = pinolo.new CoolButton(pinolo.Answer_list.get(1));
button2.setAlignmentX(Component.CENTER_ALIGNMENT);
button3 = pinolo.new CoolButton(pinolo.Answer_list.get(2));
button3.setAlignmentX(Component.CENTER_ALIGNMENT);
button4 = pinolo.new CoolButton(pinolo.Answer_list.get(3));
button4.setAlignmentX(Component.CENTER_ALIGNMENT);
JFrame frame = new JFrame("SPI trainer - Sum");
JPanel panel = new JPanel();
label.setAlignmentX(Component.CENTER_ALIGNMENT);
int R = (int) (Math.random( )*256);
int G = (int)(Math.random( )*256);
int B= (int)(Math.random( )*256);
Color randomColor = new Color(R, G, B);
label.setForeground(randomColor);
panel.add(label);
button.setAlignmentX(Component.CENTER_ALIGNMENT);
panel.add(button);
ActionListener doGreeting = new StartListener();
button.addActionListener(doGreeting );
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(BorderLayout.CENTER,panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(BorderLayout.CENTER,panel);
frame.setSize(300,300);
frame.setVisible(true);
frame.setLocationRelativeTo( null );
}
}
class StartListener extends Quizv2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("boo");
label.setLabelText("The button text changed.");
}
}
However it seems I'm doing something wrong as it prints 'boo' but it doesn't change the label text. I'd like to avoid to use
class StartListener extends Quizv2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (buttony == e.getSource()) {
label.setLabelText( domanda.rand1 + " + " + domanda.rand2 + " = : ????");
button1.setVisible(true);
button2.setVisible(true);
button3.setVisible(true);
button4.setVisible(true);
button.setVisible(false);
.....
.....
else if (buttonx == e.getSource())
....
}
}
in order to figure out which button was pressed so that the programs knows which block of code execute.
I then tried not to use a subclass and everything worked out. Here is the code (Quizv2)
import java.util.ArrayList;
import java.util.Collections;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class Quizv2 implements ActionListener{
public MyLabel label = new MyLabel("Click Start");
JButton button = new JButton("Start");
Answersv2 pinolo;
Question domanda;
Answersv2.CoolButton button1;
Answersv2.CoolButton button2;
Answersv2.CoolButton button3;
Answersv2.CoolButton button4;
public static void main (String [] args) {
Quizv2 quiz = new Quizv2();
quiz.go();
}
public void go () {
domanda = new Question();
pinolo = new Answersv2(domanda.rand1,domanda.rand2);
pinolo.generate();
button1 = pinolo.new CoolButton(pinolo.Answer_list.get(0));
button1.setAlignmentX(Component.CENTER_ALIGNMENT);
button2 = pinolo.new CoolButton(pinolo.Answer_list.get(1));
button2.setAlignmentX(Component.CENTER_ALIGNMENT);
button3 = pinolo.new CoolButton(pinolo.Answer_list.get(2));
button3.setAlignmentX(Component.CENTER_ALIGNMENT);
button4 = pinolo.new CoolButton(pinolo.Answer_list.get(3));
button4.setAlignmentX(Component.CENTER_ALIGNMENT);
JFrame frame = new JFrame("SPI trainer - Sum");
JPanel panel = new JPanel();
label.setAlignmentX(Component.CENTER_ALIGNMENT);
int R = (int) (Math.random( )*256);
int G = (int)(Math.random( )*256);
int B= (int)(Math.random( )*256);
Color randomColor = new Color(R, G, B);
label.setForeground(randomColor); // Little bit of color
panel.add(label);
button.setAlignmentX(Component.CENTER_ALIGNMENT);
panel.add(button);
button.addActionListener(this);
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
panel.add(button1);
button1.setVisible(false);
panel.add(button2);
button2.setVisible(false);
panel.add(button3);
button3.setVisible(false);
panel.add(button4);
button4.setVisible(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(BorderLayout.CENTER,panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(BorderLayout.CENTER,panel);
frame.setSize(300,300);
frame.setVisible(true);
frame.setLocationRelativeTo( null );
}
public void actionPerformed(ActionEvent e) {
label.setLabelText( domanda.rand1 + " + " + domanda.rand2 + " = : ????");
button1.setVisible(true);
button2.setVisible(true);
button3.setVisible(true);
button4.setVisible(true);
button.setVisible(false);
}
}
1) I suggest you put this program aside for quite awhile. You are making a lot of basic errors, so I don't see how you got anything to compile. And your code is a labyrinth which is a sign that the program is way too complex for your abilities at this time.
2) Your post also shows that you need to improve your debugging skills. You really shouldn't post more than about 20 lines of code when asking a question. Reducing a problem to around 20 lines of code is an exercise that improves your debugging skills. 90% of the code you posted is irrelevant to your problem. For instance, your whole Answerv2 class could have been reduced to this:
public class Answersv2 {
public ArrayList<String> Answer_list = new ArrayList<String>();
public Answersv2 () {
Answer_list.add("300", "150", "160", "170");
}
}
Do you really think that the way your code calculated those strings is relevant to why clicking on a button fails to change the text of a label? In fact, your whole Answerv2 class is irrelevant.
The number of lines of code your program can contain is proportional to your debugging skills. You cannot write a 500 line program two days after learning java. And writing Swing programs adds a lot of moving parts, so you need to have a solid grasp of the basics before attempting Swing--like not trying to access a non-static variable inside a static method.
When you are having trouble with some code, like your inheritance problem, start a new program to experiment. Make the new program as simple as possible:
1) Write a basic Swing program that sets up the relevant swing components...
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MyGui {
protected JLabel label = new JLabel("Hello");
protected JButton button = new JButton("Click me");
public MyGui() {
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(300, 100, 500, 300);
JPanel panel = new JPanel();
panel.add(label);
panel.add(button);
Container cpane = frame.getContentPane();
cpane.add(panel);
frame.setVisible(true);
}
}
public class SwingProg {
private static void createAndShowGUI() {
new MyGui();
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
} }
2) Get an actionPerformed() method in the same class to work:
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MyGui implements ActionListener { //********
protected JLabel label = new JLabel("Hello");
protected JButton button = new JButton("Click me");
public MyGui() {
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(300, 100, 500, 300);
JPanel panel = new JPanel();
panel.add(label);
button.addActionListener(this); //**********
panel.add(button);
Container cpane = frame.getContentPane();
cpane.add(panel);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) { //**************
System.out.println("boo");
label.setText("The button was clicked!");
}
}
public class SwingProg {
private static void createAndShowGUI() {
new MyGui();
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
3) Now try inherit from MyGui and put the actionPerformed method in the child class. Okay, so you can't figure out how to make it work. Now at least you have a simple example to post.
The problem with your button is: you never specified that the actionPerformed() method in the subclass should be the listener for the button. Here is a solution to your problem:
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MyGui {
protected JLabel label = new JLabel("Hello");
protected JButton button = new JButton("Click me");
public MyGui() {
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(300, 100, 500, 300);
JPanel panel = new JPanel();
panel.add(label);
panel.add(button);
Container cpane = frame.getContentPane();
cpane.add(panel);
frame.setVisible(true);
}
}
class StartListener extends MyGui implements ActionListener {
public StartListener(){
super();
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
System.out.println("boo");
label.setText("The button text changed.");
}
}
public class SwingProg {
private static void createAndShowGUI() {
new StartListener();
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Don't try to solve problems in the middle of a complex program. Instead, extrapolate the problem out into a new program, and solve the problem in the new program.
When I compile it show error in line 33 : Cannot find symbol.
I am calling jbtNew.addActionListener(listener), so why it's unable to find jbtNew in
(e.getSource() == jbtNew) in line 33.
from code
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class AnonymousListenerDemo extends JFrame {
public AnonymousListenerDemo() {
// Create four buttons
JButton jbtNew = new JButton("New");
JButton jbtOpen = new JButton("Open");
JButton jbtSave = new JButton("Save");
JButton jbtPrint = new JButton("Print");
// Create a panel to hold buttons
JPanel panel = new JPanel();
panel.add(jbtNew);
panel.add(jbtOpen);
panel.add(jbtSave);
panel.add(jbtPrint);
add(panel);
// Create and register anonymous inner-class listener
AnonymousListenerDemo.ButtonListener listener = new AnonymousListenerDemo.ButtonListener();
jbtNew.addActionListener(listener);
}
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jbtNew) //Here it show the problem
{
System.out.println("Process New");
}
}
}
/** Main method */
public static void main(String[] args) {
JFrame frame = new AnonymousListenerDemo();
frame.setTitle("AnonymousListenerDemo");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
That's a local variable.
It doesn't exist outside the constructor.
You need to make a field in the class.
this could be work (in the form as you posted here) and #SLaks mentioned +1, with a few major changes
in the case that all methods will be placed into separated classes to use put/getClientProperty()
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class AnonymousListenerDemo {
private static final long serialVersionUID = 1L;
private JFrame frame = new JFrame("AnonymousListenerDemo");
// Create four buttons
private JButton jbtNew = new JButton("New");
private JButton jbtOpen = new JButton("Open");
private JButton jbtSave = new JButton("Save");
private JButton jbtPrint = new JButton("Print");
public AnonymousListenerDemo() {
JPanel panel = new JPanel();// Create a panel to hold buttons
panel.add(jbtNew);
panel.add(jbtOpen);
panel.add(jbtSave);
panel.add(jbtPrint);
// Create and register anonymous inner-class listener
jbtNew.addActionListener(new ButtonListener());
frame.add(panel);
//frame.setTitle("AnonymousListenerDemo");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jbtNew) {
System.out.println("Process New");
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new AnonymousListenerDemo();
}
});
}
}