我应该调用哪些不同的更新方法来使组件在添加到 JPanel 后出现?

Which of those different update methods should I call to make components appear after being added to a JPanel?

在这个简单的代码中,如果我点击按钮几次,几个 JCheckBoxes 将被添加到 JPanel。但是,除非在 add("TEST") 之后立即调用 revalidate()(只是 invalidate() 不起作用)或 updateFrame(),否则显示不会更新。此外,如果我使用 revalidate(),则会出现 JCheckBoxes 但不会调整 JPanel 的大小。我也知道 repaint() 方法,但我不确定如何使用它或其他方法。

那些组件更新方法之间的关系是什么,以便我可以达到我想要的最小值(出现 JCheckBoxes 和调整 JPanel 的大小)?

如何简化代码?

public class UserInterface2 {

    private final JFrame frame;
    private JButton button;
    private JPanel panel;
    
    public UserInterface2() {
        
        frame = new JFrame("Test App");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.getContentPane().setLayout(new BorderLayout());
        
        createButton();
        panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
        
        frame.getContentPane().add(button, BorderLayout.WEST);
        frame.getContentPane().add(panel, BorderLayout.CENTER);
    }
    
    private void updateFrame() {
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    private void createButton() {
        button = new JButton("Text");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                add("TEST");
                panel.revalidate();
                //updateFrame();
            }
        });
    }
    
    public void show() {
        updateFrame();
    }

    private void add(String text) {
        panel.add(new JCheckBox(text));
    }
    
    public static void main(String [] args) {
        SwingUtilities.invokeLater(() -> new UserInterface2().show());
    }
}

JPanel 将调整大小,但您看不到它,因为它受到容纳它的 JFrame 的约束,如果没有明确指示它就无法调整大小。

建议:

  1. 将 JPanel 放在 JScrollPane 中,这将允许 JPanel 在添加组件时调整大小(并调用 revalidate())或
  2. 在封闭的 top-level window 上调用 pack(),这里是一个 JFrame,在将组件添加到 JPanel 之后,这将 re-size 整个 GUI。

也考虑

  • 为 JPanel 提供 GridLayout(0, 1)...
  • ...将其嵌入另一个 BorderLayout-using JPanel 的 BorderLayout.PAGE_START 位置...
  • ...然后将该 JPanel 添加到滚动窗格或 JFrame 的 contentPane 的 BorderLayout.CENTER 位置。这会将添加的组件压缩到 JPanel 的顶部。

例如:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import javax.swing.*;

public class UserInterface3 {
    private JPanel mainPanel = new JPanel(new BorderLayout());
    private JPanel panel = new JPanel(new GridLayout(0, 1));
    
    public UserInterface3() {
        JPanel wrapperPanel = new JPanel(new BorderLayout());
        wrapperPanel.add(panel, BorderLayout.PAGE_START);       
        JScrollPane scrollPane = new JScrollPane(wrapperPanel);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.getViewport().setPreferredSize(new Dimension(300, 300));
        
        JButton addCheckBoxBtn = new JButton("Add CheckBox");
        addCheckBoxBtn.addActionListener(e -> addCheckBox());
        addCheckBoxBtn.setMnemonic(KeyEvent.VK_A);
        JPanel btnPanel = new JPanel();
        btnPanel.add(addCheckBoxBtn);       
        
        
        mainPanel.add(scrollPane);
        mainPanel.add(btnPanel, BorderLayout.PAGE_END);     
    }
    
    private void addCheckBox() {
        panel.add(new JCheckBox("Test"));
        mainPanel.revalidate();
    }

    public JPanel getMainPanel() {
        return mainPanel;
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("GUI");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            UserInterface3 ui3 = new UserInterface3();
            frame.add(ui3.getMainPanel());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}