【问题标题】:How to remove all components from a JFrame with removeAll()?如何使用 removeAll() 从 JFrame 中删除所有组件?
【发布时间】: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) 它听起来像是“除非你打算提供答案,不要批评我的代码'。通常,当人们“将代码撕成碎片”时,他们会把你的最大利益放在心上。

标签: java swing jframe components removeall


【解决方案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);
            }
        });
    }
}

【讨论】:

    猜你喜欢
    • 2012-03-09
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 2022-08-14
    • 1970-01-01
    • 2012-06-22
    • 2015-05-01
    相关资源
    最近更新 更多