如何使用 removeAll() 从 JFrame 中删除所有组件?

Posted

技术标签:

【中文标题】如何使用 removeAll() 从 JFrame 中删除所有组件?【英文标题】:How to remove all components from a JFrame with removeAll()? 【发布时间】:2013-07-26 15:38:11 【问题描述】:

因此,当字符串等于某个值时,我希望从JFrame 中删除所有内容,但是当我调用removeAll(); 后跟revalidate();repaint(); 时,它不会改变任何内容。

我尝试按照here 的指示拨打getContentPane.removeAll();,但没有任何效果。

我的代码如下:

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

public class MTGSAMPServerReference extends JFrame implements ActionListener 
    private static final long serialVersionUID = 1L;
    private static JList list1;
    private static JButton select1;
    public static String selectionMenu = "Main";

    public MTGSAMPServerReference() 
        this.getContentPane().setLayout(new FlowLayout(FlowLayout.LEADING));
            Object[]mainMenu = "Vehicles", "Bikes/Bicycles", "Boats", "Houses", "Businesses", "Objects", "Jobs", "Ranks", "Licenses", "VIP", "FAQ's";
                Object[]VehiclesValueMenu = "Lower Class", "Upper Class", "VIP";
        if ("Main".equals(selectionMenu)) 
            JPanel controls = new JPanel(new BorderLayout(5,5));
            list1 = new JList<Object>(mainMenu);
            list1.setVisibleRowCount(10);
            select1 = new JButton("Select");
            select1.addActionListener(this);
            controls.add(new JScrollPane(list1));
            controls.add(select1, BorderLayout.PAGE_END);
            controls.setBorder(new EmptyBorder(25,25,0,0));
            add(controls);
            revalidate();
            repaint();
        
        if ("VehiclesValue".equals(selectionMenu)) 
            removeAll();
            revalidate();
            repaint();
        

    

    @Override
    public void actionPerformed(ActionEvent e) 
        if ("Main".equals(selectionMenu)) 
            if (e.getActionCommand().equals("Select")) 
                int indexMain = list1.getSelectedIndex();
                System.out.println("Index Selected: " + indexMain);
                String valueMain = (String) list1.getSelectedValue();
                System.out.println("Value Selected: " + valueMain);
                if ("Vehicles".equals(valueMain)) 
                    selectionMenu = "VehiclesValue";
                    System.out.println("Menu selected: " + selectionMenu);
                    revalidate();
                    repaint();
                
            
        
    

    public void createAndShowGUI() 
        JFrame f = new MTGSAMPServerReference();
        f.pack();
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //f.add(new drawOnPanel());
        f.setSize(1200, 800);
        f.setLocationRelativeTo(null);
        list1.setSize(250, 250);
        list1.setLocation(0, 0);
        select1.setSize(75, 25);
        select1.setLocation(251, 276);
        MTGSAMPServerReference.this.repaint();
    

    public static void main(String[] args) 
        javax.swing.SwingUtilities.invokeLater(new Runnable() 
            public void run() 
            MTGSAMPServerReference gui = new MTGSAMPServerReference();
            gui.createAndShowGUI();
            
        );
    

我已经完成了研究,但无法弄清楚我做错了什么。

如果我尝试更改我的JFrame f to a Global Variable instead of a Local Variable,它不会显示任何开头的内容。

是的,我知道我是mixing Commmand Line with GUI,但那是only for debugging purposes。完成后,我将简单地删除所有Command Line related

无论如何,对我的问题有什么想法吗?

提前致谢!

【问题讨论】:

