如何隐藏当前的 JPanel 并在 Java 中显示一个带有按钮的新 JPanel?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13110094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 11:30:56  来源:igfitidea点击:

How do I hide the current JPanel and show a new one with a button in Java?

javaswingjframejpanel

提问by allocate

I unfortunately have to use multiple windows in this program and I don't think CardLayout is going to work because I can't have any buttons constant between the different layouts. So I'm trying to code a button to hide the present JPanel (thePanel) and show a new one (thePlacebo).

不幸的是,我不得不在这个程序中使用多个窗口,我认为 CardLayout 不会起作用,因为我不能在不同的布局之间有任何按钮不变。所以我试图编写一个按钮来隐藏当前的 JPanel (thePanel) 并显示一个新的 (thePlacebo)。

I'm trying to hide thePanel in an ActionListener like this:

我试图在这样的 ActionListener 中隐藏 thePanel:

frame.getContentPane().remove(thePanel);

I thought this would work, but it just freezes my program as soon as I hit the button.

我认为这会奏效,但只要我按下按钮,它就会冻结我的程序。

Here's a chunk of the code for context:

这是上下文的一段代码:

public class Reflexology1 extends JFrame{
JButton button1, button2;
JButton movingButton;
JTextArea textArea1;
int buttonAClicked, buttonDClicked;
private long _openTime = 0;
private long _closeTime = 0;
JPanel thePanel = new JPanel();
JPanel thePlacebo = new JPanel();
final JFrame frame = new JFrame("Reflexology");

public static void main(String[] args){
    new Reflexology1();
}

public Reflexology1(){


    frame.setSize(600, 475);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setTitle("Reflexology 1.0");
    frame.setResizable(false);


    button1 = new JButton("Accept");
    button2 = new JButton("Decline");
    movingButton = new JButton("Click Me");

    ListenForAcceptButton lForAButton = new ListenForAcceptButton();
    ListenForDeclineButton lForDButton = new ListenForDeclineButton();
    button1.addActionListener(lForAButton);
    button2.addActionListener(lForDButton);
    //movingButton.addActionListener(lForMButton);

    JTextArea textArea1 = new JTextArea(24, 50);

    textArea1.setText("Tracking Events\n");
    textArea1.setLineWrap(true);
    textArea1.setWrapStyleWord(true);
    textArea1.setSize(15, 50);

    FileReader reader = null;
    try {
        reader = new FileReader("EULA.txt");
        textArea1.read(reader, "EULA.txt");
    } catch (IOException exception) {
        System.err.println("Problem loading file");
        exception.printStackTrace();
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException exception) {
                System.err.println("Error closing reader");
                exception.printStackTrace();
            }
        }
    }

    JScrollPane scrollBar1 = new JScrollPane(textArea1, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    AdjustmentListener listener = new MyAdjustmentListener();

    thePanel.add(scrollBar1);
    thePanel.add(button1);
    thePanel.add(button2);
    thePlacebo.add(movingButton);

    frame.add(thePanel);

    ListenForWindow lForWindow = new ListenForWindow();
    frame.addWindowListener(lForWindow);
    frame.setVisible(true);

}
// Implement listeners

private class ListenForAcceptButton implements ActionListener{
    public void actionPerformed(ActionEvent e){
        if (e.getSource() == button1){
            Calendar ClCDateTime = Calendar.getInstance();
            System.out.println(ClCDateTime.getTimeInMillis() - _openTime);
            _closeTime = ClCDateTime.getTimeInMillis() - _openTime;
            frame.getContentPane().remove(thePanel);
        }
    }
}

Does anybody know what I might be doing wrong?

有谁知道我可能做错了什么?

回答by nIcE cOw

After removing components from a container, it goes into the invalidatestate. To bring it back to the validstate you have to revalidateand repaintthat. In your case you are directly adding/removing components from JFrameso depending on the Java version you can do this :

从容器中移除组件后,它会进入invalidate状态。把它带回来给valid你要的状态revalidaterepaint那个。在您的情况下,您直接添加/删除组件,JFrame具体取决于 Java 版本,您可以这样做:

frame.revalidate(); // For Java 1.7 or above
frame.getContentPane().validate(); // For Java 1.6 or below
frame.repaint();

Here is one working example for your help :

这是一个可以帮助您的工作示例:

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

public class Assignment
{
    private JFrame frame;
    private JPanel firstPanel;
    private JPanel secondPanel;

    private JButton forwardButton;
    private JButton backButton;

    private void displayGUI()
    {
        frame = new JFrame("Assignment");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        firstPanel = new JPanel();
        firstPanel.setOpaque(true);
        firstPanel.setBackground(Color.BLUE);

        secondPanel = new JPanel();
        secondPanel.setOpaque(true);
        secondPanel.setBackground(Color.RED);

        forwardButton = new JButton("Forward");
        forwardButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent ae)
            {
                frame.remove(firstPanel);
                frame.add(secondPanel);
                frame.revalidate(); // For Java 1.7 or above.
                // frame.getContentPane().validate(); // For Java 1.6 or below.
                frame.repaint();
            }
        });

        backButton = new JButton("Back");
        backButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent ae)
            {
                frame.remove(secondPanel);
                frame.add(firstPanel);
                frame.revalidate(); // For Java 1.7 or above.
                // frame.getContentPane().validate(); // For Java 1.6 or below.
                frame.repaint();
            }
        });

        firstPanel.add(forwardButton);
        secondPanel.add(backButton);

        frame.add(firstPanel);
        frame.setSize(300, 300);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new Assignment().displayGUI();
            }
        });
    }
}

回答by mKorbel

  1. correct way could be (only) by using CardLayout

  2. otherwise have to remove JPanelfrom container and to call (as last code line and call only one times after all changes for container are done)

  1. 正确的方法可能是(仅)使用CardLayout

  2. 否则必须从容器中删除JPanel并调用(作为最后一行代码,并且在容器的所有更改完成后仅调用一次)

.

.

myJPanelsContainer#revalidate(); // in Java6 for JFrame validate()
myJPanelsContainer#repaint();