简体   繁体   English

JButton没有出现在JFrame中

[英]JButton doesn't show up in JFrame

I'm currently working on a schoolproject, where I have to code the game snake. 我目前正在做一个学校项目,必须在其中编写游戏蛇的代码。 Now I`m finished with the biggest part and tryed to make the game menue. 现在,我完成了最大的部分,并尝试制作游戏菜单。 I tryed to place a JButton for starting the game (startPlay). 我试图放置一个JButton来启动游戏(startPlay)。 However, the button won't show up and I can't figure out why. 但是,该按钮不会显示,我也不知道为什么。 Can someone help? 有人可以帮忙吗? Thanks in advance!! 提前致谢!!

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)
    {

    }
}

Immediate Problem 眼前的问题

静态,静态-无处不在

The over use of static highlights issues with your design. 过度使用static突出设计的问题。 static is not your friend, you should use it sparingly and wisely. static不是您的朋友,您应该谨慎而明智地使用它。

You're trying to put all your eggs in single basket. 您正在尝试将所有鸡蛋放在一个篮子里。 This is just going to make the state management harder to handle. 这只会使状态管理更难处理。

Instead, start by separating your menu and game into separate classes and managing them independently of each other. 取而代之的是,首先将菜单和游戏分成不同的类,然后彼此独立地进行管理。

This then allows you to use a CardLayout to manage the navigation between the different views. 然后,您可以使用CardLayout来管理不同视图之间的导航。

The following is simple example to demonstrate how you might use CardLayout to perform decoupled navigation 下面是一个简单的示例,以演示如何使用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);
        }

    }
}

Every thing else you'll need to fix 您需要修复的所有其他内容

  • Don't use KeyListener , use Key bindings instead , they will fix the focus related issues in a more reliable way 不要使用KeyListener而是使用Key绑定 ,它们将以更可靠的方式解决与焦点相关的问题
  • You're violating the requirements of the paint chain, which is part of your immediate problem - See Performing Custom Painting and Painting in Swing for more details about how painting works and how you should work with it 您违反了paint链的要求,这是您当前的问题之一-有关绘画的工作方式以及如何使用它的详细信息,请参见在Swing中 执行自定义绘画绘画。
  • Swing is single thread AND not thread safe - see Concurrency in Swing for more details. Swing是单线程而不是线程安全的-有关更多详细信息,请参见Swing中的并发 Essentially the use of java.util.Timer is running the risk of dirty read/writes which could lead to any number of weird and near impossible to diagnose issues. 本质上,使用java.util.Timer冒着读/写脏的风险,这可能导致任何数量的怪异且几乎无法诊断问题。 Instead, you should be using Swing Timer instead, which will ensure that any updates you make are made within the context of the Event Dispatching Thread. 相反,您应该使用Swing Timer ,它可以确保您所做的任何更新都是在事件调度线程的上下文内进行的。 You should also be using a single Timer and scheduling everything in a simple update pass - this will generally improve performance 您还应该使用单个Timer并通过简单的更新过程安排所有时间-这通常会提高性能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM