change the size of JTextField on KeyPress

前端 未结 4 1087
臣服心动
臣服心动 2021-01-28 07:12

I have to extend the size of JTextField on KeyPressed event as user enter the text in textfield.please give me some idea how to achieve this?

thanks in advance

4条回答
  •  爱一瞬间的悲伤
    2021-01-28 07:42

    Okay, jumping for it :-)

    Let's assume the question is

    How to adjust a JTextField's width to always fit its content width?

    Usual collaborators

    • a LayoutManager which sizes its children at their pref size, f.i. FlowLayout
    • JTextField reports its pref size fitted to content
    • auto-magical resize expected

    Quick example:

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

    type ... and nothing happens: size remains at initial size. That's surprise: for some reason, the field's auto-validation simply doesnt't happen. In fact, a manual revalidate of the field on receiving a change notification (Note: the only correct listener type here is a DocumentListener) doesn't change the field as well:

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

    @Gagandeep Bali found out that it's the parent that needs to be revalidated:

    private void updateField(JTextField field) {
        field.getParent().revalidate();
    }
    

    Unexpected, so the next question is the notorious why? Here: why doesn't the invalidate bubble up the container hierarchy until it finds a validateRoot? The answer is in the api doc:

    Calls to revalidate that come from within the textfield itself will be handled by validating the textfield, unless the textfield is contained within a JViewport, in which case this returns false.

    Or in other words: it's not bubbled up because the field itself is a validateRoot. Which leaves the other option to override and unconditionally return 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);
    

    The price to pay for this, is that the scrolling doesn't work - which isn't a big deal in this context, as the text always fits into the field. Or implement slightly more intelligent, and return true if the actual width is less than the pref.

提交回复
热议问题