Java 在Swing中修改组合框显示
我想修改(不可编辑)Java 在Swing中修改组合框显示,java,swing,jcombobox,Java,Swing,Jcombobox,我想修改(不可编辑)JComboBox的显示方式,使当前选择的条目在编辑字段(而不是下拉列表)中有一些额外的文本 大概是这样的: 我的第一个猜测是覆盖ComboBox的模型,以便getSelectedItem返回修改显示的包装器对象: petList.setModel(new ComboBoxModel() { private Object selected; public void setSelectedItem(Object anItem) { selec
JComboBox
的显示方式,使当前选择的条目在编辑字段(而不是下拉列表)中有一些额外的文本
大概是这样的:
我的第一个猜测是覆盖ComboBox的模型,以便getSelectedItem
返回修改显示的包装器对象:
petList.setModel(new ComboBoxModel() {
private Object selected;
public void setSelectedItem(Object anItem) {
selected = anItem;
}
public Object getSelectedItem() {
return new ActiveComboItem(selected);
}
// … The rest of the methods are straightforward.
});
其中,ActiveComboItem
如下所示:
static class ActiveComboItem {
private final Object item;
public ActiveComboItem(Object item) { this.item = item; }
@Override
public boolean equals(Object other) {
return item == null ? other == null : item.equals(other);
}
@Override
public String toString() { return String.format("Animal: %s", item); }
}
事实上,只要修改显示,这一点就行了。不幸的是,当前条目不再标记为活动:
(请注意缺少复选标记…或操作系统显示的选项。)
进一步检查表明,每次用户在框中选择新项时,都会调用模型的getElementAt
方法,索引为-1
。仅当使用修改后的选定项时,才会出现这种情况。当模型的getSelectedItem
方法返回不带包装器的普通对象时,所选项在下拉框中标记为选中,并且getElementAt
不使用参数-1
调用
显然,组合框依次比较每个项目与当前活动的项目,但是,尽管我重写了equals
方法,但它没有找到匹配项如何解决此问题?
(此问题的完整可编译代码)您需要提供自定义ListCellRenderer。以下工作:
final JComboBox animalCombo = new JComboBox(animals);
animalCombo.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(final JList list, Object value, final int index, final boolean isSelected,
final boolean cellHasFocus) {
if (index == -1) {
value = "Animal: " + value;
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
当其绘制的值不在下拉列表中时,索引为-1
作为将来的参考,当您只想更改Swing中的显示方式时,您永远不想修改支持模型。每个组件都有一个渲染器,通常您只需要稍微修改默认的渲染器。使用
图标创建JTextField
和JButton
,因为JButton
通过覆盖其方法isRollover()、isPressed()、isArmed()
不要从JComboBox
中提取Icon
,绘制自己的三角形,然后JButton
带有Icon
的将是外观
和本机操作系统
抵抗,以便更好地实现JButton#setRolloverIcon()
创建一个JPopup
或JWindow
,放在这里JScrollPane
,从model.isPressed()或isArmed显示此容器
现在你有两个选择
1) 创建包含JCheckBox
的JList
(从JCheckBox中删除矩形)
2) 或者在鼠标单击上实现并添加/删除图标
隐藏JPopup
或JWindow
自MouseListener
事件+1-不要修改模型以更改UI。相反,扩展渲染器以添加额外的片段。不幸的是,这不太管用。JComboBox在默认情况下似乎不使用DefaultListCellRenderer
:使用上述代码,当前选定项目的显示与正常渲染不同(至少在OS X上)/编辑:它是com.apple.laf.aquaComboxRender
。不过,这只需进行微小的修改即可工作。除了我的previos注释外:不要使用super.GetListCellRenderComponent
,而是在设置新的渲染器之前存储以前使用过的渲染器,并使用其实现。@Konrad:是的,在不同的外观中支持默认渲染器实际上是一个更好的主意。谢谢。非常感谢。谢谢康拉德·鲁道夫。我扩展了一个JComboBox以使用自定义渲染器,并花了数小时试图使combobox的背景看起来正确。没有提前保存渲染,我只是调用super.getListCellRenderComponent,在使用windows LaF时以白色背景结束。当你将LaF设置为windows时,即使是oracle的自定义combo演示也有一个白色背景,因为它不尊重UI LaF.ehhh。。。这个随机码和OPs问题有关,因为?仅供记录:ComboBoxModel的实现是无效的,因为它不会在上触发ListModelEventsetSelectedItem@kleopatra很高兴知道。FWIW,该代码只是一个最小的尝试,在使其正确之前,首先使其工作。不点火是行为不当的常见原因:-)
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
public class CheckList {
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create a list containing CheckListItem's
JList list = new JList(new CheckListItem[]{
new CheckListItem("apple"),
new CheckListItem("orange"),
new CheckListItem("mango"),
new CheckListItem("paw paw"),
new CheckListItem("banana")});
// Use a CheckListRenderer (see below) to renderer list cells
list.setCellRenderer(new CheckListRenderer());
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addMouseListener(new MouseAdapter() {// Add a mouse listener to handle changing selection
@Override
public void mouseClicked(MouseEvent event) {
JList list = (JList) event.getSource();
int index = list.locationToIndex(event.getPoint());// Get index of item clicked
CheckListItem item = (CheckListItem) list.getModel().getElementAt(index);
item.setSelected(!item.isSelected()); // Toggle selected state
list.repaint(list.getCellBounds(index, index));// Repaint cell
}
});
frame.getContentPane().add(new JScrollPane(list));
frame.pack();
frame.setVisible(true);
}
}
// Represents items in the list that can be selected
class CheckListItem {
private String label;
private boolean isSelected = false;
public CheckListItem(String label) {
this.label = label;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean isSelected) {
this.isSelected = isSelected;
}
@Override
public String toString() {
return label;
}
}
// Handles rendering cells in the list using a check box
class CheckListRenderer extends JCheckBox implements ListCellRenderer {
private static final long serialVersionUID = 1L;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) {
setEnabled(list.isEnabled());
setSelected(((CheckListItem) value).isSelected());
setFont(list.getFont());
setBackground(list.getBackground());
setForeground(list.getForeground());
setText(value.toString());
return this;
}
}