从使用ListCellRenderer的奥斯卡的想法工作,我已经提出了一些几乎工程...该组件值正确呈现,但列表的值需要一个丑陋的黑客。
因为对于列表项,渲染器的大小(来自getSize())反映的是最长项目的文本宽度,而不是可用于渲染值的空间宽度,所以需要hack。我尝试过使用JComboBox本身,但它的宽度包含了小小的下拉按钮,所以如果有一个滚动条存在,它的宽度将不被考虑。如果渲染器的宽度小于组合框的宽度,则使用存储宽度,如果渲染器的宽度大于组合框的宽度,则使用存储的宽度。渲染器的宽度介于内部JLabel的宽度和组合框的宽度之间时,会出现拐角情况。
由于渲染空间将是组合框的宽度,减少滚动条和插入的宽度,如果任何人有一个建议,我怎么能知道列表有一个滚动条,以及如何获得滚动条让我可以提取宽度,我都是耳朵。也许我可以做list.getParent()并期望它是一个JScrollPane(JComboBox或JList doco确实声明它使用滚动窗格)。
其他建议这样做更好的欢迎。
代码如下:
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);
}
}
我给一个旋转这个周末;假设它的工作原理,你介意我是否用渲染器代码编辑你的答案,然后接受它? – 2009-04-25 00:48:49