你应该调用哪个不同的更新方法,以使组件在添加到JPanel后显示出来?

huangapple go评论72阅读模式
英文:

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

问题

以下是您提供的代码的翻译:

在这个简单的代码中,如果我点击按钮几次,将会向JPanel添加几个JCheckBoxes。然而,除非在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());
    }
}
英文:

In this simple code if I click the button a few times a few JCheckBoxes will be added to the JPanel. However the display is not updated unless right after add("TEST") I call either revalidate() (just invalidate() won't work), or updateFrame(). Also, if I use revalidate(), the JCheckBoxes appear but the JPanel is not resized. I'm also aware of the repaint() method, but I'm not sure how to use it or those other methods.

What is the relationship between those component update methods so I can achieve the minimum I want (the JCheckBoxes to appear and the JPanel to be resized)?

How could I simplify the code?

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

答案1

得分: 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);
        });
    }
}
英文:

The JPanel will resize, but you're not seeing it because it is constrained by the JFrame that holds it, which can't resize without explicitly telling it to do so.

Suggestions:

  1. Put the JPanel inside of a JScrollPane which will allow the JPanel to resize as components are added (and revalidate() is called) or
  2. Call pack() on the enclosing top-level window, here a JFrame, after adding components to the JPanel which will re-size the entire GUI.

Also consider

  • giving the JPanel a GridLayout(0, 1)...
  • ...embedding it in the BorderLayout.PAGE_START position of another BorderLayout-using JPanel...
  • ...then adding that JPanel to the scroll pane or to the BorderLayout.CENTER position of the JFrame's contentPane. This will compress the added components to the top of the JPanel.

For example:

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

huangapple
  • 本文由 发表于 2020年8月6日 04:44:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/63273227.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定