Swing 应用程序不显示任何内容

Swing application does not display anything

我目前正在尝试使用 Java Swing 和 AWT 创建一个简单的躲避游戏。现在,我已经创建了一些简单的大纲代码来测试我尝试创建的概念是否可行。我已经使用多态性来尝试创建多种类型的对象 Enemy,它们将具有单独的 draw() 和 act() 代码,使它们由 AWT 绘制,然后根据它们的类型以特定的方式移动。我将 Graphics2D 导入到 draw() 以尝试使代码更可重用。然后我使用 while 循环 运行 Java Swing/AWT 内置线程来允许敌人的动画。然而,当我 运行 代码时,它编译正确,但只显示一个空白屏幕。

我该如何解决?

这是我使用的代码。涉及鼠标的代码不完整。

Game.java

import javax.swing.*;
import java.awt.*;

public class Game extends JPanel {
    //FPS Setup
    int fps = 30; //FPS
    int secConst = 1000; //milliseconds per second
    int frmConst = (int) Math.floor((double) secConst / (double) fps); //delay between frames

    //FRAME Setup
    String appName = "Dodge This"; //app name
    int frameW = 500; //frame width
    int frameH = 500; //frame height

    //ENEMY TEST
    //TO REPLACE WITH ARRAY OF ENEMIES
    Square square = new Square(0, 100, 0, 10);
    Circle circle = new Circle(50, 50, 10);
    boolean lose = true;

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //TO REPLACE WITH LOOP THROUGH ARRAY OF ENEMIES
        square.act();
        square.draw(g2d);
        circle.act();
        circle.draw(g2d);

        if (this.lose) {
            g2d.setColor(new Color(0, 0, 0));
            g2d.setFont(new Font("Sans Serif", Font.PLAIN, 32));
            g2d.drawString("You Lose", 0, 0); //TO REPLACE WITH RANDOMIZED LOSE MESSAGE
            }
        }

    public static void main(String [] args) throws InterruptedException {
        Game game = new Game();

        JFrame frame = new JFrame(game.appName);
        frame.setSize(game.frameW, game.frameH);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        while (true) {
            if (MouseInfo.getPointerInfo().getLocation().equals(new Point(game.circle.getX(), game.circle.getY())) && MouseInfo.getPointerInfo().getLocation().equals(new Point(game.square.getX(), game.square.getY()))) {
                game.lose = true;
                break;
                }

            game.repaint();
            Thread.sleep(game.frmConst);
            }
        }
    }

Enemy.java

import java.awt.*;

public abstract class Enemy {
    public int x;
    public int y;
    public double direction;
    public double speed;

    //BASIC METHODS
    public void setX(int x) {
        this.x = x;
        }

    public void setY(int y) {
        this.y = y;
        }
    
    public void setDirection(double direction) {
        this.direction = direction;
        }
    
    public void setSpeed(double speed) {
        this.speed = speed;
        }

    public int getX() {
        return this.x;
        }

    public int getY() {
        return this.y;
        }
    
    public double getDirection() {
        return this.direction;
        }
    
    public double getSpeed() {
        return this.speed;
        }

    //METHODS FOR UNIQUE ENEMIES
    public abstract void act();

    public abstract void draw(Graphics2D g2d);
    }

Square.java

import java.awt.*;

public class Square extends Enemy{
    //CONSTRUCTORS
    public Square() {
        this.x = 0;
        this.y = 0;
        this.direction = (int) Math.floor(Math.random() * 8) * 45;
        this.speed = (int) Math.floor(Math.random() * 15);
        } //default constructor

    public Square(int x, int y) {
        this.x = x;
        this.y = y;
        this.direction = (int) Math.floor(Math.random() * 8) * 45;
        this.speed = (int) Math.floor(Math.random() * 15);
        }
    
    public Square(int x, int y, double direction) {
        this.x = x;
        this.y = y;
        this.direction = direction;
        this.speed = (int) Math.floor(Math.random() * 15);
        }
    
    public Square(int x, int y, double direction, double speed) {
        this.x = x;
        this.y = y;
        this.direction = direction;
        this.speed = speed;
        }

    //ACTIONS
    @Override
    public void act() {
        this.x += Math.floor(this.speed * (Math.cos(this.direction)));
        this.y += Math.floor(this.speed * -1 * (Math.sin(this.direction)));
        }
    
    @Override
    public void draw(Graphics2D g2d) {
        g2d.setColor(new Color(100, 100, 100));
        g2d.fillRect(this.x, this.y, 50, 50);
        }
    }

Circle.java

import java.awt.*;

public class Circle extends Enemy{
    double mouseX;
    double mouseY;

    //CONSTRUCTORS
    public Circle() {
        this.x = 0;
        this.y = 0;
        this.direction = 0;
        this.speed = 5;
        } //default constructor

