简体   繁体   中英

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). 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 is not your friend, you should use it sparingly and wisely.

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.

The following is simple example to demonstrate how you might use CardLayout to perform decoupled navigation

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
  • 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
  • Swing is single thread AND not thread safe - see Concurrency in Swing for more details. 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. 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. You should also be using a single Timer and scheduling everything in a simple update pass - this will generally improve performance

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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