Редактировать 1 : упс - увидев скриншот @ Эндрю, понял, что это работает не так, как ожидалось, текст на самом деле длиннее, чем показано с этим (упущен внутренний комментарий "В ОЖИДАНИИ: не работает для JList в JScrollPane ";-) Немного покопаю и удаляю этот ответ, если я не смогу заставить его работать в ближайшее время.
Редактировать 2 : получил - реализация рендерера, как показано ниже, в порядке, виновником является JList с случайным кэшированием менее оптимального размера. Есть две части этого
- BasicListUI не учитывает, что для изменения размера списка может потребоваться очистка кэша внутреннего размера (фактически высоты строки), код приложения должен принудительно сделать это, например. в ComponentListener
- реализуемая в списке прокручиваемая реализация trackViewportWidth содержит логику, которая стоит на пути (приводит к циклическому растяжению области до одной строки), подкласс для возврата true.
Код, который использует рендерер ниже:
final JList list = new JList(model) {
/**
* @inherited <p>
*/
@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;
}
}