    public Circle(int x, int y) {
        this.x = x;
        this.y = y;
        this.direction = 0;
        this.speed = 5; 
        }
    
    public Circle (int x, int y, int speed) {
        this.x = x;
        this.y = y;
        this.direction = 0;
        this.speed = speed;
        }

    //ACTIONS
    @Override
    public void act() {
        this.mouseX = MouseInfo.getPointerInfo().getLocation().getX();
        this.mouseY = MouseInfo.getPointerInfo().getLocation().getY();

        this.x += this.speed * Math.floor(Math.abs(this.y - this.mouseY) / Math.abs(this.x - this.mouseX));
        this.y += this.speed * -1 * Math.floor(Math.abs(this.x - this.mouseX) / Math.abs(this.y - this.mouseY));
        }
    
    @Override
    public void draw(Graphics2D g2d) {
        g2d.setColor(new Color(50, 50, 50));
        g2d.fillOval(this.x, this.y, 10, 10);
        }
    }

请参阅以下代码以了解程序结构的一些改进以及更好地使用 Swing 工具。注意评论:

import java.awt.*;
import javax.swing.*;

public class Game extends JPanel {
    //FPS Setup
    int fps = 3; // FPS (slow for testing)
    int secConst = 1000; //milliseconds per second
    int frmConst = secConst / fps; //delay between frames
    private Timer timer;

    String appName = "Dodge This"; //app name
    int frameW = 500, frameH = 500; //frame width and height

    Square square = new Square(0, 100, 0., 10.);
    Circle circle = new Circle(50, 50, 0., 10.);
    boolean lose = false; //the correct state at start ;

    //override  paintComponent rather than  paint
    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        square.draw(g2d);
        circle.draw(g2d);

        if (lose) {
            g2d.setColor(new Color(0, 0, 0));
            g2d.setFont(new Font("Sans Serif", Font.PLAIN, 32));
            g2d.drawString("You Lose", 0, 0);
        }
    }

    public void start(){
        //use swing timer to invoke game cycles
        if(timer != null && timer.isRunning()) {
            timer.stop();
        }

        timer = new Timer(frmConst, e->{
                if(lose) {
                    timer.stop();
                } else {
                    play();
                }
            }
        );

        timer.start();
    }

    public void play(){
        square.act();
        circle.act();
        //lose criteria (not sure what are you trying to check)
        if (MouseInfo.getPointerInfo().getLocation().equals(new Point(circle.getX(), circle.getY()))
                && MouseInfo.getPointerInfo().getLocation().equals(new Point(square.getX(), square.getY()))) {
            lose = true;
        }
        repaint();
    }

    public static void main(String [] args) throws InterruptedException {
        Game game = new Game();

        JFrame frame = new JFrame(game.appName);
        frame.setSize(game.frameW, game.frameH);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(game);// add game to frame

        game.start();
    }
}

abstract class Enemy {
    public int x,y;
    public double direction, speed;

    public Enemy(int x, int y, double speed) {
        this(x,y,0, speed);
    }

    public Enemy(int x, int y, double direction, double speed) {
        this.x = x;
        this.y = y;
        this.direction = direction;
        this.speed = speed;
    }

    //BASIC METHODS
    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void setDirection(double direction) {
        this.direction = direction;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public double getDirection() {
        return direction;
    }

    public double getSpeed() {
        return speed;
    }

    //METHODS FOR UNIQUE ENEMIES
    public abstract void act();

    public abstract void draw(Graphics2D g2d);
}

class Square extends Enemy{

    public Square(int x, int y, double direction, double speed) {
        super(x, y, direction, speed);
    }

    @Override
    public void act() {
        x += Math.floor(speed * Math.cos(direction));
        y += Math.floor(speed * -1 * Math.sin(direction));
    }

    @Override
    public void draw(Graphics2D g2d) {
        g2d.setColor(new Color(100, 100, 100));
        g2d.fillRect(x, y, 50, 50);
    }
}

class Circle extends Enemy{
    double mouseX, mouseY;

    public Circle(int x, int y, double direction, double speed) {
        super(x, y, direction, speed);
    }

    @Override
    public void act() {
        mouseX = MouseInfo.getPointerInfo().getLocation().getX();
        mouseY = MouseInfo.getPointerInfo().getLocation().getY();

        x += speed * Math.floor(Math.abs(y - mouseY) / Math.abs(x - mouseX));
        y += speed * -1 * Math.floor(Math.abs(x - mouseX) / Math.abs(y - mouseY));
    }

    @Override
    public void draw(Graphics2D g2d) {
        g2d.setColor(new Color(50, 50, 50));
        g2d.fillOval(x, y, 10, 10);
    }
}

(运行它在线here)