static 变量很好地表明了糟糕的设计 为此,我会使用CardLayout,如short example所示。 通过容器实例 list1select1 不必是static,因为它们应该属于MTGSAMPServerReference 的单个实例。 selectionMenu 不必是 static,因为它可以作为参数传递给 MTGSAMPServerReference 构造函数。如果您需要访问 JListJButton 包含的值,则应根据需要提供 getter 和 setter。如果可以避免,则应避免将子组件暴露给外界,因为这意味着其他人会突然控制您的整个组件,并且可以做您无法阻止的事情 “一旦你批评了我的代码,你介意提供一个解决方案吗?” 我不认为这是一个很有帮助的评论。 1) 提供建议的人可能不知道答案,但仍然能够识别会导致问题的代码(我同意使用static - 如果有的话,这很少是解决方案)。 2) 修复他们指出的问题实际上可能成为解决方案,或者 90% 的解决方案,并且.. 3) 它听起来像是“除非你打算提供答案,不要批评我的代码'。通常,当人们“将代码撕成碎片”时,他们会把你的最大利益放在心上。 【参考方案1】:

我发现该代码存在几个问题:

MTGSAMPServerReference 被调用两次,一次是主要的,另一次被createAndShowGUI() 调用。

MTGSAMPServerReference 扩展了 JFrame,但 createAndShowGUI() 也包含一个局部变量 JFrame f。本质上,您将this 分配给了一个局部变量f,这没有任何意义。

要初始化 GUI,您需要执行构造函数和createAndShowGUI(),之后所有可以执行的代码都归因于事件。在您的情况下,使用 actionPerformed() 方法。如果你想删除框架内的组件,你必须在那里(或在某个时候从那里调用)执行正确的代码。

如您的链接所述,要删除所有组件,您必须在 JFrame 的 contentPane 上执行 removeAll(),通过 getContentPane() 获得。

我不知道您打算如何处理这些比较 if("Main".equals(selectionMenu))。同样是初始化代码,它运行了一次。在那里你构建了所有的 GUI。变量selectionMenu 将来可能会更改,但这不会追溯执行该代码。如果您想使用 selectionMenu 的新值执行任何操作,请在 actionListener 上执行。

这是您的代码的有效修改。

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

public class MTGSAMPServerReference extends JFrame implements ActionListener 
    private static final long serialVersionUID = 1L;
    private static JList list1;
    private static JButton select1;
    public static String selectionMenu = "Main"; //accomplishes nothing

    public static void main(String[] args) 
    
        javax.swing.SwingUtilities.invokeLater(new Runnable() 
            public void run() 
            MTGSAMPServerReference gui = new MTGSAMPServerReference();
            gui.createAndShowGUI();
            
        );
    

    public void createAndShowGUI() 
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //f.add(new drawOnPanel());
        setSize(1200, 800);
        setLocationRelativeTo(null);
        list1.setSize(250, 250);
        list1.setLocation(0, 0);
        select1.setSize(75, 25);
        select1.setLocation(251, 276);
        setVisible(true);
    


    public MTGSAMPServerReference() 
        this.getContentPane().setLayout(new FlowLayout(FlowLayout.LEADING));
            Object[]mainMenu = "Vehicles", "Bikes/Bicycles", "Boats", "Houses", "Businesses", "Objects", "Jobs", "Ranks", "Licenses", "VIP", "FAQ's";
                Object[]VehiclesValueMenu = "Lower Class", "Upper Class", "VIP";
            JPanel controls = new JPanel(new BorderLayout(5,5));
            list1 = new JList<Object>(mainMenu);
            list1.setVisibleRowCount(10);
            select1 = new JButton("Select");
            select1.addActionListener(this);
            controls.add(new JScrollPane(list1));
            controls.add(select1, BorderLayout.PAGE_END);
            controls.setBorder(new EmptyBorder(25,25,0,0));
            add(controls);
            //revalidate(); //uneeded at this point the JFrame is not yet visible, thus nothing to repaint
            //repaint();
    

    @Override
    public void actionPerformed(ActionEvent e) 
        if (e.getActionCommand().equals("Select")) 
            int indexMain = list1.getSelectedIndex();
            System.out.println("Index Selected: " + indexMain);
            String valueMain = (String) list1.getSelectedValue();
            System.out.println("Value Selected: " + valueMain);
            if ("Vehicles".equals(valueMain)) 
                System.out.println("Menu selected: " + selectionMenu);
                getContentPane().removeAll(); //equivalent to this.getContentPane().removeAll();
                revalidate();
                repaint();
            
        
      
 

