I have a Swing app with multiple JCheckBoxes. Each JCheckBox
corresponds to another object of type Foo
have elsewhere in my program. For each object of type Foo
, I'll have one of these JCheckBoxes available for the user to click on (it tells the Foo object if they should display on the UI or not).
What I am currently doing is using the name attribute on JCheckBox
as a reference back to the string "name" of the Foo
object. I feel like a much cleaner solution would be to extend JCheckBox
to add an extra field to it, so that the JCheckBox
can keep track of which Foo object it's attached to by simply storing a reference to it. Thoughts? Do people regularly extend Swing components so that they can link the parts in the controller/view back to the model? Is there some horrible pitfall I'm going to run into?
It is hard to get the whole picture for this particular example without additional details. You may be able to accomplish this task using actions. See How to Use Actions for more details. Here is an example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.*;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class CheckBoxDemo {
static class Foo {
private boolean visible;
private String name;
public Foo(String name) {
this.name = name;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
System.out.println(getName() + ".setVisible:" + visible);
}
public String getName() {
return name;
}
}
static class FooAction extends AbstractAction {
private Foo foo;
public FooAction(Foo foo) {
super(foo.getName());
this.foo = foo;
}
@Override
public void actionPerformed(ActionEvent e) {
JCheckBox checkBox = (JCheckBox) e.getSource();
foo.setVisible(checkBox.isSelected());
}
}
private static void createAndShowGUI() {
List<Foo> fooList = new ArrayList<Foo>();
fooList.add(new Foo("Foo1"));
fooList.add(new Foo("Foo2"));
fooList.add(new Foo("Foo3"));
JPanel content = new JPanel(new BorderLayout());
JPanel fooPanel = new JPanel();
for (Foo foo : fooList) {
fooPanel.add(new JCheckBox(new FooAction(foo)));
}
content.add(fooPanel, BorderLayout.NORTH);
final JTextArea textArea = new JTextArea();
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setPreferredSize(new Dimension(200, 200));
content.add(scrollPane, BorderLayout.CENTER);
JFrame frame = new JFrame("CheckBoxDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(content);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
// just for brevity of example
System.setOut(new PrintStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
textArea.append(String.valueOf((char) b));
}
}));
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}