编辑1 :哎呀-看到@Andrew的屏幕截图,意识到这不能按预期工作,文本实际上比显示的要长(忽略了内部注释“
PENDING:不适用于JScrollPane中的JList” ;-)将挖出一个如果我无法尽快解决,请删除该答案。
编辑2 :知道了-如下所示的渲染器实现是可以的,罪魁祸首是JList,它偶尔会出现小于最佳大小的缓存。其中有两个部分
- BasicListUI没有考虑到调整列表大小可能需要清除内部大小(实际上是行高)缓存,应用程序代码必须强制这样做,例如在ComponentListener中
- list的tracksViewportWidth的Scrollable实现包含妨碍逻辑的逻辑(导致对该区域进行循环扩展,直到它成为单行为止),子类返回true。
使用以下渲染器的代码:
final JList list = new JList(model) { @Override public boolean getScrollableTracksViewportWidth() { return true; } }; list.setCellRenderer(new MyCellRenderer()); ComponentListener l = new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { // next line possible if list is of type JXList // list.invalidateCellSizeCache(); // for core: force cache invalidation by temporarily setting fixed height list.setFixedCellHeight(10); list.setFixedCellHeight(-1); } }; list.addComponentListener(l); add(new JScrollPane(list));第一个答案 (使用Jtextarea作为呈现组件的呈现器实现)
textarea在调整大小时有些棘手:需要将其初始化为合理的值:
public class MyCellRenderer implements ListCellRenderer { private JPanel p; private JPanel iconPanel; private JLabel l; private Jtextarea ta; public MyCellRenderer() { p = new JPanel(); p.setLayout(new BorderLayout()); // icon iconPanel = new JPanel(new BorderLayout()); l = new JLabel("icon"); // <-- this will be an icon instead of a // text iconPanel.add(l, BorderLayout.NORTH); p.add(iconPanel, BorderLayout.WEST); // text ta = new Jtextarea(); ta.setLineWrap(true); ta.setWrapStyleWord(true); p.add(ta, BorderLayout.CENTER); } @Override public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean hasFocus) { ta.setText((String) value); int width = list.getWidth(); // this is just to lure the ta's internal sizing mechanism into action if (width > 0) ta.setSize(width, Short.MAX_VALUE); return p; }}


