简体   繁体   中英

How can I display a short length version of a file name in java inside of a jlist

I have a JList that displays a filelist. The style I have it set to looks good with a FileFilter set to only show files and directories with names that are 15 characters long, however I still want to show the files that are longer than that, just show the first 15 characters or so. Basically, I want it to show this:

If I have a text file that says "1234567891234567.txt" - that has 20 characters including the ".txt" and it won't show up in the list. But I want it to show something like this:

"12345...567.txt" or something similar. Is there a way to do this?

Would I have to create a seperate array and copy everything over, and edit the value of the new array to be no longer than 15 characters? I tried looking for a function that would change the name of the file but I couldn't find any. Suggestions?

You can check the length of file name and abbreviate it if it contains more than 20 characters, like the method below:

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"));
}

Please note that it won't work if the extension itself is more than 20 characters or file name does not have any extension. However, you can modify it as per your requirement.

Coming up with an abbreviated string that will fit in a certain amount of space isn't as trivial as it may sound. Sure, you could just make sure your text is no longer than 15 characters, but all Swing look-and-feels assign a variable-width font to JLists. The system look-and-feel will use whatever font the underlying desktop uses for lists, which also is a variable-width font in all desktops I'm aware of.

Which means, the 20-character string IIIIIIIIIIIIIIII.txt and the 20-character string WWWWWWWWWWWWWWWW.txt are not the same width. Truncating each of them to fit in the JList's space will not be as simple as making them 15 characters long.

Fortunately, you can use a FontMetrics to calculate a string's visual size.

The simplest, though hardly most efficient, algorithm is to whittle down a string one character at a time until it fits in the JList's width:

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;
}

(Notice that “…” is not three period characters, but rather the ellipsis character . What's the difference? The ellipsis is kerned differently, justified differently, read by screen readers differently, can't be broken up by word-wrap, and is simply the correct punctuation. You wouldn't use two apostrophes to represent a double-quote.)

I naïvely start by replacing the center character in each string, regardless of the width of the characters on either side of that character, but a more intelligent and possibly more visually pleasing approach would be to use the character visually located at the center, using TextLayout.hitTestChar .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM