2

关于JavaDoc 中javax.swing.ListCellRenderer示例代码的快速问题:

我有点惊讶,在示例中,ListCellRenderer是由扩展的类实现的,JLabel并且getListCellRendererComponent(...)- 方法只是返回this。看起来JLabel周围只有一个 a 实例,即使对于包含多个元素的列表也是如此。

通常,我会期望当在setText(...)内部为列表中的第二项调用该方法时getListCellRendererComponent(...),它会更改列表中已经存在的第一项的标签。或者,实际上,列表可能甚至不可能使用相同的JLabel-instance 两次(或多次),列表中的每个项目一次。

现在,我想出了两种可能的方法来解决这个问题,并且想知道哪一种(如果有的话)实际上正在发生:

  • 是否以某种方式为每个列表项JList创建提供的新实例?ListCellRenderer
  • 或者它是否使用返回的组件getListCellRendererComponent(...)仅在列表的画布上调用其paint(...)方法,而不是实际将此组件添加到某个面板?
4

1 回答 1

3

JList渲染本身时,它会询问ListModel它应该显示的元素。对于它调用的每个元素javax.swing.ListCellRenderer来提供一个渲染组件。然后它绘制组件。就这样。渲染组件不绑定到它渲染的元素状态。

的 javadocListCellRenderer说:

标识可用作“橡皮图章”以在JList.

所以你的第二个假设是正确的。

一看javax.swing.plaf.BasicListUI就知道:

protected void paintCell(Graphics g, int row, Rectangle rowBounds,
        ListCellRenderer cellRenderer, ListModel dataModel,
        ListSelectionModel selModel, int leadIndex) {
    Object value = dataModel.getElementAt(row);
    boolean cellHasFocus = list.hasFocus() && (row == leadIndex);
    boolean isSelected = selModel.isSelectedIndex(row);

    Component rendererComponent = cellRenderer
            .getListCellRendererComponent(list, value, row, isSelected,
                    cellHasFocus);

    int cx = rowBounds.x;
    int cy = rowBounds.y;
    int cw = rowBounds.width;
    int ch = rowBounds.height;

    if (isFileList) {
        // Shrink renderer to preferred size. This is mostly used on Windows
        // where selection is only shown around the file name, instead of
        // across the whole list cell.
        int w = Math
                .min(cw, rendererComponent.getPreferredSize().width + 4);
        if (!isLeftToRight) {
            cx += (cw - w);
        }
        cw = w;
    }

    rendererPane.paintComponent(g, rendererComponent, list, cx, cy, cw, ch,
            true);
}
于 2013-07-26T12:37:46.617 回答