Java 停止JPanel';从绘制背景开始绘制组件方法

Java 停止JPanel';从绘制背景开始绘制组件方法,java,swing,jframe,Java,Swing,Jframe,我正在用Java做一个蛇游戏 为了提高效率,我只画改变了这个框架的位置(蛇的第一个和最后一个单元格) 这是我的密码: public class GameCanvas extends JPanel { private final List<GameChange> changes; public GameCanvas() { setBackground(Color.darkGray); changes = new ArrayList<>(); } pu

我正在用Java做一个蛇游戏

为了提高效率,我只画改变了这个框架的位置(蛇的第一个和最后一个单元格)

这是我的密码:

public class GameCanvas extends JPanel {

private final List<GameChange> changes;

public GameCanvas() {
    setBackground(Color.darkGray);

    changes = new ArrayList<>();
}

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    Graphics2D g2d = (Graphics2D) g;

    for (GameChange change : changes) {
        Vector2 pos = change.position;
        int val = change.value;

        if (val != 0) g2d.setColor(Color.BLACK);
        else g2d.setColor(Color.WHITE); //getBackground();

        g2d.fillRect(GameWindow.pixelSize * pos.x,GameWindow.pixelSize * pos.y, GameWindow.pixelSize, GameWindow.pixelSize);
    }

    changes.clear();
}

public void applyChanges(List<GameChange> changes) {
    this.changes.addAll(changes);
    repaint();
}
}

当蛇移动时,我只绘制变化,但如果框架自动重新绘制,蛇不会消失。它似乎在工作,但我不确定使用
getGraphics()
方法是否安全。

这显然不是你的游戏,但它可能有助于消除你需要做一些特殊事情来提高绘画效率的想法

  • 要创建蛇,请按住左键并拖出一条曲线
  • 然后松开按钮,在面板中移动鼠标,观察
    “snake”
    跟随鼠标
  • 您可以随时通过拖动鼠标添加更多点
这只需创建一个点列表并在它们之间绘制一条线即可。当鼠标移动时,它将删除第一个点并将当前点添加到端点。paint方法只是对每次鼠标移动的列表进行迭代,并绘制所有线条,给出移动的外观

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class SimpleSnake extends JPanel {
    JFrame frame = new JFrame("Simple Snake");
    List<Point> snake = new ArrayList<>();
    final static int WIDTH = 500;
    final static int HEIGHT = 500;
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> new SimpleSnake());
    }
    public SimpleSnake() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addMouseMotionListener(new MyMouseListener());
        setBackground(Color.white);
        frame.add(this);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(WIDTH, HEIGHT);
    }
    
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (snake.size() < 2) {
            return;
        }
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setColor(Color.black);
        g2d.setStroke(new BasicStroke(3)); // line thickness
        Point start = snake.get(0);
        for(int i = 1; i < snake.size(); i++) {
            Point next = snake.get(i);
            g2d.drawLine(start.x, start.y, next.x, next.y);
            start = next;
        }
        g2d.dispose();
    }
    
    public class MyMouseListener extends MouseAdapter {
        public void mouseDragged(MouseEvent me) {
            snake.add(new Point(me.getX(), me.getY()));
            repaint();
        }
        
        public void mouseMoved(MouseEvent me) {
            if(snake.isEmpty()) {
                return;
            }
            snake.remove(0);
            snake.add(new Point(me.getX(), me.getY()));
            repaint();
        }       
    }
}
这其中有一个明显的(也许还有另一个不那么明显的)缺陷。点的数量是恒定的,但由于点随着鼠标移动速度的加快而展开,因此点之间的线更长,因此蛇的大小会扩展和收缩。但这与绘画无关,而是与鼠标移动的速度有关

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class SimpleSnake extends JPanel {
    JFrame frame = new JFrame("Simple Snake");
    List<Point> snake = new ArrayList<>();
    final static int WIDTH = 500;
    final static int HEIGHT = 500;
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> new SimpleSnake());
    }
    public SimpleSnake() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addMouseMotionListener(new MyMouseListener());
        setBackground(Color.white);
        frame.add(this);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(WIDTH, HEIGHT);
    }
    
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (snake.size() < 2) {
            return;
        }
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setColor(Color.black);
        g2d.setStroke(new BasicStroke(3)); // line thickness
        Point start = snake.get(0);
        for(int i = 1; i < snake.size(); i++) {
            Point next = snake.get(i);
            g2d.drawLine(start.x, start.y, next.x, next.y);
            start = next;
        }
        g2d.dispose();
    }
    
    public class MyMouseListener extends MouseAdapter {
        public void mouseDragged(MouseEvent me) {
            snake.add(new Point(me.getX(), me.getY()));
            repaint();
        }
        
        public void mouseMoved(MouseEvent me) {
            if(snake.isEmpty()) {
                return;
            }
            snake.remove(0);
            snake.add(new Point(me.getX(), me.getY()));
            repaint();
        }       
    }
}
import java.awt.BasicStroke;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Point;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.SwingUtilities;
公共类SimpleSnake扩展了JPanel{
JFrame=新JFrame(“简单蛇”);
List snake=new ArrayList();
最终静态整数宽度=500;
最终静态内部高度=500;
公共静态void main(字符串[]args){
调用器(()->new SimpleSnake());
}
公共SimpleSnake(){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addMouseMotionListener(新的MyMouseListener());
挫折地面(颜色:白色);
框架。添加(此);
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
@凌驾
公共维度getPreferredSize(){
返回新尺寸(宽度、高度);
}
@凌驾
公共组件(图形g){
超级组件(g);
if(snake.size()<2){
返回;
}
Graphics2D g2d=(Graphics2D)g.create();
g2d.setColor(Color.black);
g2d.设定行程(新基本行程(3));//线厚度
点开始=snake.get(0);
对于(inti=1;i
这不是
paintComponent
的工作方式,调用时,您需要更新整个组件。你“可以”做三角洲的过程,但它需要油漆旧的地区(清除有什么)和新的地区。您也可以考虑使用其中一种方法,它允许您指定要更新的区域以使其高效——不必担心效率。您可以轻松地重新绘制蛇的3个单元格,没有问题。您不需要显式删除任何内容。您只需不断地重新绘制整个背景,其中应包括新位置。但是,通过额外的逻辑,可以仅使用剪辑区域绘制已更改的区域。但是对于这么简单的东西,它是没有必要的。