One action listener, two JButtons - java

I have two JButtons called "Left" and "Right".
The "Left" button moves a rectangle object to the left and the "Right" button moves it to the right.
I have one ActionListener in the class that acts as the listener for when either button is clicked.
However I want different actions to happen when each are clicked. How can I distinguish, in the ActionListener, between which was clicked?

Set actionCommand to each of the button.
// Set the action commands to both the buttons.
btnOne.setActionCommand("1");
btnTwo.setActionCommand("2");
public void actionPerformed(ActionEvent e) {
int action = Integer.parseInt(e.getActionCommand());
switch(action) {
case 1:
//doSomething
break;
case 2:
// doSomething;
break;
}
}
UPDATE:
public class JBtnExample {
public static void main(String[] args) {
JButton btnOne = new JButton();
JButton btnTwo = new JButton();
ActionClass actionEvent = new ActionClass();
btnOne.addActionListener(actionEvent);
btnTwo.addActionListener(actionEvent);
btnOne.setActionCommand("1");
btnTwo.setActionCommand("2");
}
}
class ActionClass implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int action = Integer.parseInt(e.getActionCommand());
switch (action) {
case 1:
// DOSomething
break;
case 2:
// DOSomething
break;
default:
break;
}
}
}

Quite easy with the getSource() method available to ActionEvent:
JButton leftButton, rightButton;
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if (src == leftButton) {
}
else if (src == rightButton) {
}
}

Related

How to click a JButton multiple times, changing the button text each time?

I can't find a solution for this that works for more than 2 clicks. I want to use an actionlistener on my button, so that on each click, the button text changes between "A", "B" and "C" in this order.
My "click" is set to 0 right now as I don't know what to set it to in order to do this.
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
button = (JButton) event.getSource()
click = 0;
switch (click) {
case 0:
button.setText("A");
break;
case 1:
button.setText("B");
break;
case 2:
button.setText("C");
break;
}
}
});
You are close. What should work is moving the click out of the method:
button.addActionListener(new ActionListener() {
int click = 0;
#Override
public void actionPerformed(ActionEvent event) {
button = (JButton) event.getSource()
switch (click % 3) { // loop back around after 3 clicks
case 0:
button.setText("A");
break;
case 1:
button.setText("B");
break;
case 2:
button.setText("C");
break;
}
click++;
}
});

Replace many "else if" with something else

I am using an ActionListener and have lots of else if statements in order to know which button is pressed and run some code depending on the button.
Is there a way to make the code nicer? I have nearly 10 else if statements following each other, is there something else I could use instead?
Sample of code:
class BtnListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == menu.getOpen()) {
getFile();
} else if (e.getSource() == btnPlay) {
} else if (e.getSource() == btnQuit)) {
}
}
Thanks.
You can fill Map<Object, Consumer<ActionEvent>> before using of listener, for example in constructor, where key is source and value is a consumer for action event. In action perform just get consumer by key and invoke it.
class BtnListener implements ActionListener {
Map<Object, Consumer<ActionEvent>> eventsMap = new HashMap<>();
public BtnListener() {
eventsMap.put(menu.getOpen(), actionEvent -> this.getFile());
eventsMap.put(btnPlay, actionEvent -> { //do something
});
eventsMap.put(btnQuit, actionEvent -> { //do something else
});
}
#Override
public void actionPerformed(ActionEvent e) {
Optional.of(e)
.map(ActionEvent::getSource)
.map(eventsMap::get)
.ifPresent(
actionEventConsumer -> actionEventConsumer.accept(e)
);
}
}
You may use the action command of the button, and a switch-case block :
public void actionPerformed(ActionEvent e){
switch(e.getActionCommand()) {
case "Open":
open();
break;
case "Delete":
delete();
break;
default :
break;
}
}
Of course you will have to set the action command of each button first, like :
openButton.setActionCommand("Open");
Note that switch-case with String objects only exists since JDK 7 : Strings in switch Statements
You can switch statement instead lot of else if ladder.
class BtnListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == menu.getOpen()) {
getFile();
}
switch( e.getSource() ){
case btnPlay:
break;
case btnQuit:
break;
default:
}
}
}
the best way to avoid all the "overheads" is to Lambda-Expressioned the buttons. Example:
JButton b1 = new JButton("Play");
b1.addActionListener(e -> play());
...
JButton bn = new JButton("Stop");
bn.addActionListener(e -> stop());
...
private void play() {
....// playing codes
}
...
private void stop() {
...// stopping codes
}
...

How do I use the outcome of my actionPerformed method to effect the main method - java

