Edit 1: oops - seeing @Andrew's screenshot, realized that this isn't working as expected, the text is actually longer than shown with this (overlooked an internal comment "PENDING: not working for JList in JScrollPane" ;-) Will dig a bit and delete this answer if I can't make it work soon.
Edit 2: got it - the renderer implementation as shown below is okay, the culprit is the JList with its occasional less than optimal size caching. There are two parts of that
- BasicListUI doesn't take into account that resizing the list might require clearing the internal size (actually row height) cache, application code must force it to do so, f.i. in a ComponentListener
- list's Scrollable implementation of tracksViewportWidth contains logic which stands in the way (leads to looping stretch-out of the area until it's a single line), subclass to return true.
Code that uses the renderer below:
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));
First answer (a renderer implementation which uses JTextArea as rendering component)
TextArea is a bit tricky in sizing: it needs to get initialized to something reasonable:
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;
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…