我还删除了对变量 selectionMenu 的修改,它现在并没有真正做任何事情。

正如其他人所说,您可能希望在某些时候使用另一个布局。哪一个取决于您在 JFrame 上还需要什么。

干杯。

【讨论】:

实际上,修改确实改变了一些事情。但无论如何,我会试试这个!【参考方案2】:

这是一个使用 CardLayout 的示例,它取消了 static 变量并通过 setter 和 getter 提供对一些内部值的访问,用于演示

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;

public class MTGSAMPServerReference extends JFrame implements ActionListener 

    private JList list1;
    private JButton select1;
    private String selectionMenu;
    private JPanel mainMenuPane;
    private JPanel vehicleMenuPane;

    public MTGSAMPServerReference(String selectionMenu) 
        this.getContentPane().setLayout(new FlowLayout(FlowLayout.LEADING));
        Object[] mainMenu = "Vehicles", "Bikes/Bicycles", "Boats", "Houses", "Businesses", "Objects", "Jobs", "Ranks", "Licenses", "VIP", "FAQ's";
        Object[] VehiclesValueMenu = "Lower Class", "Upper Class", "VIP";

        mainMenuPane = new JPanel(new BorderLayout(5, 5));
        list1 = new JList<Object>(mainMenu);
        list1.setVisibleRowCount(10);
        select1 = new JButton("Select");
        select1.addActionListener(this);
        mainMenuPane.add(new JScrollPane(list1));
        mainMenuPane.add(select1, BorderLayout.PAGE_END);
        mainMenuPane.setBorder(new EmptyBorder(25, 25, 0, 0));

        vehicleMenuPane = new JPanel();
        vehicleMenuPane.add(new JLabel("Vehicle"));

        CardLayout cl = new CardLayout();
        setLayout(cl);
        add("main", mainMenuPane);
        add("vehicle", vehicleMenuPane);

        cl.show(getContentPane(), "main");

        setSelectionMenu(selectionMenu);

    

    public String getSelectionMenu() 
        return selectionMenu;
    

    public void setSelectionMenu(String value) 
        if (selectionMenu == null ? value != null : !selectionMenu.equals(value)) 
            selectionMenu = value;
            updateMenu();
        
    

    protected void updateMenu() 
        CardLayout cl = (CardLayout) getContentPane().getLayout();
        if ("Main".equals(selectionMenu)) 
            cl.show(getContentPane(), "main");
         else if ("VehiclesValue".equals(selectionMenu)) 
            cl.show(getContentPane(), "vehicle");
        
    

    @Override
    public void actionPerformed(ActionEvent e) 
        if ("Main".equals(selectionMenu)) 
            if (e.getActionCommand().equals("Select")) 
                int indexMain = list1.getSelectedIndex();
                System.out.println("Index Selected: " + indexMain);
                String valueMain = (String) list1.getSelectedValue();
                System.out.println("Value Selected: " + valueMain);
                if ("Vehicles".equals(valueMain)) 
                    setSelectionMenu("VehiclesValue");
                    System.out.println("Menu selected: " + selectionMenu);
                
            
         else 
            setSelectionMenu("Main");
        
    

    public static void main(String[] args) 
        javax.swing.SwingUtilities.invokeLater(new Runnable() 
            public void run() 
                MTGSAMPServerReference gui = new MTGSAMPServerReference("Main");
                gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                gui.pack();
                gui.setLocationRelativeTo(null);
                gui.setVisible(true);
            
        );
    

【讨论】:

以上是关于如何使用 removeAll() 从 JFrame 中删除所有组件?的主要内容,如果未能解决你的问题,请参考以下文章

如何将值从一个JFrame传递到另一个JFrame?

如何从 JFrame 中仅删除最大化按钮?

如何从Java最小化JFrame窗口?

如何从JFrame中仅删除“最大化”按钮?

LINQ:RemoveAll 并删除元素

如何从 JFrame 中删除 JPanel?