Reputation:
I am working on a project where there is a front and back course for a golf app that tracks the scores and stuff, and I am using the same frames for the front and the back, the front and the back write and read to different files and need to use different methods etc.
I am setting up my action listeners like this
BUTTON_NAME.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// does stuff
}
});
The problem that I am having with this if you use one of the action listeners from the front course frame they wont change when I want them to
Here is now I'm trying to change the action listeners
BUTTON_NAME.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
BUTTON_NAME.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// does stuff
}
});
}
});
So how would I correctly accomplish this? Thank you in advance.
Upvotes: 0
Views: 174
Reputation: 347204
The core issue is not with the button or ActionListener
, but with how you want to change the functionality when the ActionListener
is triggered.
This is a core design principle which is demonstrated through the use of things like "dependency injection", "delegation", "observers", "models" and/or "data sources". Many of these are the same concept, performing slightly different roles, depending on your needs
See...
for more details.
For simplicity, a "delegate" can often be thought of as an "observer", for example, the ActionListener
provides delegation of workflow when a button is clicked.
import java.awt.EventQueue;
import java.awt.GridBagLayout;
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.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
JPanel panel = new JPanel(new GridLayout(1, 2));
panel.add(new CommonPane(new CommonDelegate() {
@Override
public void didClickMe(CommonPane source) {
JOptionPane.showMessageDialog(source, "Left was clicked");
}
}));
panel.add(new CommonPane(new CommonDelegate() {
@Override
public void didClickMe(CommonPane source) {
JOptionPane.showMessageDialog(source, "Right was clicked");
}
}));
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface CommonDelegate {
public void didClickMe(CommonPane source);
}
public class CommonPane extends JPanel {
public CommonPane(CommonDelegate delegate) {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(32, 32, 32, 32));
JButton btn = new JButton("Click me");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
delegate.didClickMe(CommonPane.this);
}
});
add(btn);
}
}
}
import java.awt.EventQueue;
import java.awt.GridBagLayout;
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.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
JPanel panel = new JPanel(new GridLayout(1, 2));
panel.add(new CommonPane(new CommonDataSource() {
@Override
public String getClickMeTitle() {
return "On the left";
}
@Override
public String getClickMeMessage() {
return "Left was clicked";
}
}));
panel.add(new CommonPane(new CommonDataSource() {
@Override
public String getClickMeTitle() {
return "On the right";
}
@Override
public String getClickMeMessage() {
return "Right was clicked";
}
}));
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface CommonDataSource {
public String getClickMeTitle();
public String getClickMeMessage();
}
public class CommonPane extends JPanel {
public CommonPane(CommonDataSource dataSource) {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(32, 32, 32, 32));
JButton btn = new JButton(dataSource.getClickMeTitle());
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(CommonPane.this, dataSource.getClickMeMessage());
}
});
add(btn);
}
}
}
You could combine the roles of the "delegate" and the "data source" (aka "model") or you could seperate them and use both, so your UI would require both a "model" and a "delegate", depending on your needs.
One thing I would not recommend, is exposing the JButton
to other calls, instead, if absolutely required, I'd expose a setXxxActionListener
if you want to provide a more "direct" delegation of an individual action, but this would raise some alarm bells for me and I'd be questioning the need to design the code this way, but that's me.
Upvotes: 1