如何使用子类中的Action Listener从超类中的JPanel中删除所有元素?

时间:2013-07-05 20:43:24

标签: java swing jpanel subclass actionlistener

我是Java新手所以请帮忙:) 我有一个名为 MainFrame 的超类,主方法和构造函数类 Run()。 我从子类caled MenuBar 获得JFrame的菜单栏。 菜单栏有多个子类,其中包含已实施的ActionListeners。 每当我尝试使用ActionListener从 MainFrame 超类中调用一个方法时,我就会收到错误,该方法会删除在 MainFrame JPanel 中的所有元素>构造函数方法运行() MainFrame代码:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.Arrays;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;


public class MainFrame {
    JFrame mainFrame;
    JPanel mainPanel;
    JPanel[] pagePanels, tablePanels;
    JScrollPane scrollBar;

    private double zoom=1;
    private int width;
    private int height;
    private GridBagConstraints c;

    //private Page blankPage = new Page();
    MenuBar menubar;
    Page blankPage;

    public static void main(String[] args) {
        MainFrame generator = new MainFrame();
        generator.Run();
    }

    public void Run() {

        pagePanels = new JPanel[100];
        tablePanels = new JPanel[100];

        menubar = new MenuBar();
        blankPage = new Page();
        c = new GridBagConstraints();

        mainFrame = new JFrame("Code Generator v.1.0");
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        c.gridx=0;
        c.insets = new Insets(20,0,20,0);
        //get size of screen
        GetScreenSize();

        mainPanel=new JPanel(new GridBagLayout());

        scrollBar=new JScrollPane(mainPanel);
        scrollBar.setPreferredSize(new Dimension(width,height));

        //create main frame with height and width equal to screen size (fullscreen)
        mainFrame.setJMenuBar(menubar.getMenuBar());
        mainFrame.getContentPane().add(scrollBar);
        mainFrame.setSize(width,height);
        mainFrame.setVisible(true);
    }

    public void GetScreenSize(){
        GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        width = gd.getDisplayMode().getWidth();
        height = gd.getDisplayMode().getHeight();
    }

    public void RemoveAllfromMainPanel(){
        mainPanel.removeAll();
    }


}

子类 MenuBar 的代码是:

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

public class MenuBar  extends MainFrame{

    public JMenuBar getMenuBar(){

        JMenuBar menubar = new JMenuBar();

        //add menus to menu bar 
        JMenu file = new JMenu("File");
        menubar.add(file);

        //add items to File menu
        JMenuItem newReport = new JMenuItem("New report");
        file.add(newReport);
        newReport.addActionListener(new newReport());

        JMenuItem exit = new JMenuItem("Exit");
        file.add(exit);
        exit.addActionListener(new exitAction());

        return menubar;

    }

    class exitAction implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            System.exit(0);
        }
    }
    class newReport implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            RemoveAllfromMainPanel();
        }
    }
}

我认为它必须对继承做些什么,但这是我最近开始研究的话题。你能否向我解释为什么我会收到这个错误:

线程“AWT-EventQueue-0”中的异常java.lang.NullPointerException     在MainFrame.TEST(MainFrame.java:125)

在这一行:

mainPanel.removeAll();

提前谢谢!干杯!

2 个答案:

答案 0 :(得分:1)

你实际上有两个不同的实例,这就是问题所在。

首先,当您启动应用程序时,您创建一个MainFrame对象并在该实例上调用Run(请使用方法的小写名称)。该实例具有正确初始化的字段mainPanel

然后,您创建了MenuBar的第二个实例,这是一个扩展MainFrame的类。它继承了超类中的字段,但来自另一个实例的值。因此,MenuBar对象也有一个mainPanel字段,但它是null。现在,当您在menuBar上调用RemoveAllfromMainPanel()时,您可以从menuBar实例访问该字段,并在导致NPE的removeAll上调用null

答案 1 :(得分:1)

您的MenuBar不应该从MainFrame延伸。这与您的main方法中的run方法创建的实例不同,这意味着mainPanel尚未初始化。

相反,您应该在创建MenuBar时将MainFrame的实例引用 menubar = new MenuBar(this);

public class MenuBar {

    private MainFrame mainFrame;

    public MenuBar(MainFrame mainFrame) {
        this.mainFrame = mainFrame;
    }

    /* other code */


    class newReport implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            mainFrame.RemoveAllfromMainPanel();
        }
    }
 }

在你的MenuBar上......

{{1}}