JFrame没有响应setVisible()和dispose()

时间:2015-01-02 16:06:37

标签: java swing netbeans jframe

我正在创建一个“Snake”游戏作为家庭作业,我已经花了几个小时搜索所有可能的方法来关闭JFrame,但没有结论。我开始创建一个带有背景图像和菜单的JFrame的程序,仅此而已。当我点击“开始游戏”按钮(JMenuItem)时,它会打开一个带有线程的新JFrame来玩游戏。我的问题是第一个JFrame无论如何我都没有关闭。我尝试使用these解决方案和these以及these,但JFrame仍在那里。它看起来像他监听的唯一命令是“EXIT_ON_CLOSE”作为DefaultCloseOperation,甚至“DISPOSE_ON_CLOSE”都没有工作。这是我的SnakeFrame类:

package snake;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

/**
 *
 * @author Giacomo
 */
public class SnakeFrame extends Snake{

    protected JMenuItem start = new JMenuItem("Start game");

    public void pullThePlug(final SnakeFrame frame) {

  /*// this will make sure WindowListener.windowClosing() et al. will be called.
        WindowEvent wev = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
       // this will hide and dispose the frame, so that the application quits by
        // itself if there is nothing else around. 
        frame.setVisible(false);
        frame.dispose();*/


        frame.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentHidden(ComponentEvent e) {

                ((JFrame)(e.getComponent())).dispose();
            }
        });
    }

    public int game(final SnakeFrame frame,final JFrame gameFrame){

        short game_ok=0;

        try{
            start.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    GameThread gamethread = new GameThread(frame,gameFrame);
                    gamethread.start();

                    pullThePlug(frame);

                }
            });
        }
        catch(Exception e){
            game_ok=1;
        }


        return game_ok;
    }

//-----------Frame initialization with relative Listeners and Events.---------\\
    public SnakeFrame(){

            JFrame frame= new JFrame("Le Snake");
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            double larghezza = screenSize.getWidth();
            double altezza = screenSize.getHeight();
            frame.setBounds(((int)larghezza/4),((int)altezza/4),800, 600);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            ImageIcon icon = new ImageIcon("C:\\Users\\Giacomo\\Documents"
            + "\\NetBeansProjects\\Snake\\src\\res\\Snake-icon.png");
            frame.setIconImage(icon.getImage());
            frame.setResizable(false);
            frame.setLayout(new GridLayout());

            JMenuBar menuBar = new JMenuBar();
            JMenu menu = new JMenu("Menu");
            menuBar.add(menu);
            menuBar.setBounds(1, 1, frame.getWidth(),frame.getHeight()/25);
            JMenuItem close = new JMenuItem("Exit");

            close.addActionListener(new ActionListener(){

                @Override
                public void actionPerformed(ActionEvent e) {

                    System.exit(0);
                }
            });

            menu.add(start);
            menu.add(close);
            frame.setJMenuBar(menuBar);

            try {
            frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read
                (new File("C:\\Users\\Giacomo\\Documents\\NetBeansProjects\\"
                        + "Snake\\src\\res\\default.png")))));
            } catch (IOException e) {
                System.out.println("Exception with the background image.");
            }

            frame.pack();

        }
//-------------------------Frame initialization ended.-----------------------\\

}

这是游戏线程的代码(现在):

package snake;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;

/**
 *
 * @author Giacomo
 */
public class GameThread extends Thread implements Runnable{

    private final SnakeFrame frame;
    private final JFrame gameFrame;

    public GameThread(final SnakeFrame f,final JFrame gF){
        this.frame = f;
        this.gameFrame = gF;
    }

    @Override
    public void run(){

        System.out.println("Game Thread started.");

        final Label[][] griglia = new Label[50][50];
        final Container container = new Container();

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        double larghezza = screenSize.getWidth();
        double altezza = screenSize.getHeight();

        gameFrame.setVisible(true);
        gameFrame.setBounds(((int)larghezza/4),((int)altezza/4),
                800, 600);
        gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ImageIcon icon = new ImageIcon("C:\\Users\\Giacomo\\Documents"
            + "\\NetBeansProjects\\Snake\\src\\res\\Snake-icon.png");
            gameFrame.setIconImage(icon.getImage());
        gameFrame.setResizable(false);

        gameFrame.addWindowListener(new WindowAdapter(){

        @Override
        public void windowClosing(WindowEvent e){

                //Just to be sure he dies.       
                gameFrame.dispose();
                frame.dispose();
                System.exit(0); 

            }
        });

        gameFrame.setLayout(new GridLayout(50,50));

        for(int i=0;i<50;i++){
            for(int j=0;j<50;j++){
                griglia[i][j] = new Label();
                griglia[i][j].setBackground(Color.BLACK);
                container.add(griglia[i][j]);
            }
        } 
        gameFrame.add(container);
    }

}

我忘了什么吗?有没有人有想法?很抱歉,如果我的代码不好但我在学校学习:P我正在使用NetBeans 8.0.2。感谢大家。 ++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++ 修改

我现在已经解决了我遇到的大部分问题,主要是:

public static void main(String[] args) {

    final SnakeFrame frame = new SnakeFrame();
    short isGameOk;

    isGameOk =(short)frame.game(frame);

    if(isGameOk==1)
        System.err.println("Game Error!");

}

虽然这里是SnakeFrame类(“已修复”):

public class SnakeFrame extends Snake{

    private final JMenuItem start = new JMenuItem("Start game");
    private final BackgroundPanel defaultpanel;

    public int game(final SnakeFrame frame){

        short game_ok=0;

        try{
            start.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {

                    defaultpanel.setVisible(false);
                    JPanel panel = new JPanel();
                    JLabel[][] griglia = new JLabel[50][50];
                    panel.setLayout(new GridLayout(50,50));

                for(int i=0;i<50;i++){
                    for(int j=0;j<50;j++){
                        griglia[i][j] = new JLabel();
                        griglia[i][j].setBackground(Color.BLACK);
                        panel.add(griglia[i][j]);
                    }
                } 
                frame.add(panel);
                griglia[45][30].setIcon(new ImageIcon
                        ("src\\res\\sneikhead.png"));
                panel.setVisible(true);
                }
            });
        }
        catch(Exception e){
            game_ok=1;
        }

        return game_ok;
    }

//-----------Frame initialization with relative Listeners and Events.---------\\
    public SnakeFrame(){

            JFrame frame= new JFrame("Le Snake");
            ImageIcon imm = new ImageIcon(getClass().getResource
        ("/res/default.png"));
            Image background = imm.getImage();
            defaultpanel = new BackgroundPanel(background, BackgroundPanel.ACTUAL,
                    1.0f, 0.5f);
            frame.add(defaultpanel);
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            double larghezza = screenSize.getWidth();
            double altezza = screenSize.getHeight();
            frame.setBounds(((int)larghezza/4),((int)altezza/4),800, 600);
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            ImageIcon imageIcon = new ImageIcon(getClass().getResource("/res/Snake-icon.png"));
            Image icon = imageIcon.getImage();
            frame.setIconImage(icon);
            frame.setResizable(false);
            frame.setLayout(new GridLayout());
            JMenuBar menuBar = new JMenuBar();
            JMenu menu = new JMenu("Menu");
            menuBar.add(menu);
            menuBar.setBounds(1, 1, frame.getWidth(),frame.getHeight()/25);
            JMenuItem close = new JMenuItem("Exit");

            close.addActionListener(new ActionListener(){

                @Override
                public void actionPerformed(ActionEvent e) {

                    System.exit(0);
                }
            });

            menu.add(start);
            menu.add(close);
            frame.setJMenuBar(menuBar);

            frame.pack();

        }
//-------------------------Frame initialization ended.-----------------------\\

}

我现在能够使用defaultpanel.setVisible(false)更改SnakeFrame的背景;但即使我将其设置为真,也应该显示的黑色彩色标签面板不可见。我怎样才能看到它?谢谢。

1 个答案:

答案 0 :(得分:3)

一些一般性意见:

  1. 你为什么要创建第二帧?通常游戏是在自己的框架中进行的吗?你有一个菜单,允许你改变游戏的选项,这是通过显示模态JDialog完成的。然后你有一个&#34;开始&#34;通过向现有框架添加面板来启动游戏的按钮。

  2. 不要在框架上使用ComponentListener。无需处理componentHidden。

  3. 为什么你有game()方法?我甚至不会在您的代码中看到您调用该方法的位置。只需将actionListener添加到类的构造函数中的“开始”菜单项即可。保持菜单项的创建和actionListener在同一代码块中的分配,这样我们就不需要遍历整个类来查找组件的所有相关属性。

  4.   

    当我点击&#34;开始游戏&#34;按钮(JMenuItem)它打开一个带有线程的新JFrame来玩游戏。

    这是错误的。你不应该开始一个单独的线程。应在Event Dispatch Thread(EDT)上创建所有Swing组件。因此,基本上应该从ActionListener中调用代码,因为所有事件代码都在EDT上执行。

      

    看起来他唯一听到的命令是&#34; EXIT_ON_CLOSE&#34;作为DefaultCloseOperation,甚至不是&#34; DISPOSE_ON_CLOSE&#34;正在努力。

    这些是您为框架设置的属性。然后,当用户点击&#34; X&#34;根据属性,框架顶部/右侧的按钮将关闭框架。当您直接调用frame.dispose()或System.exit()时,这些属性不起作用。

    GameThread gamethread = new GameThread(frame,gameFrame);
    

    你为什么把框架传递给你的其他班级?如果你的目标是关闭原始框架。然后在创建另一帧后关闭框架。事实上,为什么你甚至引用了游戏框架#34;这里。如果你有另一个创建框架组件的类,它也应该创建框架。

    pullThePlug(frame);
    

    此代码不执行任何操作。您尝试关闭框架后调用此方法。

    一般来说,由于代码不完整,我无法遵循您的逻辑。但是作为一般规则,应用程序应该只包含一个JFrame。隐藏/显示多个帧不是想要看到的体验。当新游戏开始时,您应该只刷新现有框架的内容窗格。