Java - 如何使非字符串对象的 JComboBox 显示字符串名称?

Posted

技术标签:

【中文标题】Java - 如何使非字符串对象的 JComboBox 显示字符串名称?【英文标题】:Java - How to make JComboBox of non-String objects display String names? 【发布时间】:2014-08-02 12:09:12 【问题描述】:

我想让JComboBox 组件显示String 名称,而不是引用。但是,我不知道这是怎么做到的。

下面显示了我的代码:

public class Properties extends JPanel implements ItemListener 
    private static final long serialVersionUID = -8555733808183623384L;
    private static final Dimension SIZE = new Dimension(130, 80);
    private JComboBox<Category> tileCategory;

    public Properties() 
        tileCategory = new JComboBox<Category>();
        tileCategory.setPreferredSize(SIZE);
        tileCategory.addItemListener(this);

        this.setLayout(new GridLayout(16, 1));
        loadCategory();
    

    private void loadCategory() 
        //Obtains a HashMap of Strings from somewhere else. All of this is constant, so they
        //aren't modified at runtime.
        HashMap<Integer, String> map = EditorConstants.getInstance().getCategoryList();

        DefaultComboBoxModel<Category> model = (DefaultComboBoxModel<Category>) this.tileCategory.getModel();
        for (int i = 0; i < map.size(); i++) 
            Category c = new Category();
            c.name = map.get(i + 1);
            model.addElement(c);
        
        this.add(tileCategory);
    

我唯一知道的是我将Category 类传递给JComboBox。下面显示了Category 类:

public class Category 
    public String name;

就是这样。

我唯一的目标是让Category.name 成员变量显示在JComboBox 下拉列表中,矩形在图片中标记。

谁能告诉我这是怎么做到的?提前致谢。

【问题讨论】:

【参考方案1】:

JComboBox 使用ListCellRenderer 允许您自定义值的呈现方式。

查看Providing a Custom Renderer了解更多详情

例如...

public class CategoryListCellRenderer extends DefaultListCellRenderer 

    @Override
    public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) 

        if (value instanceof Category) 
            value = ((Category)value).name;
        

        return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); //To change body of generated methods, choose Tools | Templates.

    


然后你只需指定组合框的渲染

tileCategory.setRenderer(new CategoryListCellRenderer());

现在,话虽如此,这将阻止用户使用内置搜索功能的组合框。

为此,请查看Combo Box With Custom Renderer 以了解可能的解决方法。这是由我们自己的 camickr 编写的

【讨论】:

你必须热爱盲目投票。它无法让人们学习或改进答案 我没有投反对票,但渲染器会破坏可访问性和剪贴板操作(以及,正如你提到的,键盘导航)。最好用自定义的toString方法做一个包装类。 @VGR 虽然我同意你的主要陈述,但可以修改可访问性和剪贴板操作,至于键盘操作,我们只是说 API 需要更好的设计,但要覆盖 toString 进行演示- 这可能是最糟糕的事情,因为在所有情况下对象不会总是以相同的方式呈现,toString 最好留给调试,但那是 MHO ;) 正确。这就是为什么我推荐一个自定义包装类(比如,CategoryItem),而不是修改 Category.toString。 @vgr 恕我直言,这是有限的,除非你突然将 html 注入到 toString 方法中:P【参考方案2】:

最简单的方法是覆盖类的toString() 方法。这不是一个非常强大的解决方案,但可以完成工作。

public class Category 
    public String name;

    @Override
    public String toString()
        return name;
    

【讨论】:

toString 是做出渲染决策的糟糕选择,您可能并不总是希望在各种组件中以相同的方式渲染值,这就是渲染器存在的原因。 toString 应仅限于提供调试信息 @MadProgrammer DefaultXxxRenderer 即将使用 toString(编辑)并允许 JList/JComboBox 中的两个相同(描述为)项目而没有索引问题(否则返回最近的索引) @mKorbel 但是仅仅为了演示目的而修改类的toString 方法是一个坏主意。同意,这是一个非常简单的类,但是如果它变得更复杂并且 OP 想要在这个组合框或那个列表中以不同的方式显示它......那么他们就会遇到问题,只是说...... 你是绝对正确的,这就是为什么我添加了关于它的评论。但这是完成 OP 想要的最快的方法。 @MadProgrammer 看到我对原始评论的编辑,我希望你知道这个问题

以上是关于Java - 如何使非字符串对象的 JComboBox 显示字符串名称?的主要内容,如果未能解决你的问题,请参考以下文章

如何使非类类型符合类协议?

如何通过 iOS 在应用程序购买中使非消耗性产品可用于多次购买?

使非客户区无效

Java求助:如何判断某对象是不是存在?如果不存在,创建该对象

java中如何将对象转成json格式字符串

如何将json字符串转成带有对象引用的java对象