This question already has an answer here:
-
Adding ActionListener to a Panel - Panel implements ActionListener vs Panel HAS A ActionListener
2 answers
I made a JPanel Child which contains a couple of radio buttons in it. Whenever a radio button is clicked i want an ActionEvent to be generated from the Child also. This action event should "contain" a reference to the button which actually generated an event.
This Child will be used as a component inside another JPanel Parent which will listen to the events from the Child, instead of listening to the individual radio buttons.
How can I do this ?
Code so far -
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class RadioListener extends JPanel implements ActionListener{
public static final String id = "id";
public RadioListener(){
for(int i = 1; i < 5; i++){
JRadioButton jrb = new JRadioButton(i + "", false);
jrb.putClientProperty(id, i);
this.add(jrb);
jrb.addActionListener(this);
}
}
public void actionPerformed(ActionEvent e){
JRadioButton jrb = (JRadioButton) e.getSource();
Integer id = (Integer) jrb.getClientProperty(RadioListener.id);
System.out.println("id " + id);
}
public static void main(String[]args){
JFrame frame = new JFrame("Radio buttons");
frame.getContentPane().setLayout(new FlowLayout());
frame.setSize(400, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new RadioListener());
frame.setVisible(true);
}
}
I'd recommend providing the ability for the component to act as a proxy for other interested parties to register interest.
This means you don't need to expose methods/components that other components shouldn't be calling or have access to.
You should also make use of inner classes for listeners, as they will prevent the exposure of other methods that others shouldn't have access to
public class ProxyActionListener extends JPanel {
public static final String id = "id";
private List<JRadioButton> buttons;
public ProxyActionListener() {
buttons = new ArrayList<>(25);
ActionHandler actionHandler = new ActionHandler();
for (int i = 1; i < 5; i++) {
JRadioButton jrb = new JRadioButton(i + "", false);
jrb.putClientProperty(id, i);
this.add(jrb);
jrb.addActionListener(actionHandler);
buttons.add(jrb);
}
}
public void addActionListener(ActionListener listener) {
for (JRadioButton btn : buttons) {
btn.addActionListener(listener);
}
}
public void removeActionListener(ActionListener listener) {
for (JRadioButton btn : buttons) {
btn.removeActionListener(listener);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
ProxyActionListener pal = new ProxyActionListener();
pal.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JRadioButton jrb = (JRadioButton) e.getSource();
Integer id = (Integer) jrb.getClientProperty(ProxyActionListener.id);
System.out.println("Proxy- id " + id);
}
});
JFrame frame = new JFrame("Radio buttons");
frame.getContentPane().setLayout(new FlowLayout());
frame.setSize(400, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(pal);
frame.setVisible(true);
}
});
}
protected class ActionHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
JRadioButton jrb = (JRadioButton) e.getSource();
Integer id = (Integer) jrb.getClientProperty(ProxyActionListener.id);
System.out.println("id " + id);
}
}
}
To go MadProgrammer's recommendations (1+) one step further, you could use Swing Components intrinsic PropertyChangeSupport for this purpose:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
@SuppressWarnings("serial")
public class RadioListenerTesterHFOE extends JPanel {
private RadioListenerHFOE radioListenerHfoe = new RadioListenerHFOE();
public RadioListenerTesterHFOE() {
add(radioListenerHfoe);
radioListenerHfoe.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (pcEvt.getPropertyName().equals(RadioListenerHFOE.RADIO)) {
System.out.println("Radio Selected: " + pcEvt.getNewValue());
}
}
});
}
private static void createAndShowGui() {
RadioListenerTesterHFOE mainPanel = new RadioListenerTesterHFOE();
JFrame frame = new JFrame("RadioListenerTesterHFOE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class RadioListenerHFOE extends JPanel {
private static final String[] LABELS = {"1", "2", "3", "4"};
private static final int GAP = 5;
public static final String RADIO = "radio";
private ButtonGroup buttonGroup = new ButtonGroup();
private RadioListenerHandler handler = new RadioListenerHandler();
public RadioListenerHFOE() {
setLayout(new GridLayout(1, 0, GAP, 0));
for (String label : LABELS) {
JRadioButton radioButton = new JRadioButton(label);
radioButton.setActionCommand(label);
radioButton.addActionListener(handler);
buttonGroup.add(radioButton);
add(radioButton);
}
}
private class RadioListenerHandler implements ActionListener {
private String actionCommand = null;
@Override
public void actionPerformed(ActionEvent evt) {
setActionCommand(evt.getActionCommand());
}
private void setActionCommand(String actionCommand) {
String oldValue = this.actionCommand;
String newValue = actionCommand;
this.actionCommand = newValue;
firePropertyChange(RADIO, oldValue, newValue);
}
}
}
Is this solution good enough ?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class RadioListener extends JPanel{
public static final String id = "id";
private ActionListener privateActionListener;
JRadioButton[] btns = new JRadioButton[5];
public RadioListener(){
for(int i = 0; i < btns.length; i++){
JRadioButton jrb = new JRadioButton(i + "", false);
jrb.putClientProperty(id, i);
btns[i] = jrb;
this.add(jrb);
}
}
public static void main(String[]args){
JFrame frame = new JFrame("Radio buttons");
frame.getContentPane().setLayout(new FlowLayout());
frame.setSize(400, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
AnActionListener an = new AnActionListener();
RadioListener rl = new RadioListener();
rl.setActionListener(an);
frame.getContentPane().add(rl);
frame.setVisible(true);
}
public ActionListener getActionListener() {
return privateActionListener;
}
public void setActionListener(ActionListener privateActionListener) {
this.privateActionListener = privateActionListener;
for(int i = 0; i < btns.length; i ++){
btns[i].addActionListener(privateActionListener);
}
}
}
class AnActionListener implements ActionListener{
public void actionPerformed(ActionEvent e){
JRadioButton jrb = (JRadioButton) e.getSource();
Integer id = (Integer) jrb.getClientProperty(RadioListener.id);
System.out.println("id " + id);
}
}