I have a class called Screen containing the actionPerformed method.
I want a different outcome for the different menu items: random, aggressive and human.
This outcome effects the main method, however I am unsure how to link the two...
public class Screen extends JFrame
implements ActionListener {
ActionListener listener;
JMenuItem random = new JMenuItem("Random");
JMenuItem aggressive = new JMenuItem("Aggressive");
JMenuItem human = new JMenuItem("Human");
public Screen(Board board){
//menuBar items
menu.add(random);
random.addActionListener(this);
menu.add(aggressive);
aggressive.addActionListener(this);
menu.add(human);
human.addActionListener(this);
....
//sets up board of buttons and adds actionListener to each.
....
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == random){
}
if(e.getSource() == aggressive){
}
if(e.getSource() == human){
}
//code for the board buttons - nothing to do with the menu.
//But thought it might help
if (numClicks == 0){
JButton piece = (JButton) e.getSource();
String xy = piece.getName();
String x = xy.substring(0,1);
String y = xy.substring(2,3);
FromXInt = Integer.parseInt(x);
FromYInt = Integer.parseInt(y);
System.out.println("From" + " " +FromXInt + "," + FromYInt);
}
else{
JButton piece = (JButton) e.getSource();
String xy = piece.getName();
String x = xy.substring(0,1);
String y = xy.substring(2,3);
ToXInt = Integer.parseInt(x);
ToYInt = Integer.parseInt(y);
System.out.println("To" + " " + ToXInt + "," + ToYInt);
}
numClicks++;
if (numClicks >= 2){
numClicks = 0;
}
return;
}
}
My class which contains the main method:
public class Chess{
public static void main(String [ ] args){
Screen s = new Screen(board);
// my attempt but doesn't work
if (s.actionPerformed(e) == random){
.....
note: I am new to Java and still trying to get my head round the linking of multiple classes.
--------------------The ActionPerformed method also contains events if buttons are clicked but I haven't added that code in because it over complicates things.--
This approach uses a public enum and sets the style variable according to the users menu choice:
package chess;
//...
public class Screen extends JFrame
implements ActionListener {
private JMenuItem random = new JMenuItem("Random");
private JMenuItem aggressive = new JMenuItem("Aggressive");
private JMenuItem human = new JMenuItem("Human");
public enum PlayStyle {Random, Aggressive, Human};
private PlayStyle style;
public Screen(Board board) {
//menuBar items
menu.add(random);
random.addActionListener(this);
menu.add(aggressive);
aggressive.addActionListener(this);
menu.add(human);
human.addActionListener(this);
//....
//sets up board of buttons and adds actionListener to each.
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == random) {
style=PlayStyle.Random;
}
if (e.getSource() == aggressive) {
style=PlayStyle.Aggressive;
}
if (e.getSource() == human) {
style=PlayStyle.Human;
}
//code for the board buttons - nothing to do with the menu.
//....
}
public PlayStyle getStyle(){
return style;
}
}
This is the class that contains the main method:
package chess;
import chess.Screen.PlayStyle;
public class Chess{
public static void main(String [ ] args){
Screen s = new Screen(board);
// this attempt will work
if (s.getStyle()==PlayStyle.Random) {
...
} else if (s.getStyle()==PlayStyle.Aggressive){
...
You are calling a method and it seems that you want to use something that comes back from that method but the method itself returns nothing, i.e. "void". I changed your Screen class so that the method returns something now.
public class Screen extends JFrame
implements ActionListener {
public Source actionPerformed(ActionEvent e) {
....
if(e.getSource() == random){
}
if(e.getSource() == aggressive){
}
if(e.getSource() == human){
}
return e.getSource()
}
The main method will now be able to receive a result from the call and use it.

How to make an action command for same buttons

I have here just a snip of code for my button:
up = new JButton(new ImageIcon("more_buttons\\up3.png"));
up.setBackground(new Color(224,223,227));
up.setPreferredSize(new Dimension(5,15));
up.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
value1000++;
if(value1000>0)
{
number.setText(value1000+"");
down.setEnabled(true);
}
}
});
down = new JButton(new ImageIcon("more_buttons\\down3.png"));
down.setBackground(new Color(224,223,227));
down.setPreferredSize(new Dimension(5,15));
down.setEnabled(false);
down.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
value1000--;
if(value1000>0)
{
number.setText(value1000+"");
}
if(value1000==0)
{
number.setText(value1000+"");
down.setEnabled(false);
}
}
});
I'm wondering if I can make an action command for this button so that I won't have to repeat this code throughout my program. I only have to call the function like buttonaction(e) or something like that. I'm not used to creating action command but I have used it before but only for appending text. I'm not sure how to do that with a function like this. Is it possible? Or is there a more efficient way to do this?
You can add the same ActionListener to multiple buttons:
ActionListener al = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// You can check which button was pressed and act accordingly
// simply by checking the event source:
if (e.getSource() == button1)
System.out.println("Button1 was pressed.");
else if (e.getSource() == button2)
System.out.println("Button2 was pressed.");
}
};
button1.addActionListener(al);
button2.addActionListener(al);
To remove boiler plate code, You need to at least implement an ActionListener in your class
samaple:
public class myClass implements ActionListener
It will generate an actionPerformed method After you need to add actionCommand in your button so when you click a button it will recognize it that you pressed that button
sample:
down.setActionCommand("down");
down.addActionListener(this);
up.setActionCommand("up");
up.addActionListener(this);
in the actionPerformed method
#Override
public void actionPerformed(ActionEvent evt)
{
String actionCommand = evt.getActionCommand(); //get the actionCommand and pass it to String actionCommand
switch(actionCommand) { //switch statement for each of the action command
case "down":
//down button command here
break;
case "up":
//up button command here
}
}
Take a look at How to use Actions
public abstract class AbstractNumberValueAction extends AbstractAction {
private NumberModel model;
private JTextField numberField;
private int delta;
public ValueAction(NumberModel model, JTextField numberField, int delta) {
this.model = model;
this.numberField = numberField;
this.delta = delta;
}
public void actionPerformed(ActionEvent evt) {
int value1000 = model.updateValue(delta);
if(value1000>0)
{
numberField.setText(value1000+"");
}
if(value1000==0)
{
numberField.setText(value1000+"");
setEnabled(false);
}
}
}
public class UpAction extends AbstractNumberValueAction {
public ValueAction(NumberModel model, JTextField numberField) {
this(model, numberField, 1);
putValue(SMALL_ICON, new ImageIcon("more_buttons\\up3.png"));
}
}
public class DownAction extends AbstractNumberValueAction {
public ValueAction(NumberModel model, JTextField numberField) {
this(model, numberField, -1);
putValue(SMALL_ICON, new ImageIcon("more_buttons\\down3.png"));
}
}
Which could then simply be applied as
up = new JButton(new UpAction(model, number));
down = new JButton(new DownAction(model, number));
For example...
(ps- NumberModel would be a simple class that controlled the underlying value to make is simpler to manage ;))

