Basically, there are two aspects to the problem, both of which are located in the delegate ui
- he cannot adjust the rendering to its real state during measurement, that is, completely ignores the choice (and focus).
- It is often stubborn from being forced to recalculate the sizes of cached cells: it does not have a public api to do this and only voluntarily change the model.
The first remedy is really a visualization tool: implement to ignore the selected flag and request a list for real selection, as described by @Andy. In code using OP components
ListCellRenderer renderer = new ListCellRenderer() { Yeah yeah = new Yeah(false); Oh oh = new Oh(); @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
To fix the second, a user delegate ui might be selected (as suggested in other answers). Although some work in the general case, if support for multiple LAFs is needed.
A less intrusive but slightly dirty method to force ui to voluntarily update its cache is to send a fake ListDataEvent to selectionChange:
ListSelectionListener l = new ListSelectionListener() { ListDataEvent fake = new ListDataEvent(list, ListDataEvent.CONTENTS_CHANGED, -1, -1); @Override public void valueChanged(ListSelectionEvent e) { JList list = (JList) e.getSource(); ListDataListener[] listeners = ((AbstractListModel) list.getModel()) .getListDataListeners(); for (ListDataListener l : listeners) { if (l.getClass().getName().contains("ListUI")) { l.contentsChanged(fake); break; } } } }; list.addListSelectionListener(l);
BTW, the JXList of the SwingX project has a user ui delegate - mainly to support sorting / filtering - using the public api to recount the cache, then the ListSelectionListener above will be simplified (and cleared :-) to
ListSelectionListener l = new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { ((JXList) e.getSource()).invalidateCellSizeCache(); } }; list.addListSelectionListener(l);
source share