【问题标题】:Java Swing: Set member which is displayed in JListBoxJava Swing:在JListBox中显示的集合成员
【发布时间】:2011-01-16 05:30:40
【问题描述】:

对于 JListBox Swing 组件,是否有与 .NET “set DisplayMember”类似的机制?

重写toString() 方法是不够的,因为我还希望能够在运行时更改显示成员。

我也考虑实现自己的ListCellRenderer,但发现它不是很方便。

有没有更简单或更优雅的方法?

感谢您的宝贵时间。

【问题讨论】:

  • 覆盖 toString() 或提供自定义渲染器是自定义显示的两种常用方法。我看不出你对这两种方法的担忧是什么。发布您的sscce.org,说明您在使用这两种方法时遇到的问题。
  • 谢谢,您已经帮我说没有其他常用方法了。我提出了一个基于实现自定义 ListCellRenderer 的令人满意的解决方案。

标签: java swing listbox cellrenderer


【解决方案1】:

您应该围绕您的业务对象创建一个覆盖 toString() 的包装类。这样您就可以保持自己的对象干净,并且可以在运行时交换包装器。

public class MyWrapper()
{
    private MyBusinessObject object;

    public String toString()
    {
        return object.getImportantString();
    }
}

【讨论】:

  • 嘿,我也想过这样的事情。这样做的问题是,您的 ListModel 必须包含包装对象而不是纯域对象。因此,当您想在运行时更改显示的成员时,您必须创建一大堆新的包装器。另外,您必须定义包装类,这会给您留下许多不是特别有用的类。
【解决方案2】:

基于实现自定义ListCellRenderer,我想出了一个令人满意的解决方案。

import java.awt.Component;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JList;
import javax.swing.ListCellRenderer;

public class DynamicCellRenderer implements ListCellRenderer {
    private final ListCellRenderer listCellRenderer;
    private String displayMember;

    public DynamicCellRenderer(String displayMember) {
        this(displayMember, new DefaultListCellRenderer());
    }

    public DynamicCellRenderer(String displayMember, ListCellRenderer wrapped) {
        listCellRenderer = wrapped;
        this.displayMember = displayMember;
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        Object displayMemberValue = getDisplayMemberValue(value);
        return listCellRenderer.getListCellRendererComponent(list, displayMemberValue, index, isSelected, cellHasFocus);
    }

    private Object getDisplayMemberValue(Object value) {
        // value is the domain class
        // only works if display member is a method, TODO: fallback to field
        // displayMember is something like "getName" -> value.getName() gets called
        try {
            return value.getClass().getMethod(displayMember).invoke(value);
        } catch (Exception ex) {
            // if anything went wrong it is the programmers fault -> propagate exception
            throw new RuntimeException(ex);
        }
    }

    public String getDisplayMember() {
        return displayMember;
    }

    public void setDisplayMember(String displayMember) {
        this.displayMember = displayMember;
    }

}

在您的客户端 GUI 代码中,您可以执行以下操作:

jListBox1.setCellRenderer(new DynamicCellRenderer("getName"));
...
...
// and later at some point
((DynamicCellRenderer) jListBox1.getCellRenderer()).setDisplayMember("getEmail");

【讨论】:

  • 我还建议在方法更改时存储该方法,而不是在每次重新渲染时调用 value.getClass().getMethod(displayMember)。方法没变就不用找方法了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多