自定义单元格渲染器可以像窗体一样定义对象的属性吗?

时间:2016-07-16 23:19:03

标签: java swing jlist listcellrenderer

自定义单元格渲染器可以像窗体一样定义对象的属性吗?

我一直在寻找一种方法来定义JList的元素,以反映对象的当前状态,而不是简单地使用一串信息。即,而不是文字使用说明单选按钮,文本框和标签。以预先格式化的方式,如模板。

我需要在列表中显示的项目是移位的时间段,每个时间段表示开始和结束时间以及各种布尔属性。如果我可以使用组件来显示每个对象的状态,那么有人可以选择它会更好。选择后,编辑将在列表下完成,而不是在列表中。只是为了展示。

这样的事情:

http://i.stack.imgur.com/3MoeQ.png

1 个答案:

答案 0 :(得分:2)

如果您想要的只是渲染 JTable单元格内的swing组件,那么没问题:只需从单元格渲染器返回相关的JPanel实例。但是,如果您希望内容可以完全成熟,可能会遇到问题JPanel

问题基本上是这样的:JList(和JTable,供参考)使用从单元格渲染器返回的面板来渲染项目。渲染完成后,实例将被丢弃。这意味着您无法从外部更改从单元格渲染器返回的其中一个组件的状态,并希望它在表格中更新。

但是,在某些情况下你可以逃脱它,因为一旦用户点击一个单元格,列表就会进入编辑模式,此时用户正在编辑的单元格实际上包含了swing组件的实例,而不是只是渲染它们。

我发现使用自定义布局管理器来完成这样的任务会更好 - 甚至更简单。一个例子:

static class ListLayout implements LayoutManager {
    private final int myItemHeight;

    public ListLayout(int itemHeight) {
        myItemHeight = itemHeight;
    }

    @Override
    public void addLayoutComponent(String name, Component comp) {
    }

    @Override
    public void removeLayoutComponent(Component comp) {
    }

    public Dimension preferredLayoutSize(Container parent) {
        int h = 0;
        int w = 0;
        for (Component c : parent.getComponents()) {
            h += c.getPreferredSize().height;
            w = Math.max(w, c.getPreferredSize().width);
        }
        return new Dimension(w, h);
    } 

    public Dimension minimumLayoutSize(Container parent) {
        int w = 0;
        for (Component c : parent.getComponents()) {
            w = Math.max(w, c.getMinimumSize().width);
        }
        return new Dimension(w, 0);
    }

    public void layoutContainer(Container parent) {
        int y = 0;
        // Note: should really deal with parent's border insets here as well
        // Additionally, can add fields like padding, margin, etc. to make this
        // class more generally useful
        for (Component c : parent.getComponents()) {
             c.setBounds(0, y, parent.getWidth(), myItemHeight);
             y += myItemHeight;
        }
    }
}

调用代码:

    JFrame frame = new JFrame();
    JPanel content = new JPanel();
    content.setLayout(new ListLayout(25));
    JScrollPane scroll = new JScrollPane(content);

    for (int i = 0; i < 20; ++i) {
        content.add(new JButton(Integer.toString(i)));
    }

    frame.setContentPane(scroll);
    frame.pack();
    frame.setVisible(true);

当然,以这种方式这样做会失去JList的其他功能,例如选择hilighting等等,所以这一切都取决于你想要做什么。但是,上面将以类似列表的布局为您提供完全可交互的组件。