I use a multiline JTextArea to edit the values in my JTree.
With some coaxing, I'm able to get the JTextArea to resize to accommodate the text inside it, but the JTree nodes/rows around the editor don't move out of the way. (SCCEE w/ Screenshot below)
How do I get JTree to "reflow" all its nodes around the editor component?
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
public final class TextAreaEditorForJTree {
public static final String INITIAL_TEXT = "Line 1\nLine 2\nLine 3";
public static void main(String args[]) {
JTree tree = createSimpleTree();
addTextAreaEditor(tree);
JScrollPane scrollPane = new JScrollPane(tree);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 300);
frame.setVisible(true);
}
private static JTree createSimpleTree() {
DefaultMutableTreeNode root = new DefaultMutableTreeNode(INITIAL_TEXT);
for (int i = 0; i < 10; i++) {
MutableTreeNode child = new DefaultMutableTreeNode(INITIAL_TEXT);
root.add(child);
}
JTree tree = new JTree(root);
tree.setEditable(true);
tree.setShowsRootHandles(true);
return tree;
}
private static void addTextAreaEditor(JTree tree) {
TreeCellEditor editor = new TextAreaTableCellEditor();
tree.setCellEditor(editor);
}
private static final class TextAreaTableCellEditor extends AbstractCellEditor implements TreeCellEditor {
private final JPanel panel;
private final JLabel label;
private final JTextArea textArea;
private DefaultMutableTreeNode currentNode;
public TextAreaTableCellEditor() {
label = new JLabel("Editor:");
textArea = new JTextArea();
textArea.setColumns(10);
panel = new JPanel();
BoxLayout boxLayout = new BoxLayout(panel, BoxLayout.X_AXIS);
panel.setLayout(boxLayout);
panel.add(label);
panel.add(textArea);
textArea.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent e) {
setSizeToPreferredSizeLater();
}
@Override
public void componentShown(ComponentEvent e) {
setSizeToPreferredSizeLater();
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentHidden(ComponentEvent e) {
}
});
textArea.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
setSizeToPreferredSizeLater();
}
public void removeUpdate(DocumentEvent e) {
setSizeToPreferredSizeLater();
}
public void changedUpdate(DocumentEvent e) {
setSizeToPreferredSizeLater();
}
});
}
private void setSizeToPreferredSizeLater() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
panel.setSize(panel.getPreferredSize());
}
});
}
public Object getCellEditorValue() {
return textArea.getText();
}
public boolean isCellEditable(EventObject anEvent) {
return true;
}
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
public boolean stopCellEditing() {
currentNode.setUserObject(textArea.getText());
return true;
}
public void cancelCellEditing() {
currentNode.setUserObject(textArea.getText());
}
public Component getTreeCellEditorComponent(final JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
this.currentNode = ((DefaultMutableTreeNode) value);
textArea.setText((String) currentNode.getUserObject());
return panel;
}
}
}
Screenshot of SCCEE - The editor (Gray box and text to it's right) appears on-top-of all the other tree nodes.