I've been trying to get two buttons to work.
However it seems that actionPerformed cannot see my buttons.
Things I've tried:
- checking my import statements, they seem to be correct
- checking for missing parentheses
- checked if I put the actionPerformed in the constructor by accident
- checked acces modifiers
- checked variable names
So far I'm lost at why it can't solve the symbols for button1 and button2.
Please help?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionListener;
public class Wisselscherm
extends JFrame
implements ActionListener {
public Wisselscherm(Wisselkoers wisselkoers){
String munt1 = String.valueOf(wisselkoers.getMunt1().getNaam() );
String munt2 = String.valueOf(wisselkoers.getMunt2().getNaam() );
setTitle(munt1 + " - " + munt2 + " Converter" );
setSize(500,500);
setLayout(new FlowLayout());
String teken1 = String.valueOf(wisselkoers.getMunt1().getTeken() );
JLabel munteenheid1 = new JLabel(teken1);
add(munteenheid1);
JTextField textf1 = new JTextField(10);
add(textf1);
JButton button1 = new JButton(">>");
add(button1);
button1.addActionListener(this);
JButton button2 = new JButton("<<");
button2.addActionListener(this);
add(button2);
String teken2 = String.valueOf(wisselkoers.getMunt2().getTeken() );
JLabel munteenheid2 = new JLabel(teken2);
add(munteenheid2);
JTextField textf2 = new JTextField(10);
add(textf2);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button1) {
System.out.println("Button1 is pressed");
} else if (e.getSource() == button2) {
System.out.println("Button2 is pressed");
}
}
}
Your buttons are defined as local variables to the Wisselscherm's constructor, so they will not be accessible outside of it's context
You could...
Make them instance variables, which would allow them to be accessible from within the whole class
You could...
Use anonymous listeners, which would allow you to associate a individual listener with each button, meaning that you can gurentee what triggered the ActionListener
You could...
Make use of the actionCommand property of the JButton and ActionEvent to decouple the listener from the source of the event, allowing you to re-use the ActionListener with other buttons/actions which generate the same actionCommand.
By default, the actionCommand will be the text of the button if it's not otherwise set directly
You could...
Use the Action API
All in or, you should probably have a closer look at How to Write an Action Listeners, How to Use Actions and How to Use Buttons, Check Boxes, and Radio Buttons for more details
This is a scope problem, just move button1 and button2 to the Class's scope level:
public class Wisselscherm extends JFrame implements ActionListener {
JButton button1;
JButton button2;
...
Then you can have:
button1 = new JButton(">>");
(Note that I removed JButton word in that line)
Related
I was tasked with creating a program that displays a numeric keypad (like one on a phone) and has a screen that displays the numbers that are picked. Also included is a clear button that clears the screen.
In creating my program, I created three classes. The Phone class simply creates a JFrame that adds a PhonePanel to the screen. The PhonePanel class adds a JLabel which acts as a screen, a JButton which acts as a clear button, and a KeypadPanel which is a GridLayout of JButtons which acts as the numeric keys.
The clear button and numeric buttons both use separate action listeners. Is this the most efficient way of going about this? Is there a way I can use one action listener instead of two?
// ******************************************************************************************
// Phone.java
// David Read
// This class creates a JFrame that contains a PhonePanel. The PhonePanel provides a
// user interface that allows one to input numeric symbols on a screen and allows clearing
// of the screen.
// ******************************************************************************************
package lab5;
import javax.swing.JFrame;
public class Phone {
public static void main(String[] args)
{
// Create a JFrame object.
JFrame frame = new JFrame ("Phone");
// Set the default close operation for the JFrame.
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
// Add a Phone panel to the screen.
frame.getContentPane().add(new PhonePanel());
frame.pack();
frame.setVisible(true);
}
}
// ******************************************************************************************
// PhonePanel.java
// David Read
// This class creates a JPanel that includes an output label which displays inputed numeric
// symbols, a clear button that clears what is displayed on the output label, and a KeypadPanel
// which displays a GridLayout of buttons that when pressed, display their corresponding symbols
// on the output label.
// ******************************************************************************************
package lab5;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class PhonePanel extends JPanel
{
private static JLabel labelOutput;
private JButton buttonClear;
//-----------------------------------------------------------------------
// Creates a JPanel that arranges three objects in a Border layout. The
// north component contains a JLabel, the east component contains a JButton
// and the center component contains a KeypadPanel.
//-----------------------------------------------------------------------
public PhonePanel()
{
// Set the layout manager, size and background color of the Phone Panel.
setLayout(new BorderLayout());
setPreferredSize (new Dimension(400, 200));
setBackground (Color.yellow);
// Output label created.
labelOutput = new JLabel(" ");
// Clear button created, assigned a button title and assigned an action listener.
buttonClear = new JButton();
buttonClear.setText("Clear");
buttonClear.addActionListener(new ClearButtonListener());
// Add the JLabel, JButton and KeypadPanel to the PhonePanel.
add(labelOutput, BorderLayout.NORTH);
add(buttonClear, BorderLayout.EAST);
add(new KeypadPanel(), BorderLayout.CENTER);
}
//-----------------------------------------------------------------------
// Adds the specified symbol to the output label.
//-----------------------------------------------------------------------
public static void addToOutputLabel(String input)
{
// Create a String object to hold the current value of the output label.
String label = labelOutput.getText();
// Append the inputed String onto the String.
label += input;
// Update the output label with the appended String.
labelOutput.setText(label);
}
//-----------------------------------------------------------------------
// Listens for the clear button to be pressed. When pressed, the output
// label is reassigned as blank.
//-----------------------------------------------------------------------
private class ClearButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
labelOutput.setText(" ");
}
}
}
// ******************************************************************************************
// KeypadPanel.java
// David Read
// This class creates a JPanel that contains several buttons which when pressed, adds their
// corresponding numeric symbol to the output label in the PhonePanel.
// ******************************************************************************************
package lab5;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class KeypadPanel extends JPanel
{
private JButton button1, button2, button3, button4, button5, button6, button7, button8, button9, buttonStar, button0, buttonNumber;
//-----------------------------------------------------------------------
// Creates a JPanel that arranges several JButtons in a GridLayout. Each
// of the buttons are assigned button titles, action listeners and
// action commands.
//-----------------------------------------------------------------------
public KeypadPanel()
{
// Set layout to a GridLayout with 4 rows and 3 columns.
setLayout(new GridLayout(4,3));
// Create new JButtons.
button1 = new JButton();
button2 = new JButton();
button3 = new JButton();
button4 = new JButton();
button5 = new JButton();
button6 = new JButton();
button7 = new JButton();
button8 = new JButton();
button9 = new JButton();
buttonStar = new JButton();
button0 = new JButton();
buttonNumber = new JButton();
// Assign button titles to the JButtons.
button1.setText("1");
button2.setText("2");
button3.setText("3");
button4.setText("4");
button5.setText("5");
button6.setText("6");
button7.setText("7");
button8.setText("8");
button9.setText("9");
buttonStar.setText("*");
button0.setText("0");
buttonNumber.setText("#");
// Create a new KeypadButtonListener.
KeypadButtonListener listener = new KeypadButtonListener();
// Assign the listener as an action listener for all of the JButton objects.
button1.addActionListener(listener);
button2.addActionListener(listener);
button3.addActionListener(listener);
button4.addActionListener(listener);
button5.addActionListener(listener);
button6.addActionListener(listener);
button7.addActionListener(listener);
button8.addActionListener(listener);
button9.addActionListener(listener);
buttonStar.addActionListener(listener);
button0.addActionListener(listener);
buttonNumber.addActionListener(listener);
// Set the action commands for all of the JButtons.
button1.setActionCommand("1");
button2.setActionCommand("2");
button3.setActionCommand("3");
button4.setActionCommand("4");
button5.setActionCommand("5");
button6.setActionCommand("6");
button7.setActionCommand("7");
button8.setActionCommand("8");
button9.setActionCommand("9");
buttonStar.setActionCommand("*");
button0.setActionCommand("0");
buttonNumber.setActionCommand("#");
// Add the JButtons to the KeypadPanel.
add(button1);
add(button2);
add(button3);
add(button4);
add(button5);
add(button6);
add(button7);
add(button8);
add(button9);
add(buttonStar);
add(button0);
add(buttonNumber);
}
//-----------------------------------------------------------------------
// Listens for all of the buttons to be pressed. When a particular button
// is pressed, the addToOutputLabel method of the PhonePanel is called
// with the input being the action command of the button pressed.
//-----------------------------------------------------------------------
private class KeypadButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
// Add the action command string to the output label.
PhonePanel.addToOutputLabel(e.getActionCommand());
}
}
}
In this case it is better to use two separate action listeners as functionality for clear button and for number buttons is different.
It is considered as best practice to use single responsibility principle (https://en.wikipedia.org/wiki/Single_responsibility_principle) when developing your classes. This will make your code more maintainable and easier to read and modify.
It is better to use multiple ActionListeners here, however, if you still desire to use one ActionListener instead you may make a separate class to handle all actions similar to this.
public class KeyListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
//Get the name of the ActionEvent
String cmd = e.getActionCommand();
//Here the Actionevent is only checked to see if it is a "Clear" or not
//If you need to impliment more then a switch statment may be appropriate
if(cmd.equals("Clear")) {
//Clear Label with additional setter method
PhonePanel.clearLabel();
}
else {
PhonePanel.addToOutputLabel(e.getActionCommand());
}
}
So for my program i have three buttons;
Button1: 8
Button2: 5
Button3: 3
public void actionPerformed(ActionEvent e) {
JButton b1= (JButton) e.getSource();
JButton b2= (JButton) e.getSource();
String button= b1.getText();
String button2 = b2.getText();
System.out.println("b1: " + button);
System.out.println("b2: " + button2);
I'm trying to check which buttons are pressed and storing them into the variable. So when the user presses 8, button should be 8, and once they press any second button, button2 should get that button
Do i make a new ActionEvent?
Currently both your buttons refer to the same source (I.e the same button)
If the actions to be triggered are similar in nature (for example, the buttons in MineSweeper, they are different buttons, but the actions to be triggered are the same), then you don't have to create multiple action listeners for multiple buttons. You can let your buttons add the same action listener:
//Example
class MyPanel extends JPanel{
private JButton btn1, btn2;
public MyPanel(){
btn1 = new JButton("Button 1");
btn2 = new JButton("Button 2");
ButtonHandler bn = new ButtonHandler();
btn1.addActionListener(bh);
btn2.addActionListener(bh);
}
}
Infact, what you wanted to do is just a one-liner:
private class ButtonHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e){
System.out.println((JButton)e.getSource().getText());
}
}
However, if you have different actions for different buttons (for example, Start Game and Exit Game), then you can create separate action listeners for them.
So maybe you want to check the source of the event? Like:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1) {
System.out.println("b1 pressed");
} else if (e.getSource() == b2) {
System.out.println("b2 pressed");
} else {
System.out.println("some other button pressed");
}
}
and you should really create different buttons outside of the scope of this actionPerformed method!
EDIT
The example solution by user3437460 is much better than this oneā¦
Every component can hold information on it, by putClientProperty();
This mechanism is kind of map, so can hold few named objects. We use only one.
This obcjet (pie of information) is not visible for user, it is not text written on button like getText() in few tries, is only for consuming by algorithm. There can live not only primitives or strings, but live objects too.
class MyPanel extends JPanel{
private JButton btn1, btn2;
public MyPanel(){
btn1 = new JButton("Button 1");
btn1.putClientProperty("myinternalsense", 8); // <-- here
btn2 = new JButton("Button 2");
btn1.putClientProperty("myinternalsense", 5); // <-- here
btn1.putClientProperty("myfunctor", new MyFunctor() ); // <-- here
ButtonHandler bn = new ButtonHandler();
btn1.addActionListener(bh);
btn2.addActionListener(bh);
}
}
This information is accessible in any context, for example common event handler to many buttons.
private class ButtonHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e){
System.out.println((JButton)e.getSource().getClientPropertygetText("myinternasense")); // <-- here
}
}
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);
In the if statement, it is failing to find launchBtn. I'm probably doing something stupidly obvious. Can anyone see what's wrong? The errors are in bold (or highlighted with two **, Here is my code:
package launcher;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
class Window extends JFrame implements ActionListener
{
JPanel panel = new JPanel();
public Window()
{
//Creates the blank panel
super("Launcher");
setSize(500, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
add(panel);
setVisible(true);
//Create the button variables
JButton launchBtn = new JButton("Launch Game");
JButton optionsBtn = new JButton("Launcher Options");
//Add the buttons to the launcher
panel.add(launchBtn);
panel.add(optionsBtn);
//Add the buttons to the action listener
launchBtn.addActionListener(this);
optionsBtn.addActionListener(this);
}
public void actionPerformed(ActionEvent event)
{
if(event.getSource() == **launchBtn**)
{
**launchBtn**.setEnabled(true);
}
}
}
launchBtn has being declared as a local variable with the context of the Window constructor. It has no meaning beyond the constructors scope.
public Window()
{
//...
//Create the button variables
JButton launchBtn = new JButton("Launch Game");
If you wish to access the variable out side of the constructor, you should make a class instance variable...
private JButton launchBtn;
public Window()
{
//...
//Create the button variables
launchBtn = new JButton("Launch Game");
This will allow other methods of the Window class to reference the variable
You probably wanted launchBtn and optionsBtn to be instance variables of this class, not local variables declared in the constructor. Move their declarations to outside of the constructor.
I'm learning Java and GUI. I have some questions, and the first is if there are any major difference between creating a subclass of JFrame and an instance of JFrame. It seems like like a subclass is more powerful? I also wonder if it's necessary to use this code when creating a GUI:
Container contentPane = getContentPane();
contentPane.setLayot(new Flowlayout());
I add my GUI class, it's a simple test so far, to a task that I have to hand in. When a user has entered some text in the textfield and press the button to continue to the next step, how do I do to clear the frame and show a new content or is there a special way to do this is in Java? I guess there must be better to use the same window instead of creating a new!? Help id preciated! Thanks
// Gui class
import java.awt.FlowLayout; // layout
import java.awt.event.ActionListener; // listener
import java.awt.event.ActionEvent; // event
import javax.swing.JFrame; // windows properties
import javax.swing.JLabel; // row of text
import javax.swing.JTextField; // enter text
import javax.swing.JOptionPane; // pop up dialog
import javax.swing.JButton; // buttons
// import.javax.swing.*;
public class Gui extends JFrame {
private JLabel text1;
private JTextField textInput1;
private JTextField textInput2;
private JButton nextButton;
// constructor creates the window and it's components
public Gui() {
super("Bank"); // title
setLayout(new FlowLayout()); // set default layout
text1 = new JLabel("New customer");
add(text1);
textInput1 = new JTextField(10);
add(textInput1);
nextButton = new JButton("Continue");
add(nextButton);
// create object to handle the components (action listener object)
frameHandler handler = new frameHandler();
textInput1.addActionListener(handler);
nextButton.addActionListener(handler);
}
// handle the events (class inside another class inherits contents from class outside)
private class frameHandler implements ActionListener {
public void actionPerformed(ActionEvent event){
String input1 = "";
// check if someone hits enter at first textfield
if(event.getSource() == textInput1){
input1 = String.format(event.getActionCommand());
JOptionPane.showMessageDialog(null, input1);
}
else if(event.getSource() == nextButton){
// ??
}
}
}
}
This small code might help you explain things :
import java.awt.event.*;
import javax.swing.*;
public class FrameDisplayTest implements ActionListener
{
/*
* Creating an object of JFrame instead of extending it
* has no side effects.
*/
private JFrame frame;
private JPanel panel, panel1;
private JTextField tfield;
private JButton nextButton, backButton;
public FrameDisplayTest()
{
frame = new JFrame("Frame Display Test");
// If you running your program from cmd, this line lets it comes
// out of cmd when you click the top-right RED Button.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel1 = new JPanel();
tfield = new JTextField(10);
nextButton = new JButton("NEXT");
backButton = new JButton("BACK");
nextButton.addActionListener(this);
backButton.addActionListener(this);
panel.add(tfield);
panel.add(nextButton);
panel1.add(backButton);
frame.setContentPane(panel);
frame.setSize(220, 220);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent ae)
{
JButton button = (JButton) ae.getSource();
if (tfield.getText().length() > 0)
{
if (button == nextButton)
{
/*
* this will remove the first panel
* and add the new panel to the frame.
*/
frame.remove(panel);
frame.setContentPane(panel1);
}
else if (button == backButton)
{
frame.remove(panel1);
frame.setContentPane(panel);
}
frame.validate();
frame.repaint(); // prefer to write this always.
}
}
public static void main(String[] args)
{
/*
* This is the most important part ofyour GUI app, never forget
* to schedule a job for your event dispatcher thread :
* by calling the function, method or constructor, responsible
* for creating and displaying your GUI.
*/
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new FrameDisplayTest();
}
});
}
}
if you want to switch (add then remove) JComponents, then you have to
1) add/remove JComponents and then call
revalidate();
repaint()// sometimes required
2) better and easiest choice would be implements CardLayout
If your requirement is to make a wizard, a panel with next and prev buttons, and on clicking next/prev button showing some component. You could try using CardLayout.
The CardLayout manages two or more components (usually JPanel instances) that share the same display space. CardLayout let the user choose between the components.
How to Use CardLayout
If your class extends JFrame, you can do:
getContentPane().removeAll();