I was checking the documentation.
... and I'm trying to use my Custom ComboBox implementing the interface ComboBoxEditor
.
Here my complete Code...
I hava one JPanel
with JComponents
...
class ThePanel extends JPanel {
private Font intFont = new Font("Monospaced", Font.PLAIN, 8);
private final JToggleButton jtbEnabled = new JToggleButton();
private final JToggleButton jtbDefaultOperation = new JToggleButton();
private final JTextField jtfText = new JTextField("", 0);
private final JPanel jpThePanel = new JPanel();
public ThePanel(Font extFont) {
this(new TheModel(), extFont);
}
public ThePanel(TheModel data, Font extFont) {
super();
intFont = extFont;
initEnabled();
initDefaultOperation();
initText();
setData(data);
jpThePanel.setLayout(new BoxLayout(jpThePanel, BoxLayout.LINE_AXIS));
jpThePanel.add(Box.createRigidArea(new Dimension(2, 0)));
jpThePanel.add(jtbEnabled);
jpThePanel.add(jtbDefaultOperation);
jpThePanel.add(jtfText);
jpThePanel.add(Box.createRigidArea(new Dimension(2, 0)));
init();
}
private void init() {
setFont(intFont);
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0/*64*/));
add(jpThePanel);
Dimension d = getMinimumSize();
setSize(d);
setPreferredSize(d);
setMaximumSize(d);
setSize(d);
}
private void initEnabled() {
jtbEnabled.setFont(intFont);
jtbEnabled.setIcon(new ImageIcon(getClass().getResource("Unselected.png")));
jtbEnabled.setSelectedIcon(new ImageIcon(getClass().getResource("Selected.png")));
}
private void initDefaultOperation() {
jtbDefaultOperation.setFont(intFont);
jtbDefaultOperation.setIcon(new ImageIcon(getClass().getResource("Insert.png")));
jtbDefaultOperation.setSelectedIcon(new ImageIcon(getClass().getResource("Extract.png")));
jtbDefaultOperation.setDisabledIcon(new ImageIcon(getClass().getResource("DisabledInsert.png")));
jtbDefaultOperation.setDisabledSelectedIcon(new ImageIcon(getClass().getResource("DisabledExtract.png")));
}
private void initText() {
jtfText.setFont(intFont);
}
public TheModel getData() {
return new TheModel(
jtbEnabled.isSelected(),
jtbDefaultOperation.isSelected(),
jtfText.getText()
);
}
public void setData(TheModel data) {
jtbEnabled.setSelected(data.getEnabled());
jtbDefaultOperation.setEnabled(data.getEnabled());
jtbDefaultOperation.setSelected(data.getDefaultOperation());
jtfText.setText(data.getText());
}
public void selectAll() {
jtfText.selectAll();
}
}
Now, I have the Model Data for its inner components...
class TheModel {
private Boolean enabled = true;
private Boolean defaultOperation = true;
private String text = "";
public TheModel() {
this("");
}
public TheModel(String text) {
this(true, text);
}
public TheModel(Boolean defaultOperation, String text) {
this(true, defaultOperation, text);
}
public TheModel(Boolean enabled, Boolean defaultOperation, String text) {
this.enabled = enabled;
this.defaultOperation = defaultOperation;
this.text = text;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public Boolean getDefaultOperation() {
return defaultOperation;
}
public void setDefaultOperation(Boolean defaultOperation) {
this.defaultOperation = defaultOperation;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@Override
public String toString() {
return "TheModel{" + "enabled=" + enabled + ", defaultOperation=" + defaultOperation + ", text=" + text + '}';
}
}
I want to use my Custom Component (ThePanel
) in a JComboBox
and manipulate the inner elements the JToggleButton
s and the JTextField
according to documentation... I need to implement the ComboBoxEditor
interface.
NOTE: The ListCellRenderer
interface was trying to show the list... because implementng only ComboBoxEditor
was not working.
class TheComboBoxEditor implements ComboBoxEditor, ListCellRenderer {
protected ThePanel editor;
private final EventListenerList listenerList = new EventListenerList();
public TheComboBoxEditor(Font extFont) {
editor = new ThePanel(extFont);
}
private void fireActionEvent(ActionEvent evt) {
for (ActionListener al : listenerList.getListeners(ActionListener.class)) {
al.actionPerformed(evt);
}
}
@Override
public void addActionListener(ActionListener l) {
listenerList.add(ActionListener.class, l);
}
@Override
public void removeActionListener(ActionListener l) {
listenerList.remove(ActionListener.class, l);
}
@Override
public void selectAll() {
editor.selectAll();
editor.requestFocus();
}
@Override
public Object getItem() {
return editor.getData();
}
@Override
public void setItem(Object anObject) {
if (anObject != null) {
if (anObject instanceof TheModel) {
editor.setData((TheModel) anObject);
}
if (anObject instanceof String) {
editor.setData(new TheModel(anObject.toString()));
}
} else {
editor.setData(new TheModel());
}
}
@Override
public Component getEditorComponent() {
return editor;
}
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
TheModel data = (TheModel) value;
editor.setData(data);
return editor;
}
}
Now, An Example of to use my TheComboBoxEditor
class.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class ExampleComboBoxEditor extends JFrame {
public ExampleComboBoxEditor() {
TheModel items[] = {
new TheModel(true, true, "True, True"),
new TheModel(true, false, "True, False"),
new TheModel(false, true, "False, True"),
new TheModel(false, false, "False, False")};
String strings[] = {
"True, True", "True, False", "False, True", "False, False"};
JComboBox internalComboBox = new JComboBox(items);
internalComboBox.setEditable(true);
internalComboBox.setEditor(new TheComboBoxEditor(this.getFont()));
internalComboBox.setMaximumRowCount(4);
internalComboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You chose " + ((JComboBox) e.getSource()).getSelectedItem() + "!");
}
});
JComboBox stringsComboBox = new JComboBox(strings);
stringsComboBox.setEditable(true);
stringsComboBox.setMaximumRowCount(4);
stringsComboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You chose " + ((JComboBox) e.getSource()).getSelectedItem() + "!");
}
});
JPanel outer = new JPanel();
outer.add(internalComboBox);
outer.add(stringsComboBox);
add(outer);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
ExampleComboBoxEditor app = new ExampleComboBoxEditor();
app.setSize(840, 240);
app.setVisible(true);
}
}
Now, I have my doubts (for me the objectives of these methods are not clear)...
1. When I override the selectAll()
method what I have to do?
2. I have not only One JTextField
component else two JToggleButton
too, then.
What are the recommendations for addActionListener(ActionListener l)
and removeActionListener(ActionListener l)
methods?
I was checking this example... http://www.java2s.com/Tutorials/Java/Swing_How_to/JComboBox/Add_JCheckBox_components_to_JComboBox.htm
As you can see, the List is shown...
Now, in my example...
3. I can't see my the list of my components displayed properly.
4. I can't edit my jtfText
, jtbEnabled
and jtbDefaultOperation
components (storing the state/property permanently).
EDIT
Based on aterai
's response, I change the Index porpouse preserving the original TheModel
class. Now, I want to know the down side.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
/*
//https://stackoverflow.com/posts/53046908/revisions
javac -Xlint:unchecked -Xlint:deprecation -encoding utf8 -d /Users/bz/Documentos/Java/classes /Users/jose/Documentos/Java/ExampleComboBoxEditorNOIndex.java
java -cp /Users/bz/Documentos/Java/classes ExampleComboBoxEditorNOIndex &
*/
public class ExampleComboBoxEditorNOIndex {
public Component makeUI() {
TheModel[] items = {
new TheModel(true, true, "00000"),
new TheModel(true, false, "11111"),
new TheModel(false, true, "22222"),
new TheModel(false, false, "33333")
};
JComboBox<TheModel> internalComboBox = new JComboBox<>();
internalComboBox.setModel(new InternalComboBoxModel<>(items));
internalComboBox.setEditable(true);
internalComboBox.setEditor(new TheComboBoxEditor(internalComboBox.getFont()));
internalComboBox.setRenderer(new TheComboBoxRenderer<>(internalComboBox.getFont()));
internalComboBox.setMaximumRowCount(4);
InternalComboBoxModel internalComboBoxModel = (InternalComboBoxModel)internalComboBox.getModel();
internalComboBox.addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
JComboBox combo = ((JComboBox) e.getSource());
int lastValidIndex = combo.getSelectedIndex();
if (lastValidIndex > -1) {
internalComboBoxModel.setLastValidIndex(lastValidIndex);
System.out.println("You chose " + combo.getSelectedItem()
+ ", in position:" + lastValidIndex + "!");
}
combo.getEditor().selectAll();
}
});
JPanel outer = new JPanel();
outer.add(internalComboBox);
outer.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
return outer;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new ExampleComboBoxEditorNOIndex().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class TheModel {
private Boolean enabled = true;
private Boolean defaultOperation = true;
private String text = "";
//public int index = -1;
public TheModel(/*int idx, */Boolean enabled, Boolean defaultOperation, String text) {
this.enabled = enabled;
this.defaultOperation = defaultOperation;
this.text = text;
//this.index = idx;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public Boolean getDefaultOperation() {
return defaultOperation;
}
public void setDefaultOperation(Boolean defaultOperation) {
this.defaultOperation = defaultOperation;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@Override
public String toString() {
return "TheModel{" + "enabled=" + enabled + ", defaultOperation=" + defaultOperation
+ ", text=" + text + '}';
}
}
class TheComboBoxRenderer<E extends TheModel> implements ListCellRenderer<E> {
protected ThePanel renderer;
private int lastSelected = -1;
public TheComboBoxRenderer(Font extFont) {
renderer = new ThePanel(new TheModel(/*-1, */false, false, ""), extFont);
}
@Override
public Component getListCellRendererComponent(JList<? extends E> list, E value,
int index, boolean isSelected, boolean cellHasFocus) {
if (isSelected) {
this.lastSelected = index;
//System.out.println("value: " + value + ", index: " + index + ", isSelected:" + isSelected);
}
renderer.setData(value);
renderer.setBackground(isSelected ? new Color(200, 200, 255) : Color.WHITE);
return renderer;
}
}
class TheComboBoxEditor implements ComboBoxEditor {
protected ThePanel editor;
public TheComboBoxEditor(Font extFont) {
super();
editor = new ThePanel(new TheModel(/*-1, */false, false, ""), extFont);
editor.setBorder(BorderFactory.createLineBorder(Color.GRAY));
}
@Override
public void selectAll() {
editor.selectAll();
// editor.requestFocus(); // <-- The focus moves from jtfText to editor.
}
@Override
public Object getItem() {
// System.out.println("getItem(): " + editor.getData());
return editor.getData();
}
@Override
public void setItem(Object anObject) {
// System.out.println("setItem: " + anObject);
if (anObject instanceof TheModel) {
TheModel d = (TheModel) anObject;
editor.setData(d);
} else {
editor.setData(new TheModel(/*-1, */false, false, ""));
}
}
@Override
public Component getEditorComponent() {
return editor;
}
@Override
public void addActionListener(ActionListener l) {
// System.out.println("TheComboBoxEditor.addActionListener: " + l.getClass().getName());
editor.addActionListener(l);
}
@Override
public void removeActionListener(ActionListener l) {
// System.out.println("TheComboBoxEditor.removeActionListener: " + l.getClass().getName());
editor.removeActionListener(l);
}
}
class ThePanel extends JPanel {
private Font intFont = new Font("Monospaced", Font.PLAIN, 8);
// Since there is no Unselected.png etc,
// use JCheckBox instead of JToggleButton instead.
public final JCheckBox jtbEnabled = new JCheckBox();
public final JCheckBox jtbDefaultOperation = new JCheckBox();
public final JTextField jtfText = new JTextField("", 10);
private TheModel data;
public ThePanel(TheModel data, Font extFont) {
super();
this.data = data;
setData(data);
jtbEnabled.addActionListener(e -> {
Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
if (c instanceof JComboBox) {
JComboBox<?> combo = (JComboBox<?>) c;
if (combo.getItemCount() > 0) {
InternalComboBoxModel internalComboBoxModel = (InternalComboBoxModel) combo.getModel();
int lastValidIndex = internalComboBoxModel.getLastValidIndex();
// TheModel o = (TheModel) combo.getSelectedItem();
// int idx = positionItemList(getComboBoxItems(combo), o);//int idx = model.getIndexOf(data);
TheModel rd = (TheModel) combo.getItemAt(lastValidIndex);//(TheModel) combo.getItemAt(idx);
boolean b = ((JCheckBox) e.getSource()).isSelected();
rd.setEnabled(b);
jtbDefaultOperation.setEnabled(b);
}
}
});
jtbEnabled.setOpaque(false);
jtbEnabled.setFocusable(false);
jtbDefaultOperation.addActionListener(e -> {
Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
if (c instanceof JComboBox) {
JComboBox<?> combo = (JComboBox<?>) c;
if (combo.getItemCount() > 0) {
InternalComboBoxModel internalComboBoxModel = (InternalComboBoxModel) combo.getModel();
int lastValidIndex = internalComboBoxModel.getLastValidIndex();
// TheModel o = (TheModel) combo.getSelectedItem();
// int idx = positionItemList(getComboBoxItems(combo), o);//int idx = model.getIndexOf(data);
TheModel rd = (TheModel) combo.getItemAt(lastValidIndex);//(TheModel) combo.getItemAt(idx);
rd.setDefaultOperation(((JCheckBox) e.getSource()).isSelected());
}
}
});
jtbDefaultOperation.setOpaque(false);
jtbDefaultOperation.setFocusable(false);
jtfText.addActionListener(e -> {
Container c = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
if (c instanceof JComboBox) {
JComboBox<?> combo = (JComboBox<?>) c;
if (combo.getItemCount() > 0) {
InternalComboBoxModel internalComboBoxModel = (InternalComboBoxModel) combo.getModel();
int lastValidIndex = internalComboBoxModel.getLastValidIndex();
// TheModel o = (TheModel) combo.getSelectedItem();
// int idx = positionItemList(getComboBoxItems(combo), o);//int idx = model.getIndexOf(data);
TheModel rd = (TheModel) combo.getItemAt(lastValidIndex);//(TheModel) combo.getItemAt(idx);
rd.setText(((JTextField) e.getSource()).getText());
}
}
});
jtfText.setBorder(BorderFactory.createEmptyBorder());
jtfText.setOpaque(false);
setOpaque(true);
setBackground(Color.WHITE);
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
add(Box.createRigidArea(new Dimension(2, 0)));
add(jtbEnabled);
add(jtbDefaultOperation);
add(jtfText);
add(Box.createRigidArea(new Dimension(2, 0)));
}
private <T> java.util.List<T> getComboBoxItems(JComboBox comboBox) {
if (comboBox != null) {
java.util.List<String> list = new ArrayList<>();
for (int i = 0; i < comboBox.getItemCount(); i++) {
list.add(comboBox.getItemAt(i).toString());
}
return (java.util.List<T>) list;//(ArrayList<T>)list; // list; // (List<T>)list;
}
return null;
}
private Integer positionItemList(java.util.List list, Object object) {
Integer position = -1;
Integer last = list.size();
for (int pos = 0; pos < last; pos++) {
if (list.get(pos).toString().equals(object.toString())) {
position = pos;
}
}
return position;
}
public TheModel getData() {
return new TheModel(
//data.index,
jtbEnabled.isSelected(),
jtbDefaultOperation.isSelected(),
jtfText.getText());
}
public void setData(TheModel data) {
//this.data.index = data.index;
jtbEnabled.setSelected(data.getEnabled());
jtbDefaultOperation.setEnabled(data.getEnabled());
jtbDefaultOperation.setSelected(data.getDefaultOperation());
jtfText.setText(data.getText());
}
public void selectAll() {
jtfText.requestFocusInWindow();
jtfText.selectAll();
}
public void addActionListener(ActionListener l) {
jtfText.addActionListener(l);
jtbEnabled.addActionListener(l);
jtbDefaultOperation.addActionListener(l);
}
public void removeActionListener(ActionListener l) {
jtfText.removeActionListener(l);
jtbEnabled.removeActionListener(l);
jtbDefaultOperation.removeActionListener(l);
}
}
class InternalComboBoxModel<E extends TheModel> extends DefaultComboBoxModel {
private Integer lastValidIndex = 0;
InternalComboBoxModel(final E items[]) {
super(items);
}
InternalComboBoxModel(Vector<E> v) {
super(v);
}
public Integer getLastValidIndex() {
return lastValidIndex;
}
public void setLastValidIndex(Integer lastValidIndex) {
this.lastValidIndex = lastValidIndex;
}
}
And I want to solve all warnings if is it possible.
MacBook-Air:Users bz$ javac -Xlint:unchecked -Xlint:deprecation -encoding utf8 -d /Users/bz/Documentos/Java/classes /Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java
/Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java:24: warning: [unchecked] unchecked method invocation: method setModel in class JComboBox is applied to given types
internalComboBox.setModel(new InternalComboBoxModel<>(items));
^
required: ComboBoxModel<E>
found: InternalComboBoxModel<TheModel>
where E is a type-variable:
E extends Object declared in class JComboBox
/Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java:24: warning: [unchecked] unchecked conversion
internalComboBox.setModel(new InternalComboBoxModel<>(items));
^
required: ComboBoxModel<E>
found: InternalComboBoxModel<TheModel>
where E is a type-variable:
E extends Object declared in class JComboBox
/Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java:257: warning: [unchecked] unchecked cast
return (java.util.List<T>) list;//(ArrayList<T>)list; // list; // (List<T>)list;
^
required: List<T>
found: List<String>
where T is a type-variable:
T extends Object declared in method <T>getComboBoxItems(JComboBox)
/Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java:310: warning: [unchecked] unchecked call to DefaultComboBoxModel(E[]) as a member of the raw type DefaultComboBoxModel
super(items);
^
where E is a type-variable:
E extends Object declared in class DefaultComboBoxModel
/Users/bz/Documentos/Java/ExampleComboBoxEditorNOIndex.java:314: warning: [unchecked] unchecked call to DefaultComboBoxModel(Vector<E>) as a member of the raw type DefaultComboBoxModel
super(v);
^
where E is a type-variable:
E extends Object declared in class DefaultComboBoxModel
5 warnings
MacBook-Air:Users bz$
You need to add a cell renderer.
Need to add an action listener to each component of the combo editor.
Do not move the focus to the TheComboBoxEditor.
ExampleComboBoxEditor3.java
ExampleComboBoxEditor4.java