Search code examples
javaswingjtextfield

Fitting text to JTextField using


I have a JTextField textField and I have an arbitrary String string

I want the text field to display the string's end but cut off what it can't fit and use "..." in place of it. For example, if the string is "Hello How Are You Doing" then the text field may look something like

...re You Doing

Given textfield and string, how can I do this?

UPDATE: the reason I want to do this is because it's a file chooser so I want to display the end of the file with priority. Example, if the user selects to save at /Users/Name/Documents/Folder1/Folder2/Folder3/file.txt then I want to display the end and the rest that can't fit should be replaced with "..."

Here is where it's done:

JFileChooser chooser = new JFileChooser();
int response = chooser.showSaveDialog(this);
if(response == JFileChooser.APPROVE_OPTION) {
    File file = chooser.getSelectedFile();
    String string = file.getAbsolutePath();

    fileTextField.setText(/* here's where the code would go */);
}

Solution

  • The problem you will face is the fact that String#length doesn't match pixel width. You need to take into consideration the current font, the width of the component, the icon, icon spacing, insets, screen DPI.... :P

    enter image description here

    public class TrimPath {
    
        public static void main(String[] args) {
            new TrimPath();
        }
    
        public TrimPath() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException ex) {
                    } catch (InstantiationException ex) {
                    } catch (IllegalAccessException ex) {
                    } catch (UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
    
                    File path = new File("C:\\Users\\Default\\AppData\\Local\\Microsoft\\Windows\\GameExplorer");
                    TrimmedLabel label = new TrimmedLabel(path.getPath());
                    label.setIcon(FileSystemView.getFileSystemView().getSystemIcon(path));
    
                    frame.add(label);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TrimmedLabel extends JLabel {
    
            private String masterText;
    
            public TrimmedLabel(String text) {
                super(text);
            }
    
            @Override
            public void setText(String text) {
                if (masterText == null ? text != null : !masterText.equals(text)) {
                    masterText = text;
                    super.setText(text);
                }
            }
    
            @Override
            public String getText() {
    
                String text = getMasterText();
    
                if (text != null && text.length() > 0) {
                    int width = getWidth();
                    Icon icon = getIcon();
                    if (icon != null) {
                        width -= (icon.getIconWidth() + getIconTextGap());
                    }
                    FontMetrics fm = getFontMetrics(getFont());
                    if (width > 0 && fm != null) {
                        int strWidth = fm.stringWidth(text);
                        if (strWidth > width) {
                            StringBuilder sb = new StringBuilder(text);
                            String prefix = "...";
                            while (fm.stringWidth(prefix + sb.toString()) > width) {
                                sb.delete(0, 1);
                            }
                            text = prefix + sb.toString();
                        }
                    }
                }
                return text;
            }
    
            public String getMasterText() {
                return masterText;
            }
        }
    }