Java 文本小部件是否可以使用“溢出”显示溢出&引用;在正文的中间而不是结尾?

Java 文本小部件是否可以使用“溢出”显示溢出&引用;在正文的中间而不是结尾?,java,swing,widget,overflow,Java,Swing,Widget,Overflow,我有一个JComboBox,其中包含一个MRU列表组合框和一个用于目录树面板的组合框。两者一起构成了我的GUI的左侧面板(MRU位于树面板上方),它是一个JSplitPane,因此左侧面板可以调整大小 它有一个问题,目录文本的长度总是大于在树面板中查看该目录所需的宽度,因此我必须将左侧窗格的大小设置为比树所需的宽度大得多,以便阻止组合框显示截断的目录名 当文件名结尾被截断时,组合框不是很有用,但如果左窗格的宽度足以容纳文件名,则通常会使其在整个窗口中显得太宽,尤其是在未运行Maximize的情况

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

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

当文件名结尾被截断时,组合框不是很有用,但如果左窗格的宽度足以容纳文件名,则通常会使其在整个窗口中显得太宽,尤其是在未运行Maximize的情况下。通常只有文件名的尾随部分才是感兴趣的。如果我能让JComboBox以某种方式显示“开始…结束”而不是“开始…”,我的问题就会得到解决



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

mmHhh也许可以提供一个自定义渲染器

我想是listcell渲染器之类的

据我所知,默认情况是在没有足够可用空间时进行包装,通过创建/或修改渲染的单元,您可以知道组件可用宽度,并根据自己的意愿修改要渲染的文本

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


:)

根据奥斯卡提出的使用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);
    }
}
recentDirs.setRenderer(新的ComboTextRenderer(recentDirs));
...
静态私有类ComboTextRenderer
扩展DefaultListCellRenderer
实现SwingConstants
{
JComponent父代;
int renderWidth;
ComboTextRenderer(JComponent par){
超级();
父母=标准杆;
renderWidth=-1;
}
公共空间涂料(图形gc){
字符串txt=getText();
int len=txt.length();
int wid=getSize().width;
Insets-ins=getInsets();
FontMetrics-met=gc.getFontMetrics();
如果(渲染宽度==-1 | | widwid){
字符串rpl=null;

对于(int xa=0,pfx=Math.min(15,((len/2)-1)),sfx=(pfx+2);pfx>0&&sfxI将在本周末对此进行一次尝试;假设它有效,您介意我用呈现程序代码编辑您的答案,然后接受它吗?如果您使用JScrollPane,您可能会遇到问题:(Oscar,决定将该解决方案作为一个单独的自我答案发布,以便接受它,因此它会显示在答案的顶部,供未来寻找解决方案的观众观看;我投票支持你的答案,因为它使我走上了正确的轨道。