0

我有一个 JComboBox ,其中包含一个 MRU 列表组合框和一个目录树面板。两者一起构成了我的 GUI 的左侧面板(MRU 在树面板上方),它是一个 JSplitPane,因此左侧面板是可调整大小的。

它有一个问题,目录文本总是比在树面板中查看该目录所需的宽度长,因此我必须将左侧窗格的大小设置为比树所需的宽得多才能停止组合-框中显示了一个截断的目录名称。

组合框在文件名的结尾被截断时不是很有用,但是使左窗格足够宽以容纳文件名通常会使其对于整个窗口(尤其是)来说太宽了。如果没有最大化运行。而且通常只有文件名的尾随部分才是有意义的。如果我只能让 JComboBox 以某种方式显示“开始...结束”而不是“开始...”,我的问题就会得到解决。

屏幕截图 http://www.freeimagehosting.net/uploads/da9810ed86.png


更新:我有一个可行的解决方案(见下面的自我回答),但它并不完美。如果有人知道我可以如何改进它,那将不胜感激。

4

2 回答 2

1

mmHhh 也许提供自定义渲染器?...

我认为它是 listcell 渲染器或类似的东西。

据我了解,当没有足够的可用空间时,默认会被包装,通过创建/或修改呈现的单元格,您可以知道组件的可用宽度是多少,并根据您的意愿修改要呈现的文本。

嗯,我已经好几年没有接近那个 API(细胞渲染的东西)了,所以我可能有点困惑。

:)

于 2009-04-25T00:41:19.673 回答
0

根据 Oscar 使用 ListCellRenderer 的想法,我想出了一些几乎可以工作的东西......组件值被正确呈现,但列表的值需要一个丑陋的 hack。

之所以需要 hack,是因为对于列表项,渲染器的大小(来自 getSize())反映了最长项的文本宽度,而不是可用于渲染值的空间的宽度。我尝试使用 JComboBox 本身,但它的宽度包括小下拉按钮,因此如果存在滚动条,则不考虑其宽度。hack 是如果渲染器的宽度小于组合框的宽度,则存储渲染器的宽度,如果渲染器的宽度大于组合框的宽度,则使用存储的宽度。这有一个极端情况,其中渲染器的宽度介于内部 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-25T08:01:19.680 回答