在JFrame.invalidate中调用pack()是个坏主意吗?

时间:2019-05-15 16:57:57

标签: java swing

我建立了一个简单的gui,可以根据用户输入添加面板。我最初的问题是,在添加面板时,框架没有调整大小。因为这是一个处理用户输入的jpanel对象,所以向其自身添加了一个新面板,因此无法“看到” jframe(至少我找不到它的样子),因此我无法弄清楚如何调用{{1 }}或repaint()在该对象内的父框架上。但是,通过反复试验,我确实发现这可行

revalidate()

但是,因为我真的不知道使用无效操作在幕后发生的事情,所以我想知道这是否是个好主意(似乎有点粗略)。任何建议都很好,谢谢。

编辑

希望这会使问题更加清楚

JFrame jFrame = new JFrame(title){
    @Override
    public void invalidate(
         super.invalidate();
         this.pack();
    }
};

1 个答案:

答案 0 :(得分:2)

您的问题不是revalidate()repaint()无效。

这里的问题是您的JFrame已经pack(),因此具有首选的尺寸设置。如果要更改其大小,则需要再次调用pack()。不一定要在invalidate()上调用它。

我对您的代码进行了一些更改以进行编译(typos),我想到了:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TestFrame {
    JFrame jframe;
    NewPanel jpanel;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new TestFrame());
    }

    public TestFrame(){
        jframe = new JFrame();  // without above addition frame won't resize
        jpanel = new NewPanel(); 
        jframe.add(jpanel);
        jframe.pack();
        jframe.setVisible(true);
    }

    class NewPanel extends JPanel implements ActionListener{
        public NewPanel(){
            JTextField textField = new JTextField (10);
            textField.addActionListener(this);
            this.add(textField);
        }

        // Adds a label when action is performed on textfield
        @Override
        public void actionPerformed(ActionEvent ae){
            System.out.println("WOLOLO");
            JPanel extraPanel = new JPanel();
            extraPanel.add(new JLabel("hi"));
            this.add(extraPanel);
            this.revalidate();
            this.repaint();
            jframe.pack();
        }
    }
}

解决此问题的另一种方法是从getPreferredSize覆盖JPanel方法:

@Override
public Dimension getPreferredSize() {
    return new Dimension(200, 200);
}

您也可以在前面的代码中删除jframe.pack()