Работая над идеей Оскара об использовании ListCellRenderer, я придумал кое-что, что почти работает ... Значение компонента отображается правильно, но значения списка требуют ужасного взлома.
Требуется взлом, потому что для элементов списка размер средства визуализации (из getSize ()) отражает ширину текста самого длинного элемента, а не ширину пространства, доступного для визуализации значения. Я попытался использовать сам JComboBox, но его ширина включает в себя маленькую кнопку выпадающего меню, поэтому при наличии полосы прокрутки ее ширина не учитывается. Хак - сохранить ширину рендерера, если она меньше ширины поля со списком, и использовать сохраненную ширину, если ширина рендерера больше ширины поля со списком. Это угловой случай, когда ширина рендерера находится между внутренней JLabel и шириной поля со списком.
Так как пространство рендеринга будет шириной поля со списком, за вычетом ширины полосы прокрутки и вставок, если у кого-то есть предложение, как узнать, что в списке есть полоса прокрутки и как получить полосу прокрутки так что я могу извлечь ширину, я все уши. Может быть, я могу сделать list.getParent () и ожидать, что это будет JScrollPane (либо документ JComboBox, либо JList действительно заявляет, что использует панель прокрутки).
Другие предложения, чтобы сделать это лучше, приветствуются.
Код следует:
recentDirs.setRenderer(new ComboTextRenderer(recentDirs));
...
static private class ComboTextRenderer
extends DefaultListCellRenderer
implements SwingConstants
{
JComponent parent;
int renderWidth;
ComboTextRenderer(JComponent par) {
super();
parent=par;
renderWidth=-1;
}
public void paint(Graphics gc) {
String txt=getText();
int len=txt.length();
int wid=getSize().width;
Insets ins=getInsets();
FontMetrics met=gc.getFontMetrics();
if(renderWidth==-1 || wid<parent.getSize().width) { renderWidth=wid; }
else { wid=renderWidth; }
wid-=(ins.left+ins.right);
if(met.stringWidth(txt)>wid) {
String rpl=null;
for(int xa=0,pfx=Math.min(15,((len/2)-1)),sfx=(pfx+2); pfx>0 && sfx<len; xa++) {
rpl=(txt.substring(0,pfx)+" ... "+txt.substring(sfx));
if(met.stringWidth(rpl)<=wid) { break; }
rpl=null;
if ((len-sfx)>15) { sfx++; }
else if((xa%2)==0 ) { pfx--; }
else { sfx++; }
}
if(rpl!=null) { setText(rpl); }
}
super.paint(gc);
}
}