Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 重新绘制不会更新屏幕_Java_Swing_Jpanel_Paint_Repaint - Fatal编程技术网

Java 重新绘制不会更新屏幕

Java 重新绘制不会更新屏幕,java,swing,jpanel,paint,repaint,Java,Swing,Jpanel,Paint,Repaint,我想重新粉刷我的屏幕。到目前为止,它所做的只是在第一个屏幕上显示一个圆点,这个圆点应该是头部所在的位置。这很好,但是我在我的代码中写了,我希望每秒钟将头部向下移动10个像素。我正在打印头部应该位于的位置,在命令提示符中显示y值确实在增加。然而,在我的屏幕上,头部没有移动 我尝试过使用revalidate方法,尝试过扩展canvas类而不是jframe,尝试过为paint方法使用不同的类,尝试过用paintComponent方法替换paint方法。正如你可能知道的那样,我对任何与java绘画相关的

我想重新粉刷我的屏幕。到目前为止,它所做的只是在第一个屏幕上显示一个圆点,这个圆点应该是头部所在的位置。这很好,但是我在我的代码中写了,我希望每秒钟将头部向下移动10个像素。我正在打印头部应该位于的位置,在命令提示符中显示y值确实在增加。然而,在我的屏幕上,头部没有移动

我尝试过使用revalidate方法,尝试过扩展canvas类而不是jframe,尝试过为paint方法使用不同的类,尝试过用paintComponent方法替换paint方法。正如你可能知道的那样,我对任何与java绘画相关的东西都不太了解。我试着读懂这些超类,但它们太复杂了,我无法理解。我也试过在没有睡眠声明的情况下跑步。这无关紧要

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

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;
    }
}
Snake类:Screenobject的子类,头部和身体的父类。此类设置对象的方向

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;
    }
}
Head类:snake的子类,应该是snake链接列表的第一个对象

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);
    }

}
第一件事:

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

是的,您只发布了必要的信息,但是对于一个类,您仍然使用了太多的类,理想情况下,您的所有代码都可以放在一个类中

我没能在不省略代码的情况下使它变得更短

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

现在,我可以看到你已经尝试创建了它,并且正在改进,所以我将发布一个例子,说明你未来的问题中所期望的是什么,以便你将来提出更好的问题

话虽如此,我们还是去回答你的问题吧


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

  • 删除
    while(true)
    语句以支持Swing计时器,以防止阻塞事件调度线程(EDT)

  • 将程序放在EDT上,请参见第2点

  • 对于
    JFrame
    JPanel

  • 去掉方向的“幻数”,并使用
    enum
    来处理此问题,因此代码更具可读性,因为我们都知道
    TOP
    应该将其移动到顶部,但我们不知道
    1
    应该将其移动到顶部

  • 使用
    Shape
    API在
    JPanel
    上绘制形状,如中所示

  • 我还建议您使用
    camelCase
    命名方法,这样
    rungame()
    就变成了
    rungame()
    ,因为它更易于阅读,其他方法也是如此。给他们起个更有意义的名字,比如
    hoofd
    ,我不知道那是什么,如果我没有上下文单独阅读,就很难说出它是什么类型的对象


  • 导入java.awt.BorderLayout;
    导入java.awt.Color;
    导入java.awt.Dimension;
    导入java.awt.Graphics;
    导入java.awt.Graphics2D;
    导入java.awt.event.ActionListener;
    导入java.awt.geom.Rectangle2D;
    导入javax.swing.JButton;
    导入javax.swing.JFrame;
    导入javax.swing.JPanel;
    导入javax.swing.SwingUtilities;
    导入javax.swing.Timer;
    公营蛇类游戏{
    私有JFrame;
    私家蛇;
    私人JPanel按钮板;
    私有JButton[]按钮;//我们的按钮数组
    私人定时器;
    私人指导;
    //此枚举将用于确定蛇的方向。
    私有枚举方向{
    上、左、下、右
    }
    公共静态void main(字符串[]args){
    //我们使用Java8Lambda表达式将程序放在EDT上。
    SwingUtilities.invokeLater(()->newsnakegame().createAndShowGUI());
    }
    私有void createAndShowGUI(){
    frame=newjframe(getClass().getSimpleName());
    snake=新蛇();
    buttonsPane=新的JPanel();
    按钮=新的JButton[Direction.values().length];
    对于(int i=0;i{//再次使用Java 8 lambda表达式
    //我们为我们设定了当前的方向
    
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.ActionListener;
    import java.awt.geom.Rectangle2D;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class SnakeGame {
        private JFrame frame;
        private Snake snake;
        private JPanel buttonsPane;
        private JButton[] buttons; // Our array of buttons
        private Timer timer;
        private Direction currentDirection;
    
        // This enum will be used to determine the direction the snake will take.
        private enum Direction {
            TOP, LEFT, BOTTOM, RIGHT
        }
    
        public static void main(String[] args) {
            // We place our program on the EDT using Java 8 lambda expressions.
            SwingUtilities.invokeLater(() -> new SnakeGame().createAndShowGUI());
        }
    
        private void createAndShowGUI() {
            frame = new JFrame(getClass().getSimpleName());
            snake = new Snake();
            buttonsPane = new JPanel();
            buttons = new JButton[Direction.values().length];
    
            for (int i = 0; i < buttons.length; i++) {
                buttons[i] = new JButton(Direction.values()[i].toString()); // We create a JButton with the current value of the direction
                buttons[i].addActionListener(listener); // We set their ActionListeners
                buttonsPane.add(buttons[i]); // And add them to the buttonsPane
            }
    
            currentDirection = Direction.RIGHT; // We set a default direction
            timer = new Timer(1000, listener); // And start our Swing Timer
    
            // We add our components and then pack the frame, after that we start the timer.
            frame.add(snake);
            frame.add(buttonsPane, BorderLayout.SOUTH);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setVisible(true);
            timer.start();
        }
    
        // Our ActionListener for moving the snake
        private ActionListener listener = e -> { // Using Java 8 lambda expressions again
            // We set the current direction using a ternary, if the source of the event is
            // the timer we leave the current direction as is
            // otherwise we set it to the direction from the button clicked
            currentDirection = e.getSource().equals(timer) ? currentDirection : Direction.valueOf(e.getActionCommand());
            snake.move(currentDirection); // And we call the move method
        };
    
        @SuppressWarnings("serial")
        class Snake extends JPanel {
            private int xPos;
            private int yPos;
            private static final int SPEED = 10; // We set the speed as a constant (10 pixels at a time) in any direction
    
            // We determine the movement direction
            public void move(Direction direction) {
                switch (direction) {
                case TOP:
                    yPos -= SPEED;
                    break;
                case LEFT:
                    xPos -= SPEED;
                    break;
                case BOTTOM:
                    yPos += SPEED;
                    break;
                case RIGHT:
                    xPos += SPEED;
                    break;
                }
                this.repaint(); // And repaint the snake
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g;
                g2d.setColor(Color.DARK_GRAY);
                g2d.fill(new Rectangle2D.Double(xPos, yPos, 10, 10)); // We draw a rectangle using the Shape API
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(300, 300); // We set the preferredSize of the JPanel to 300 x 300
            }
        }
    }