I am using a JPanel with some JLabels and JTextFields as editor and renderer in a JTree.
The user can click on any JTextField and modify the text. All works fine.
All I am missing is how I can dynamically resize (grow) the JTextField as the user is typing.
Below a small sample program that illustrates the problem. Click on i.e. "colors" and enter some additional characters. The JTextField keeps its size, which is expected, but I would like it to grow and shrink to accommodate the text.
I tried different layout managers, calculate the preferredSize of the JTextField and the JPanel, call invalidate() and the JPanel and the Tree and so on, without success.
Any ideas?
import java.awt.Component;
import java.util.EventObject;
import javax.swing.AbstractCellEditor;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.tree.TreeCellEditor;
import javax.swing.tree.TreeCellRenderer;
public class Tree {
    public static void main(final String[] args) {
        new Tree().grow();
    }
    private void grow() {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTree tree = new JTree();
        tree.setEditable(true);
        tree.setCellRenderer(new SomeTreeCellRenderer());
        tree.setCellEditor(new SomeTreeCellRenderer());
        frame.add(new JScrollPane(tree));
        frame.pack();
        frame.setSize(400, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    private class SomeTreeCellRenderer extends AbstractCellEditor implements 
            TreeCellRenderer, TreeCellEditor {
        @Override
        public Object getCellEditorValue() {
            return null;
        }
        @Override
        public boolean isCellEditable(final EventObject event) {
            return true;
        }
        @Override
        public Component getTreeCellRendererComponent(
                final JTree tree, final Object value, final boolean selected, final boolean expanded, 
                final boolean leaf, final int row, final boolean hasFocus) {
            final JPanel panel = new JPanel();
            final BoxLayout layout = new BoxLayout(panel, BoxLayout.X_AXIS);
            panel.setLayout(layout);
            panel.add(new JLabel("Some text: "));
            panel.add(new JTextArea(String.valueOf(value)));
            return panel;
        }
        @Override
        public Component getTreeCellEditorComponent(
                final JTree tree, final Object value, final boolean isSelected,
                final boolean expanded, final boolean leaf, final int row) {
            return getTreeCellRendererComponent(tree, value, isSelected, expanded, leaf, row, false);
        }
    }
}
                What's happening is that the container owning your panel doesn't have a layout manager assigned to it - so the panel is not resizing when the text area is resizing.  A simple fix to this would be to set the size of the panel whenever your text area resizes.  So instead of directly doing this:
        panel.add(new JTextArea(String.valueOf(value)));
You can do this:
        JTextArea ta = new JTextArea(String.valueOf(value));
        ta.addComponentListener(new ComponentListener() {
            @Override
            public void componentResized(ComponentEvent e) {
                panel.setSize(panel.getPreferredSize());
            }
            @Override
            public void componentShown(ComponentEvent e) {}
            @Override
            public void componentMoved(ComponentEvent e) {}
            @Override
            public void componentHidden(ComponentEvent e) {}
        });
        panel.add(ta);
                        Just for convenience, here a solution using a JTextField instead of a JTextArea similar to the accepted solution, using info from: change the size of JTextField on KeyPress
final JPanel panel = new JPanel();
final BoxLayout layout = new BoxLayout(panel, BoxLayout.X_AXIS);
panel.setLayout(layout);
panel.add(new JLabel("Some text: "));
final JTextField field = new JTextField(String.valueOf(value));
final DocumentListener documentListener = new DocumentListener() {
    private void updatePanel() {
        panel.revalidate();
        panel.setSize(panel.getPreferredSize());
    }
    @Override
    public void removeUpdate(DocumentEvent e) {
        updatePanel();
    }
    @Override
    public void insertUpdate(DocumentEvent e) {
        updatePanel();
    }
    @Override
    public void changedUpdate(DocumentEvent e) {
    }
};
field.getDocument().addDocumentListener(documentListener);
panel.add(field);
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With