在KeyPress上更改JTextField的大小

joh*_*tom 0 java graphics layout swing jtextfield

当用户在textfield中输入文本时,我必须在KeyPressed事件上扩展JTextField的大小.请给我一些想法如何实现这一点?

提前致谢

kle*_*tra 5

好的,跳了它:-)

让我们假设问题是

如何调整JTextField的宽度以始终适合其内容宽度?

通常的合作者

  • 一个LayoutManager,它的子节点大小为pref,fi FlowLayout
  • JTextField报告其符合内容的pref大小
  • 预计会自动调整大小

快速举例:

JTextField field = new JTextField("something");
JComponent parent = new JPanel(); // has FlowLayout by default
parent.add(field);
frame.add(parent);
// just to ensure it's bigger 
frame.setSize(400, 400);
Run Code Online (Sandbox Code Playgroud)

键入...并且没有任何反应:大小保持初始大小.这是令人惊讶的:出于某种原因,该领域的自动验证根本不会发生.事实上,在接收更改通知时手动重新验证字段(注意:此处唯一正确的侦听器类型是DocumentListener)也不会更改字段:

final JTextField field = new JTextField("something");
DocumentListener l = new DocumentListener() {

    private void updateField(JTextField field)
        // has no effect
        field.revalidate();
    }


    @Override
    public void removeUpdate(DocumentEvent e) {
        updateField(field);
    }

    @Override
    public void insertUpdate(DocumentEvent e) {
        updateField(field);
    }

    @Override
    public void changedUpdate(DocumentEvent e) {
   }
};

field.getDocument().addDocumentListener(l);
JComponent parent = new JPanel(); // has FlowLayout by default
parent.add(field);
frame.add(parent);
// just to ensure it's bigger 
frame.setSize(400, 400);
Run Code Online (Sandbox Code Playgroud)

@Gagandeep Bali发现它是需要重新验证的父级:

private void updateField(JTextField field) {
    field.getParent().revalidate();
}
Run Code Online (Sandbox Code Playgroud)

出乎意料,所以下一个问题是臭名昭着的原因?这里:为什么在找到validateRoot之前,invalidate会在容器层次结构中冒泡?答案在api doc中:

通过验证textfield来处理来自textfield本身内部的重新验证调用,除非textfield包含在JViewport中,在这种情况下返回false.

换句话说:它不会冒出来,因为字段本身就是一个validateRoot.这使得另一个选项覆盖并无条件地返回false:

JTextField field = new JTextField("something") {

    @Override
    public boolean isValidateRoot() {
        return false;
    }
};
JComponent parent = new JPanel(); // has FlowLayout by default
parent.add(field);
frame.add(parent);
// just to ensure it's bigger 
frame.setSize(400, 400);
Run Code Online (Sandbox Code Playgroud)

为此付出的代价是滚动不起作用 - 在这种情况下这不是什么大问题,因为文本总是适合该领域.或者实现稍微更智能,如果实际宽度小于pref,则返回true.