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

问题描述 投票:0回答:2

在这个简单的代码中,如果我单击按钮几次,一些 JCheckBox 将被添加到 JPanel 中。但是,除非在

add("TEST")
之后立即调用
revalidate()
(仅
invalidate()
不起作用)或
updateFrame()
,否则显示不会更新。另外,如果我使用
revalidate()
,JCheckBox 会出现,但 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());
    }
}
java swing jpanel repaint jcheckbox
2个回答
1
投票

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

建议:

  1. 将 JPanel 放入 JScrollPane 中,这将允许 JPanel 在添加组件时调整大小(并且调用
    revalidate()
    )或
  2. 在将组件添加到 JPanel 后,在封闭的顶级窗口(此处为 JFrame)上调用
    pack()
    ,这将重新调整整个 GUI 的大小。

也可以考虑

  • 给 JPanel 一个 GridLayout(0, 1)...
  • ...将其嵌入到另一个 BorderLayout-使用 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);
        });
    }
}

0
投票

这是您的代码,稍作修改,删除了不必要的内容。

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

public class UserInterface2 {

    private JButton button;
    private JPanel panel;

    public UserInterface2() {
        JFrame 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);
        frame.setSize (200, 200);
        frame.setVisible(true);
    }

    private void createButton() {
        button = new JButton("Text");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                add("TEST");
                panel.revalidate();
            }
        });
    }

    private void add(String text) {
        panel.add(new JCheckBox(text));
    }

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

没有 show(),没有 updateFrame()。 问题是,您的中心面板没有内容,因此没有绘制,不占用任何空间。我使用

frame.setSize (200, 200);
来强制大小 > 0。

现在您会看到复选框出现,直到您添加到许多复选框为止。但如果调整框架大小,它们也会变得可见。但

panel.revalidate ()
是必要的。

© www.soinside.com 2019 - 2024. All rights reserved.