How to Perform Multiple Action on Single Click in Java Swing - java

I have a Question on performing other buttons action with single button click. Some example code for three buttons:
JButton a = new JButton("a");
a.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Action of a is Here
}
});
JButton b = new JButton("b");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Action of b is Here
}
});
Those should come together, like:
JButton c = new JButton("c");
c.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Action of c is Here
// Action of a
// Action of b
}
});
In the above example i have three buttons a,b,c with its own action; but as you can see, C also has to run the actions of A and B. What are good ways to address this?

The other answers are all correct, but there is one important aspect missing here: be careful about dong "too many things" on the AWT event dispatcher thread.
Meaning: when a button is clicked, an event gets created, and the UI framework uses that special thread to trigger the registered listeners. If one of the listeners now decides to do a intensive computation ... the UI event threads stays busy doing "that". And while doing "that thing"; this thread isn't available to dispatch any other UI event.
So, this is "not only" about creating methodA(), methodB(), methodC() and invoking them in your third action listener. It is also about understanding if combining multiple calls becomes subject to "I should better run those things in a separate thread; to not block the event dispatcher thread".
In that sense: the other answers tell you where to go from here; but be really careful about the "amount of activity" that your "joined actions" button is about to create!

1) Methods
Use methods for each action and call those in the ActionListener.actionPerformed
public void methodA(){}
public void methodB(){
methodA();
}
2) Action instance
You could create your own classes of ActionListener to perform the actions
First action :
class ActionA implements ActionListener{
public void actionPerformed(ActionEvent e) {
...
}
}
An improved action
class ActionB extends ActionA{
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e); //Will call the first action
...
}
}
This is limited since you can't have multiple extends but is also a nice solution
3) Click
Last but I don't like it, use AbstractButton.doClick to dynamicly click on other buttons.
4) Add multiple action
Just notice that the methods is not a setActionListener but a addActionListener meaning that it will accept multiple ActionListener.
So define create two instances
ActionListener listenerA = new ActionLisener ..
ActionListener listenerB = new ActionLisener ..
buttonA.addActionListener(listenerA);
buttonB.addActionListener(listenerB);
buttonC.addActionListener(listenerA);
buttonC.addActionListener(listenerB);
With a small test, I notice that the actions are execute in the order B -> A (might not be a generality).
As said in comment, this should be us knowing the risk, this will . If an action failed because of an exception, should the next one be executed ? By default it won't because the process will not hide exceptions.
I would restrict this solution to GUI management like reseting fields, disabling, ... that could be use in different buttons.

Whatever you want to do on Button click a, you can put in a method and call it from wherever you want.
public void methodForA(){
// do here what you want
}
You can call this now in the methods you want it to call from. In your case from button click A and button click C
JButton a = new JButton("a");
a.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
methodForA();
}
});
// and also in your c-Button
JButton c = new JButton("c");
c.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Action of c is Here
methodForA();
}
});

Create 3 methods for each button indepently from the actionListeners action Perform method and call them from the actionPerfomed methods:
private void btnAClicked(){};
private void btnBClicked(){};
private void btnCClicked(){};
JButton c = new JButton("c");
c.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
btnCClicked();
btnAClicked();
btnBClicked();
}
});

Related

Button actionlistener calls another action listener in the same class