Not waiting for a method call to finish before calling another method

I need a bit of help.
I'm just after coming back to programming after being made unemployed.
I'm trying to learn Java and I have run into a difficulty.
The problem is that I want to call a method that should ask the user for an input by pressing a button. This will return the chouce back to the class that called the method.
public class ButtonMain {
private static CreateButton cButton;
public static void main(String[] args) {
cButton = new CreateButton();
cButton.launchButton();
switch(cButton.getSelect()) {
case 'a' : System.out.println("German Car");
break;
case 'b' : System.out.println("Japanese Car");
break;
default : System.out.println("Incorrect Car Selected");
break;
}
}
}
The rest of the code is as follows
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CreateButton implements ActionListener {
private JFrame mainFrame;
private JLabel label1;
private JButton button1;
private JButton button2;
private char select = ' ';
public CreateButton() {
}
public void launchButton() {
createFrame();
createLabel();
createButton1();
createButton2();
}
private void createFrame() {
mainFrame = new JFrame("Cars");
mainFrame.setSize(200, 200);
mainFrame.setLocation(300, 300);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setVisible(true);
mainFrame.setPreferredSize(null);
mainFrame.setLayout(new java.awt.GridLayout(3, 1));
}
private void createLabel() {
label1 = new JLabel("Cars", SwingConstants.CENTER);
label1.setSize(200, 100);
mainFrame.getContentPane().add(label1, BorderLayout.CENTER);
}
public void createButton1() {
button1 = new JButton("Mercedes");
button1.setSize(200, 50);
button1.addActionListener(this);
mainFrame.getContentPane().add(button1, BorderLayout.CENTER);
}
private void createButton2() {
button2 = new JButton("Lexus");
button2.setSize(200, 50);
button2.addActionListener(this);
mainFrame.getContentPane().add(button2, BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button1) {
select = 'a';
System.out.println(select);
}
else if (e.getSource() == button2) {
select = 'b';
System.out.println(select);
}
}
public char getSelect() {
return select;
}
}
What is happening is that the output should read a or b and then whether German or Japanese cars was selected but i'm getting the incorrect car selected.
The code works fine. Its that your code is running through and nothing is stopping it. The cButton.launchButton() simply shows the frame and the code after it runs. Since select is initialized to space char "Incorrect Car Selected" is printed when the program starts. Your actions on the buttons are working correctly. Your switch statement should be in the actionPerformed method.
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button1) {
select = 'a';
System.out.println(select);
} else if (e.getSource() == button2) {
select = 'b';
System.out.println(select);
}
switch (getSelect()) {
case 'a':
System.out.println("German Car");
break;
case 'b':
System.out.println("Japanese Car");
break;
default:
System.out.println("Incorrect Car Selected");
}
}
The problem is that you will not have the selection information at the moment when main is called. Better to handle this in the ActionListener itself.
or
Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread.

Categories