我有一个JComboBox,它包含一个MRU列表组合框和一个目录树面板。这两个组合在一起形成我的GUI的左侧面板(MRU位于树面板上方),这是一个JSplitPane,因此左侧面板可以调整大小。
它有一个问题,目录文本总是比在树面板中看到该目录所需的宽度长,所以我必须调整左侧窗格的大小比树所需的宽,以便停止显示截断目录名称的组合框。
对于截断文件名的结尾,组合框不是很有用,但是对于文件名来说,左窗格足够宽,这使得它对于整个窗口来说太过宽泛,尤其是。如果没有运行最大化。它通常只是文件名的尾部部分是有意义的。如果我只能以某种方式导致JComboBox 显示“开始...结束”而不是“开始......”我的问题就会解决。
Screen Shot http://www.freeimagehosting.net/uploads/da9810ed86.png
更新:我有一个有效的解决方案(请参阅下面的自我答案),但这并不完美。如果有人知道如何改进它,那将非常感激。
答案 0 :(得分:1)
mmHhh或许提供自定义渲染器?...
我认为它是listcell渲染器或类似的东西。
根据我的理解,当没有足够的可用空间时,默认被包装,通过创建/或修改渲染的单元格,您可以知道组件的可用宽度是什么,并修改要随意渲染的文本。
mmmhh我已经差不多接近那个API(细胞渲染的东西)几年了,所以我可能有点困惑。
:)
答案 1 :(得分:0)
根据Oscar使用ListCellRenderer的想法,我提出了几乎可行的东西......组件值被正确呈现,但列表的值需要一个丑陋的黑客。
需要进行黑客攻击,因为对于列表项,渲染器的大小(来自getSize())反映了最长项的文本宽度,而不是可用于渲染值的空间宽度。我尝试使用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);
}
}