I have a submit button (and an action listener) which checks if the number inserted into a Futoshiki puzzle is legal (checking a 2D array for duplications etc)
In another method I have the actual grid with an action listener that gets the numbers and inserts them into the 2D array.
JButton acction listener
JButton isRight = new JButton("Check My Answer");
isRight.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!(puzzle.isLegal())) {
JOptionPane.showMessageDialog(FutoshikiFrame.this,
puzzle.getProblems(),
"You made a mistake!",
JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(FutoshikiFrame.this,
"YOU WIN!",
"YES THATS FINE",
JOptionPane.INFORMATION_MESSAGE);
}
puzzle.printProblems.clear();
}
});
Grid action listener
public void keyReleased(KeyEvent e) {
String getInsertedValue = Emptysquare.getText();
int getInsertedIntValue = Integer.parseInt(getInsertedValue);
setSquareValue(r, c, getInsertedIntValue);
System.out.print(getSquareValue(r, c));
}
Is there a way I can access the keyReleased action listener from the JButton so it basically "submits" the contents of the grid and then checks if its legal?
Sure, just either keep a reference to that action listener and call the keyReleased method with a null value, or refactor out the content of keyReleased to an own method and call this method from both listeners.
Although 2 other methods were given, here is an additional way you could go about it, but I'm not sure which would be best to use.
public class YourClass {
JButton isRight;
public YourClass() {
this.isRight = new JButton();
this.isRight.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
YourClass.this.isRight.getKeyListeners()[0].keyReleased(null);
//Other action related code
}
});
isRight.addKeyListener(new KeyListener() {
public void keyReleased(KeyEvent e) {
//Key related code
}
//Other required key listener methods
});
}
}

MVC pattern for multiple JButtons

How should i implement an MVC controller with multiple JButtons on the view?
for example: i have a start button, stop button and many others as well.
I tried to do this for the start button and it works fine but then how do i implement it for a stop button trigger?
Controller Code:
public MVCAuctionController(Auction a, MVCAuctionView v) {
auction = a;
view = v;
view.addProcessBidsListener(new ProcessBidsController());
view.addStopProcessListener(new StopBidsController());
}
class ProcessBidsController implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
view.disableProcessButton();
Thread thread = new Thread (auction);
thread.start();
}
}
addProcessBidsListener - is associated with the START/Process button,When i click on the button - the thread starts running and fills the JTextArea with data.
Now my Stop button should stop the thread. For this if i do something like this it doesnt actually stop the Thread:
class ProcessStartController implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == view.start){
view.disableStartButton();
new Thread (rest).start();
//thread.start();
System.out.println("inside action performed of start button");
view.kitchen.append("Orders to kitchen");
}
else if (e.getSource() == view.stop)
{
new Thread (rest).interrupt();
}
}
}
Use an Action for each button, they are self contained controllers
See How to use Actions for more details
You can then set up some kind of relationship between the Actions and the main controller should you need it, via some kind listener for example

Common Action Listener for 3 Buttons

I am having trouble with the design of my code. I have 3 buttons not in a button group. I want to - based on the selected button - perform an action. Now the action requires a modification of an object in the class. This means i cannot use an inner class because this does not have access to the outer. If i could add an event listener to a button group this would be much easier but as i see it i will need an event handler for each radio button, is this correct? If not how else can i do it? Thanks
A quick example
public class Test(){
RadioButton 1 = new RadoButton();
RadioButton 2 = new RadoButton();
RadioButton 3 = new RadoButton();
Object myObject = new Object();
public void clickEvent(){
if(1.isSelected()){
myObject.doOne();
}else if(2.isSelected()){
myObject.doTwo();
}.....
}
}
You can set the same listener to all your buttons.
Pseudo code:
radioButton1 = new RadioButton();
radioButton2 = new RadioButton();
radioButton3 = new RadioButton();
listener = new ActionListener() {
...
}
radioButton1.addActionListener(listener);
radioButton2.addActionListener(listener);
radioButton3.addActionListener(listener);
This is to illustrate how you can use an inner class:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JRadioButton;
public class TestInnerClass {
JRadioButton radioOne = new JRadioButton();
JRadioButton radioTwo = new JRadioButton();
JRadioButton radioThree = new JRadioButton();
Object myObject = new Object();
public TestInnerClass() {
ActionListener myInnerClass = new MyActionListener();
radioOne.addActionListener(myInnerClass);
radioTwo.addActionListener(myInnerClass);
radioThree.addActionListener(myInnerClass);
}
private class MyActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
if(radioOne.isSelected()) myObject.toString();
else if(radioTwo.isSelected()) myObject.notify();
else if(radioThree.isSelected()) myObject.getClass().getName();
}
}
}
Note how the inner class is not static, as stated in gontard's comment, so does have visibility to myObject. And it's safest to keep it private.
It's often good to have one listener handle all events, as in this case. There are, however, other cases where you want your event handling more specific to each component. For example, in these cases, radioThree could trigger the event, and since these buttons are not in a group it might be possible that radioOne is still in the selected state. This single handler will fire and act only on the first radio. While one way to fix this would be to add checks for the source, as in:
public void actionPerformed(ActionEvent event) {
if(event.getSource() == radioOne && radioOne.isSelected())
myObject.toString();
if(event.getSource() == radioTwo && radioTwo.isSelected())
myObject.notify();
if(event.getSource() == radioThree && radioThree.isSelected())
myObject.getClass().getName();
}
Another way would be to use one listener for each component. That's where the anonymous class comes in very handy:
radioOne.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myObject.doOne();
}
});
One of my favorite patterns, especially if the work is non-trivial, is to first create a method to do the work, then call it from the listener. I also wrap the call in SwingUtilities.invokeLater() to get the work off the Swing Event Thread.
public class Test {
JRadioButton radioOne = new JRadioButton();
Object myObject = new Object();
private void handleRadioOne() {
myObject.toString();
// etc, etc.
}
public Test() {
radioOne.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
handleRadioOne();
}
});
}
});
}
}
This provides two nice features:
It encapsulates your action work into a method allowing for programmatic access if later desired
It ensures that the method's work stays off the Swing Event Thread, so your GUI won't hang up during intensive processing

