【问题标题】:Swing application does not display anythingSwing 应用程序不显示任何内容
【发布时间】:2021-09-30 23:12:45
【问题描述】:

我目前正在尝试使用 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);
        }
    }

【问题讨论】:

  • 您似乎没有将Game 面板添加到框架中。
  • Swing 不是线程安全的,你很“狂野”while-loop 会导致很多问题。 MouseInfo 并不是监视鼠标位置的最佳选择,因为您需要将坐标从屏幕上下文转换为组件上下文,最好使用各种MouseListeners。我还建议不要覆盖paint,并且作为一般偏好,请改为覆盖paintComponent。所有这些都需要改变你思考问题的方式
  • 在任何情况下,square.act()circle.act() 都不应该在绘画方法中。您无法控制绘画何时发生;系统会。各种你无法控制的事情都可能触发绘画,包括移动窗口,甚至将鼠标移到窗口上方。
  • @khelwood 我不敢相信我忘记添加了

标签: java swing awt


【解决方案1】:

有关程序结构的一些改进以及更好地使用Swing 工具,请参阅以下代码。注意 cmets:

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 2017-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多