【问题标题】:Dynamically resize JTextField in JTree Node在 JTree 节点中动态调整 JTextField 的大小
【发布时间】:2012-07-31 14:31:15
【问题描述】:

我正在使用带有一些 JLabels 和 JTextFields 的 JPanel 作为 JTree 中的编辑器和渲染器。

用户可以单击任何 JTextField 并修改文本。一切正常。

我所缺少的只是如何在用户键入时动态调整(增长)JTextField 的大小。

下面是一个说明问题的小示例程序。单击即“颜色”并输入一些其他字符。 JTextField 保持其大小,这是预期的,但我希望它可以扩大和缩小以适应文本。

我尝试了不同的布局管理器,计算JTextField和JPanel的preferredSize,调用invalidate()和JPanel和Tree等等,都没有成功。

有什么想法吗?

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

    }

}

【问题讨论】:

  • 与您的问题无关:a)celleditor 的实现无效(在编辑终止时不服务通知侦听器 b)不要在 getXX 中创建组件,而是创建一次并显示
  • 与您的问题有关:即使在正常环境中,调整 textField 的大小以始终适合其内容也出乎意料地不直接 b) 住在树上肯定不会软化 :-) 请参阅 stackoverflow.com/questions/11716785/…
  • a) 实现不完整,因为它应该是一个最小的示例应用程序 b) 在实际应用程序中,不同数量的组件被添加到不同的节点 a2) JTextFields 是“句子”的一部分" 所以它们应该只容纳“单词”而不是固定宽度。
  • a) 足够公平 b) 即使那样,我也会使用不同数量的文本字段缓存面板(渲染器经常被称为 really)a2) 这正是答案在链接的线程中正在做
  • 请注意,我在示例代码中放置了 JTextArea 而不是 JTextField。要获得使用 JTextField 的公认答案,还需要应用 kleopatra 的发现 findings

标签: java swing resize jtextfield jtree


【解决方案1】:

发生的情况是拥有您的 panel 的容器没有分配给它的布局管理器 - 所以当文本区域调整大小时,panel 没有调整大小。一个简单的解决方法是在文本区域调整大小时设置面板的大小。所以不要直接这样做:

        panel.add(new JTextArea(String.valueOf(value)));

你可以这样做:

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

【讨论】:

    【解决方案2】:

    为了方便起见,这里使用 JTextField 而不是 JTextArea 的解决方案类似于接受的解决方案,使用来自: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);
    

    【讨论】:

      猜你喜欢
      • 2012-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-05
      • 1970-01-01
      • 2012-02-22
      • 2023-03-26
      相关资源
      最近更新 更多