ActionListener style - Good or bad [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I have a simple GUI which contains:
a push button.
Two radio buttons
Now I want to listen to each one of these buttons. What I do is something like that:
public class TestApp implements ActionListener {
private JFrame frame;
private JButton btn;
private JRadioButton rdb1;
private JRadioButton rdb2;
public static void main(String[] args) { /*....*/ }
private void initialize() {
//Each time I add a button, I add it to the listener:
btn = new JButton("Button");
btn.addActionListener(this);
//..
rdb1 = new JRadioButton("Value1");
rdb1.addActionListener(this);
//And so on...
}
//The ActionEvents
public void actionPerformed(ActionEvent e) {
if(e.getSource()==btn)
//...
if(e.getSource()==rdb1)
//...
}
}
Now I want to know if this considered a good/bad style?
Unless the listener is a very long method, I personally prefer the anonymous class pattern:
final JButton btn = new JButton("Button");
final JRadioButton rdb1 = new JRadioButton("Value1");
final ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
if (e.getSource() == btn) {
//...
} else if (e.getSource() == rdb1) {
//...
}
}
};
btn.addActionListener(listener);
rdb1.addActionListener(listener);
or even better:
btn.addActionListener(new ActionListener (){
public void actionPerformed(ActionEvent e) {
// btn handling code
}
});
rdb1.addActionListener(new ActionListener (){
public void actionPerformed(ActionEvent e) {
// rdb1 handling code
}
});
The pattern you are using allows other class to set the class TestApp to be set as a listener by other classes - unless this is intended, it is not a good practice.
A lot comes down to the complexity of what the action listener is trying to do. If you want small, single use actions, then an anonymous class would suitable.
The main benefit of using this style of listener is it will isolate exactly what the action is doing and who it's doing it for. The drawback comes when the listener contains more then, say, 10 or more lines, as it starts to becoming difficult to read and know where the listener actually ends.
In this case, something like a inner class might be more suitable. It has the benefit of an anonymous class (being tied to the class that uses it), but is easier to read.
If you want reusable actions (think of things like open, new, save), then you're better off using the Action API, which provides self configurability as well a self contained action listener
IMHO
More object-oriented way is to create an anonymous class for implementation of each of the listeners.
Creating only one listener that switches on the event source component is not very readable, but moreover, when the number of listeners increases, it becomes error prone. You can easily forget to handle all of the possible event sources in the switch block (or a chain of if-else blocks), which will result in a runtime exception silent wrong behaviour (nothing would happen for that case).
Adding individual listeners to each of the components will give you compile-time checking that you haven't forgotten to handle all of them.
public class TestApp {
// you can initialize fields inline to make thing shorter and safer
private JButton btn = new JButton("Button");
private JRadioButton rdb1 = new JRadioButton("Value1");
private void initialize() {
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// something
}
});
rdb1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// something else
}
});
}
}
Because the anonymous class syntax is very verbose, you can shorten the code of the initialize method by moving the listeners into private fields.
public class TestApp {
private JButton btn = new JButton("Button");
private JRadioButton rdb1 = new JRadioButton("Value1");
private void initialize() {
btn.addActionListener(btnListener);
rdb1.addActionListener(rb1Listener);
}
private final ActionListener btnListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// something
}
};
private final ActionListener rb1Listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// something else
}
};
}
You can think about two other ideas:
Give each UI element its own Listener; they're completely independent that way.
Inject the Listeners into your Swing UI rather than calling new. You give users the opportunity to change the behavior as they see fit. Let your Swing UI do what it was meant to do: display results. That's it. I would argue that Listeners are part of the Controller logic.
It depends to a certain extent on what you want to do in the actionPerformed method. If no other class is likely to want to call this method then I may be tempted to reduce the scope of the actionPerformed method by creating an inner class e.g.:-
public class TestApp {
private JFrame frame;
private JButton btn;
private JRadioButton rdb1;
private JRadioButton rdb2;
private class CombinedActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if(e.getSource()==btn)
//...
if(e.getSource()==rdb1)
//...
}
}
public static void main(String[] args) { /*....*/ }
private void initialize() {
ActionListener listener = new CombinedActionListener()
//Each time I add a button, I add it to the listener:
btn = new JButton("Button");
btn.addActionListener(listener);
//..
rdb1 = new JRadioButton("Value1");
rdb1.addActionListener(listener);
//And so on...
}
}
You could even make the listener class a static inner class or a top-level class by passing the button instances into the constructor - which would make the listener class easier to test.
As I said above though, this is largely dependent on i) if anyone else is likely to call this method and ii) the complexity of the logic inside the method.

