JButton并没有出现在JFrame中

时间:2018-03-17 21:10:44

标签: java swing jbutton frame

我目前正在研究一个学校项目,我必须在那里编写游戏蛇的代码。现在我完成了最大的部分,并试图让游戏变得更好。我尝试放置一个JButton来启动游戏(startPlay)。然而,按钮不会出现,我无法弄清楚原因。有人可以帮忙吗?提前致谢!!

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.*;

public class Main extends JPanel implements ActionListener, KeyListener{


    public static int field[][]; 

    public static GenerateField genField; 
    public static Snake snake;
    public static GenerateFood food;
    public static GenerateBarrier barrier;

    public int difficultness;

    public static int widthField; 
    public static int heightField;

    public static TimerTask move, genBarriers;
    public static Timer snakeTimer, barrierTimer;

    public JButton startPlay;

    public static boolean gameStarted;

    public Main ()
    {
        startPlay = new JButton("Starte Spiel");
        startPlay.setBounds(0,0,300,200);
        startPlay.addActionListener(this);
        add(startPlay);

        difficultness = 15;
        gameStarted = false;

        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);

        widthField = 150;
        heightField = 95;

        genField = new GenerateField();
        snake = new Snake();
        food = new GenerateFood();
        barrier = new GenerateBarrier();

        barrierTimer = new Timer("Timer");
        snakeTimer = new Timer("Timer");

        genBarriers = new TimerTask() {
            @Override
            public void run() {
                barrier.clearBarrier();
                barrier.multiSpawnBarrier(difficultness);
            }
        };

        move = new TimerTask()
        {
            public void run()
            {

                if(GenerateField.inGame)
                {
                    snake.moveSnake();
                    repaint();
                }
            }
        };

    }

    private static void startGame()
    {
        genField.generateField();
        field = genField.getField();
        snake.generateSnake(40, 75);
        food.spawnFood();
        snakeTimer.schedule(move,0,50);
        barrierTimer.schedule(genBarriers, 0, 25000);
    }



    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        frame.setSize(1520,1000);
        frame.getContentPane().add(new Main());
        frame.setLocationRelativeTo(null);
        frame.setBackground(Color.LIGHT_GRAY);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    @Override
    public void paint(Graphics g)
    {
        if(gameStarted) {
            for (int iy = 0; iy < heightField; iy++) {
                for (int ix = 0; ix < widthField; ix++) {
                    //Zeichnet schwarzen Hintergrund
                    if (genField.field[iy][ix] == 0) {
                        g.setColor(Color.BLACK);
                        g.fillRect(ix * 10, iy * 10, 10, 10);

                    }
                    //Zeichnet die Grenze an den Rändern
                    if (genField.field[iy][ix] == 1) {
                        g.setColor(Color.red);
                        g.fillRect(ix * 10, iy * 10, 10, 10);

                    }
                    //Zeichnet die Schlange
                    if (genField.field[iy][ix] == 2) {
                        g.setColor(Color.green);
                        g.fillRect(ix * 10, iy * 10, 10, 10);
                    }
                    //Zeichnet das "Futter"
                    if (genField.field[iy][ix] == 3) {
                        g.setColor(Color.orange);
                        g.fillRect(ix * 10, iy * 10, 10, 10);
                    }
                    //Zeichte die Hindernisse
                    if (genField.field[iy][ix] == 4) {
                        g.setColor(Color.blue);
                        g.fillRect(ix * 10, iy * 10, 10, 10);
                    }

                }
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {

        startPlay.setVisible(false);
        startGame();
        gameStarted = true;
    }

    @Override
    public void keyPressed (KeyEvent e)
    {
        int code = e.getKeyCode();
        if ( code == KeyEvent.VK_LEFT)
        {

            if (snake.mRight == false)
            {
                snake.mLeft = true;
                snake.mRight = false;
                snake.mUp = false;
                snake.mDown = false;
            }

        }

        if ( code == KeyEvent.VK_RIGHT)
        {

            if (snake.mLeft == false)
            {
                snake.mLeft = false;
                snake.mRight = true;
                snake.mUp = false;
                snake.mDown = false;
            }

        }

        if ( code == KeyEvent.VK_UP)
        {

            if (snake.mDown == false)
            {
                snake.mLeft = false;
                snake.mRight = false;
                snake.mUp = true;
                snake.mDown = false;
            }

        }

        if ( code == KeyEvent.VK_DOWN)
        {

            if (snake.mUp == false)
            {
                snake.mLeft = false;
                snake.mRight = false;
                snake.mUp = false;
                snake.mDown = true;
            }

        }
    }

    @Override
    public void keyReleased(KeyEvent e)
    {

    }

    @Override
    public void keyTyped(KeyEvent e)
    {

    }
}

1 个答案:

答案 0 :(得分:2)

即时问题

Static, Static - everywhere

过度使用static会突出您的设计问题。 static不是你的朋友,你应该谨慎而明智地使用它。

你试图将所有鸡蛋放在一个篮子里。这只会让国家管理更难处理。

相反,首先将菜单和游戏分成不同的类并相互独立地管理它们。

然后,您可以使用CardLayout来管理不同视图之间的导航。

以下是演示如何使用CardLayout执行解耦导航

的简单示例
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
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.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                CardLayout cardLayout = new CardLayout();
                JPanel base = new JPanel(cardLayout);

                NavigationController controller = new NavigationController() {
                    @Override
                    public void show(Screen screen) {
                        cardLayout.show(base, screen.name());
                    }
                };

                base.add(new MainMenuPane(controller), Screen.MENU.name());
                base.add(new GamePane(controller), Screen.GAME.name());

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(base);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public enum Screen {
        MENU, GAME;
    }

    public interface NavigationController {
        public void show(Screen scren);
    }

    public class MainMenuPane extends JPanel {

        public MainMenuPane(NavigationController controller) {
            setLayout(new GridBagLayout());
            JButton start = new JButton("Start");
            add(start);
            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    controller.show(Screen.GAME);
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }


    public class GamePane extends JPanel {

        private NavigationController controller;

        public GamePane(NavigationController controller) {
            this.controller = controller;
            setLayout(new GridBagLayout());
            add(new JLabel("Ready Player One"));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }
}

您需要修复的其他任何事情

  • 不要使用KeyListener,使用Key bindings instead,他们会以更可靠的方式解决与焦点相关的问题
  • 您违反了paint链的要求,这是您当前问题的一部分 - 请参阅Performing Custom PaintingPainting in Swing了解有关绘画如何运作以及如何使用的更多详细信息应该用它
  • Swing是单线程而非线程安全 - 有关详细信息,请参阅Concurrency in Swing。从本质上讲,java.util.Timer的使用存在脏读/写的风险,这可能导致任何数量的奇怪且几乎不可能诊断问题。相反,您应该使用Swing Timer代替,这将确保您所做的任何更新都是在事件调度线程的上下文中进行的。您还应该使用单个Timer并在简单的更新过程中安排所有内容 - 这通常会提高性能