重涂不会更新屏幕

时间:2019-06-03 20:57:12

标签: java swing jpanel paint repaint

我想重新粉刷我的屏幕。到目前为止,它所做的只是显示第一个屏幕,该屏幕上带有一个应该放置头部的点。很好,但是我已经在代码中编写了想要将头每秒降低10像素的操作。我正在打印打印头应该位于的位置,并且在命令提示符下显示y值确实在增加。但是在我的屏幕上,头部没有动。

我尝试使用revalidate方法,尝试扩展canvas类而不是jframe,我尝试仅针对paint方法使用不同的类,我尝试将paint方法替换为paintComponent方法。正如您可能会告诉我的那样,我对与Java绘画有关的任何内容都不太了解。我尝试阅读这些超类,但是它们太复杂了,以至于我无法理解。我还尝试了在没有睡眠声明的情况下运行。没关系。

主类: 此类包含开始运行蛇游戏的主要方法。

import java.util.concurrent.TimeUnit;

public class Main{

    public static void main(String[] args) throws InterruptedException {
        Main programma = new Main();
        programma.rungame();
    }

void rungame() throws InterruptedException {
        AllGUIElements gui = new AllGUIElements();
        gui.gui();
        while (true) {
            TimeUnit.SECONDS.sleep(1);
            gui.setGameScreen();
        }
    }
}

AllGUIElements类:此类创建一个包含新面板的新框架。此面板是使用paintComponent绘制的。 setGameScreen更新头部的位置,并应该重新绘制屏幕。

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

public class AllGUIElements extends JPanel {

    private JFrame frame;
    private JPanel panel;

    private int screen;

    Snake hoofd = new Head(new Point(30,30),3,null);

    void gui() throws InterruptedException {

        frame = new JFrame("Snake Game");
        panel = new AllGUIElements();
        panel.setBackground(Color.GRAY);
        panel.setSize(1000,500);
        frame.setSize(1000,500);
        frame.add(panel);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

void setGameScreen() {
    repaint();
        if (hoofd.getDirection() == 1) {
            hoofd.setPosition(new Point(hoofd.getPosition().x, hoofd.getPosition().y-10));
        }
        if (hoofd.getDirection() == 2) {
            hoofd.setPosition(new Point(hoofd.getPosition().x+10, hoofd.getPosition().y));

        }
        if (hoofd.getDirection() == 3) {
            hoofd.setPosition(new Point(hoofd.getPosition().x, hoofd.getPosition().y+10));

        }
        if (hoofd.getDirection() == 4) {
            hoofd.setPosition(new Point(hoofd.getPosition().x-10, hoofd.getPosition().y));
        }
}

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
            g.setColor(Color.DARK_GRAY);
            g.fillRect(0, 0, 1000, 10);
            g.fillRect(0, 0, 10, 500);
            g.fillRect(990, 0, 10, 500);
            g.fillRect(0, 490, 1000, 10);

            g.setColor(Color.GREEN);
            g.fillRect(hoofd.getPosition().x, hoofd.getPosition().y, 10, 10);
    }

}

Screenobject类:Snake和Food的父类(由于没有必要而不会发布),它返回头部,身体部位和食物的位置。

import java.awt.*;

public class Screenobject{

    Point pos;

    Screenobject(Point pos){
        this.pos = pos;
    }

    void setPosition(Point pos){
        this.pos = pos;
    }

    Point getPosition() {
        return pos;
    }
}

蛇类:Screenobject的子级,Head和Body的父级。此类设置对象的方向。

import java.awt.*;

public class Snake extends Screenobject{

    int direction;
    //directions:
    //1 = up
    //2 = right
    //3 = down
    //4 = left

    Snake nextpart;

    Snake(Point pos, int direction, Snake nextpart){
        super(pos);
        this.direction = direction;
        this.nextpart = nextpart;
    }

    int getDirection() {
        return direction;
    }
}

头类:蛇的子类,应该是蛇链表的第一个对象。

import java.awt.*;

public class Head extends Snake{
    Head(Point pos, int direction, Snake nextpart){
        super(pos, direction, nextpart);
    }
}

身体阶层:蛇的孩子阶层,每食用一种食物就会增长。

import java.awt.*;

public class Body extends Snake{
    Body(Point pos, int direction, Snake nextpart){
        super(pos, direction, nextpart);
    }

}

1 个答案:

答案 0 :(得分:1)

第一件事:

  

我使用“分而治之”的方法只发布必要的信息

是的,您只发布了必要的信息,但是https://jshint.com/docs/options/仍然使用了太多的类,理想情况下,所有代码都可以放在一个类中。

  

在没有省略代码以使其运行的情况下,我没有设法使其变得更短。

这就是我们要求MRE的想法,您应该创建一个全新的程序来隔离问题,在您的情况下,这是:在某个方向上移动形状,并继续在该方向上移动。

现在,我可以看到您已经尝试创建它并对其进行改进,因此,我将发布一个示例,说明您将来遇到的问题是什么,以便您将来提出更好的问题。

话虽这么说,让我们去回答你的问题。


这是一个示例,其中少于100行代码(不包括注释)解决了代码中的以下问题:

  1. 删除了while(true)语句,以使用Swing计时器,以防止阻塞事件调度线程(EDT)

  2. 将程序放在EDT上,请参阅MCVE / MRE

  3. 的第2点
  4. 使用JFrame#pack()方法,而不是同时为setSize(...)JFrame的{​​{1}}手动设置方法

  5. 摆脱了指示的“幻数” ,并为此使用了JPanel,因此代码更易读,因为我们都知道{{ 1}}应该将其移到顶部,但是我们不知道enum应该将其移到顶部。

  6. 使用TOP API在1上绘制形状,如this answer

  7. 所示。
  8. 我还建议您使用Shape命名您的方法,以使JPanel变得camelCase,因为它更易于阅读,与其他方法一样。并给它们起更有意义的名称,例如rungame(),我不知道那是什么,如果我没有上下文单独阅读它,将很难说出它是什么类型的对象。


runGame()

对于Java 7及以下版本,或者对于您不想使用lambda表达式或对您来说太困难,上面的代码会产生以下结果,请检查此答案的第二点,它显示了如何放置程序在没有Lambda表达式的EDT上,this answer也展示了如何在不包含lambda表达式的情况下编写hoofd

您可以使用一个简单的可运行示例,它是完整的,可验证的,最小的,这就是我们在以后的问题中对您的期望。

this answer