How to add multiple ActionListeners for multiple buttons in Java Swing

I know how to create one button and an Action Listener for it. But I want to have several buttons and actionListeners for them doing separate actions unrelated to each other.
Example:
protected JButton x;
x = new JButton("add");
x.addActionListener(this);
public void actionPerformed(ActionEvent evt) { //code.....}
Now I want to have other buttons which may hav different functions like subtract, multiply etc.
please suggest. thanks
What about:
JButton addButton = new JButton( new AbstractAction("add") {
#Override
public void actionPerformed( ActionEvent e ) {
// add Action
}
});
JButton substractButton = new JButton( new AbstractAction("substract") {
#Override
public void actionPerformed( ActionEvent e ) {
// substract Action
}
});
Use inner classes:
x = new JButton("add");
x.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
//your code here
}
}
);
how about...
protected JButton x, z, a, b,c;
x = new JButton("add x");
z = new JButton("add z");
a = new JButton("add a");
b = new JButton("add b");
c = new JButton("add c");
x.addActionListener(this);
z.addActionListener(this);
a.addActionListener(this);
b.addActionListener(this);
c.addActionListener(this);
then
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource()==x)
{
//do something
}
else if (evt.getSource()==z)
{
//do something
}
else if (evt.getSource()==a)
{
//do something
}
else if (evt.getSource()==b)
{
//do something
}
else if (evt.getSource()==c)
{
//do something
}
}
this is always works for me, but honestly I'm not sure if it's not bad practice
You can either use ActionEvent.getSource() to decide the source and act accordingly or you can define different ActionListeners for each of them.
You just need to create new instance of the ActionListener each time.
BTW for lots of reasons it is recommended to use Action's instead.
Here is nice resource which also explains why you should go with using Actions over ActionListeners, a Java tutorial titled How to Use Actions
EDIT: #fmucar is right you can do it all in a single ActionListener. Though having separate functional Actions allows you to reuse them independently.
You can create different action listener instances, not using your class:
x.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e)
{ ... }
});
There are several other methods to create action listener, just like any class, but for short actions this (anonymous class) is a convenient way.

Categories