如何在jlist中的java中显示文件名的短长度版本

时间:2017-03-03 20:25:10

标签: java file substring jlist

我有一个显示文件列表的JList。我设置的样式看起来很好,FileFilter设置为只显示名称长度为15个字符的文件和目录,但是我仍然想要显示比这长的文件,只显示前15个字符左右。基本上,我希望它能够证明这一点:

如果我有一个文字文件说" 1234567891234567.txt" - 有20个字符,包括" .txt"它不会出现在列表中。但是我想让它显示出类似的东西:

" 12345 ... 567.txt"或类似的东西。有没有办法做到这一点?

我是否必须创建一个单独的数组并将所有内容复制过来,并将新数组的值编辑为不超过15个字符?我试着寻找一个可以改变文件名的功能,但我找不到任何功能。建议?

2 个答案:

答案 0 :(得分:2)

您可以检查文件名的长度,如果文件名包含超过20个字符,请将其缩写,如下面的方法:

private static String getShortName(String fileName){
    if(fileName.length() <= 20){
        return fileName;
    }
    String extension = fileName.substring(fileName.lastIndexOf("."));
    String name = fileName.substring(0, fileName.lastIndexOf("."));
    return name.substring(0, 5) + "..." + name.substring(name.length() - 4) + extension;
}

public static void main(String[] args) throws Exception {
    System.out.println(getShortName("123.txt"));
    System.out.println(getShortName("123rewe.txt"));
    System.out.println(getShortName("123fdsfdsfdasfadsfdsgafgaf.txt"));
}

请注意,如果扩展名本身超过20个字符或文件名没有任何扩展名,则无效。但是,您可以根据自己的要求进行修改。

答案 1 :(得分:0)

提出一个适合一定数量空间的缩写字符串并不像听起来那么微不足道。当然,你可以确保你的文本不超过15个字符,但所有Swing外观都为JLists分配了一个可变宽度的字体。系统外观将使用底层桌面用于列表的任何字体,这也是我所知道的所有桌面中的可变宽度字体。

这意味着,20个字符的字符串IIIIIIIIIIIIIIII.txt和20个字符的字符串WWWWWWWWWWWWWWWW.txt的宽度不同。截断它们以适应JList的空间并不像使它们长15个字符那么简单。

幸运的是,您可以使用FontMetrics来计算字符串的可视大小。

最简单但最不高效的算法是一次减少一个字符串,直到它符合JList的宽度:

static <T> JList<T> createList(Collection<T> items) {
    JList<T> list = new JList<T>(new Vector<T>(items)) {
        private static final long serialVersionUID = 1;

        @Override
        public boolean getScrollableTracksViewportWidth() {
            return true;
        }
    };

    list.setCellRenderer(new DefaultListCellRenderer() {
        private static final long serialVersionUID = 1;

        private Insets insets = new Insets(0, 0, 0, 0);

        @Override
        public Component getListCellRendererComponent(JList<?> list,
                                                      Object value,
                                                      int index,
                                                      boolean selected,
                                                      boolean focused) {
            insets = list.getInsets(insets);
            int listWidth =
                list.getWidth() - insets.left - insets.right - 4;

            if (listWidth > 0 &&
                value != null &&
                !(value instanceof Icon)) {

                FontMetrics metrics = list.getFontMetrics(list.getFont());
                Graphics g = list.getGraphics();

                String text = value.toString();
                while (text.length() > 1 &&
                  metrics.getStringBounds(text, g).getWidth() > listWidth) {

                    int midpoint = text.length() / 2;
                    if (text.charAt(midpoint) != '\u2026') {
                        // Replace center character with ellipsis.
                        text = text.substring(0, midpoint) + '\u2026'
                            + text.substring(midpoint + 1);
                    } else {
                        // Remove character before or after ellipsis.
                        if (text.length() % 2 == 0) {
                            midpoint--;
                        } else {
                            midpoint++;
                        }
                        text = text.substring(0, midpoint)
                            + text.substring(midpoint + 1);
                    }
                }

                value = text;
                g.dispose();
            }

            return super.getListCellRendererComponent(list, value, index,
                selected, focused);
        }

    });

    return list;
}

(请注意,“...”不是三个句点字符,而是ellipsis character。有什么区别?省略号是不同的,有不同的辩解,屏幕阅读器读取不同,不能被分解自动换行,只是正确的标点符号。你不会用两个撇号来表示双引号。)

我天真地开始替换每个字符串中的中心字符,无论该字符两边的字符宽度如何,但更智能,可能更令人愉悦的方法是使用字符 visual < / em>位于中心,使用TextLayout.hitTestChar