JTable 中可编辑 JComboBox 的占位符
Placeholder for editable JComboBox in JTable
我有一个 JTable
,其中一列(第 1 列)是一个 JComboBox,它允许从列表中创建选项,并且可以向其中输入新选项。 MWE:
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.HashSet;
public class ComboTableDemo extends JPanel {
public ComboTableDemo() {
super(new GridLayout(1,0));
final String[] headings = {"Name", "Option"};
final String string1 = "Foo";
final String string2 = "Bar";
Object[][] data = {
{"Albert", string1},
{"Bob", null},
{"Clare", null},
{"David", null}
};
final JTable table = new JTable(data, headings);
table.setPreferredScrollableViewportSize(new Dimension(300, 100));
table.setFillsViewportHeight(true);
final String[] optionsInit = new String[] {string1, string2};
HashSet<String> options = new HashSet<String>(Arrays.asList(optionsInit));
JComboBox<String> optionsCombo = new JComboBox<String>(optionsInit);
optionsCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ev) {
String newSelection = (String)optionsCombo.getSelectedItem();
if(!options.contains(newSelection)) {
options.add(newSelection);
optionsCombo.addItem(newSelection);
}
}
});
optionsCombo.setEditable(true);
TableColumn column = table.getColumnModel().getColumn(1);
column.setCellEditor(new DefaultCellEditor(optionsCombo));
add(new JScrollPane(table));
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("ComboTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ComboTableDemo pane = new ComboTableDemo();
pane.setOpaque(true);
frame.setContentPane(pane);
frame.pack();
frame.setVisible(true);
}
});
}
}
在 table 中,用户可以并且应该为空条目输入值并不明显,因此我想包含占位符文本以明确这一点。我已经看到 elsewhere that a custom ListCellRenderer
can be provided with setRenderer
in the case of uneditable combos, but in the case of editable combos (as explained in the tutorial) 似乎必须使用 setEditor
提供 ComboBoxEditor
。是否有一个简单的实现,或者更好的方法来达到同样的目的?
实际上,JTable
中的输入组件是一种特殊情况,因为它们仅在编辑单元格时处于活动状态。因此,除了设置编辑器以控制值的编辑方式外,您还需要更改渲染器以控制所选值的呈现方式,
// As before:
TableColumn column = table.getColumnModel().getColumn(1);
column.setCellEditor(new DefaultCellEditor(optionsCombo));
// Additional line to set renderer:
column.setCellRenderer(new PlaceholderRenderer("<choose or add option>"));
这里的 PlaceholderRenderer
应该是一个 TableCellRenderer
实现,当没有选择任何值时显示占位符字符串。例如:
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
public class PlaceholderRenderer extends DefaultTableCellRenderer {
final private String placeholder;
public PlaceholderRenderer(String placeholder) {
super();
this.placeholder = placeholder;
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
if ((value == null) || (value.equals(""))) {
return super.getTableCellRendererComponent(table, this.placeholder, isSelected, hasFocus, row, column);
} else {
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}
我有一个 JTable
,其中一列(第 1 列)是一个 JComboBox,它允许从列表中创建选项,并且可以向其中输入新选项。 MWE:
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableColumn;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.HashSet;
public class ComboTableDemo extends JPanel {
public ComboTableDemo() {
super(new GridLayout(1,0));
final String[] headings = {"Name", "Option"};
final String string1 = "Foo";
final String string2 = "Bar";
Object[][] data = {
{"Albert", string1},
{"Bob", null},
{"Clare", null},
{"David", null}
};
final JTable table = new JTable(data, headings);
table.setPreferredScrollableViewportSize(new Dimension(300, 100));
table.setFillsViewportHeight(true);
final String[] optionsInit = new String[] {string1, string2};
HashSet<String> options = new HashSet<String>(Arrays.asList(optionsInit));
JComboBox<String> optionsCombo = new JComboBox<String>(optionsInit);
optionsCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ev) {
String newSelection = (String)optionsCombo.getSelectedItem();
if(!options.contains(newSelection)) {
options.add(newSelection);
optionsCombo.addItem(newSelection);
}
}
});
optionsCombo.setEditable(true);
TableColumn column = table.getColumnModel().getColumn(1);
column.setCellEditor(new DefaultCellEditor(optionsCombo));
add(new JScrollPane(table));
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("ComboTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ComboTableDemo pane = new ComboTableDemo();
pane.setOpaque(true);
frame.setContentPane(pane);
frame.pack();
frame.setVisible(true);
}
});
}
}
在 table 中,用户可以并且应该为空条目输入值并不明显,因此我想包含占位符文本以明确这一点。我已经看到 elsewhere that a custom ListCellRenderer
can be provided with setRenderer
in the case of uneditable combos, but in the case of editable combos (as explained in the tutorial) 似乎必须使用 setEditor
提供 ComboBoxEditor
。是否有一个简单的实现,或者更好的方法来达到同样的目的?
实际上,JTable
中的输入组件是一种特殊情况,因为它们仅在编辑单元格时处于活动状态。因此,除了设置编辑器以控制值的编辑方式外,您还需要更改渲染器以控制所选值的呈现方式,
// As before:
TableColumn column = table.getColumnModel().getColumn(1);
column.setCellEditor(new DefaultCellEditor(optionsCombo));
// Additional line to set renderer:
column.setCellRenderer(new PlaceholderRenderer("<choose or add option>"));
这里的 PlaceholderRenderer
应该是一个 TableCellRenderer
实现,当没有选择任何值时显示占位符字符串。例如:
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
public class PlaceholderRenderer extends DefaultTableCellRenderer {
final private String placeholder;
public PlaceholderRenderer(String placeholder) {
super();
this.placeholder = placeholder;
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
if ((value == null) || (value.equals(""))) {
return super.getTableCellRendererComponent(table, this.placeholder, isSelected, hasFocus, row, column);
} else {
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}