我需要一个 JTable,其中有一列作为 JCombobox。 JCombobox 编辑器已更新,以允许过滤 JCombobox 的内容。我找到了一些用于过滤 JCombobox 的答案和代码,它对于组合框效果很好,但是一旦我将它作为单元格编辑器添加到 JTable 列中,它就不能很好地工作。
以下是代码
import java.awt.BorderLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
public class FilterComboBox extends JComboBox<String> {
private ArrayList<String> entries;
public FilterComboBox(ArrayList<String> entries) {
DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) this.getModel();
model.addAll(entries);
model.insertElementAt("", 0);
model.setSelectedItem(model.getElementAt(0));
this.entries = entries;
this.setEditable(true);
final JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
System.out.println("Filtering the elements with " + textfield.getText());
comboFilter(textfield.getText());
}
});
}
public void comboFilter(String enteredText) {
if (!this.isPopupVisible()) {
System.out.println("Showing the popup");
this.showPopup();
}
System.out.println("Filtering the elements");
ArrayList<String> filterArray = new ArrayList<>();
for(String entry: this.entries){
if(entry.toLowerCase().indexOf(enteredText.toLowerCase()) >= 0){
filterArray.add(entry);
System.out.println(entry);
}
}
DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) this.getModel();
model.removeAllElements();
model.addAll(filterArray);
JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.setText(enteredText);
System.out.println("Filtering the elements: "+ this.isPopupVisible());
}
public static void main(String[] args) throws Exception {
ArrayList<String> entries = new ArrayList<>();
entries.add("Snowboarding");
entries.add("Knitting");
entries.add("Jane");
entries.add("Pool");
entries.add("None of the above");
entries.add("Rowing");
entries.add("Kathy");
JFrame frame = new JFrame("Adventure in Nepal - Combo Filter Test");
FilterComboBox acb = new FilterComboBox(entries);
JTable table1 = new JTable();
table1.setModel(new DefaultTableModel(new Object[][] {
{"", ""}, {"", ""}},(Object[])new String[] { "Text", "Text"}) {
Class<?>[] columnTypes = new Class[] { String.class, String.class };
boolean[] columnEditable = new boolean[] { true, true};
public Class<?> getColumnClass(int columnIndex) {
return this.columnTypes[columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return this.columnEditable[columnIndex];
}
});
table1.setAutoCreateRowSorter(true);
TableColumnModel cm = table1.getColumnModel();
cm.getColumn(0).setCellEditor(new DefaultCellEditor(new FilterComboBox(entries)));
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table1), BorderLayout.NORTH);
p.add(acb, BorderLayout.SOUTH);
frame.setContentPane(p);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setSize(500, 500);
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}
}
在上面的代码中,
acb
FilterComboBox 运行良好,但 table1
运行不佳。
基于一些强力调试,我发现
model.removeAllElements();
和 model.addAll(filterArray);
导致了问题,因为如果我删除它们,打印语句会指示正确的执行顺序。但这当然违背了这段代码的目的。
有人可以帮我让它工作吗?我怀疑组合框和 jtable 的关键事件以及在模型的
removeAllElements
和 addAll
函数调用上触发的内部事件处理不当。
使用 JTable 时,JComboBox 过滤似乎存在问题。
您可以尝试以下更改:
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JTextField;
public class FilterComboBox extends JComboBox<String> {
private ArrayList<String> entries;
public FilterComboBox(ArrayList<String> entries) {
super(new DefaultComboBoxModel<>(entries.toArray(new String[0])));
this.entries = entries;
this.setEditable(true);
final JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
comboFilter(textfield.getText());
}
});
}
public void comboFilter(String enteredText) {
if (!this.isPopupVisible()) {
this.showPopup();
}
ArrayList<String> filterArray = new ArrayList<>();
for (String entry : entries) {
if (entry.toLowerCase().contains(enteredText.toLowerCase())) {
filterArray.add(entry);
}
}
DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) this.getModel();
model.removeAllElements();
for (String entry : filterArray) {
model.addElement(entry);
}
JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.setText(enteredText);
}
}
对于主要方法:
public static void main(String[] args) throws Exception {
ArrayList<String> entries = new ArrayList<>();
entries.add("Snowboarding");
entries.add("Knitting");
entries.add("Jane");
entries.add("Pool");
entries.add("None of the above");
entries.add("Rowing");
entries.add("Kathy");
JFrame frame = new JFrame("Adventure in Nepal - Combo Filter Test");
FilterComboBox acb = new FilterComboBox(entries);
JTable table1 = new JTable();
table1.setModel(new DefaultTableModel(new Object[][] {
{"", ""}, {"", ""}}, new String[] { "Text", "Text" }) {
Class<?>[] columnTypes = new Class[] { String.class, String.class };
boolean[] columnEditable = new boolean[] { true, true };
public Class<?> getColumnClass(int columnIndex) {
return columnTypes[columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnEditable[columnIndex];
}
});
table1.setAutoCreateRowSorter(true);
TableColumnModel cm = table1.getColumnModel();
cm.getColumn(0).setCellEditor(new DefaultCellEditor(new FilterComboBox(entries)));
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table1), BorderLayout.CENTER);
p.add(acb, BorderLayout.SOUTH);
frame.setContentPane(p);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setSize(500, 500);
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}
}