简体   繁体   English

停止 JPanel 的 paintComponent 方法绘制背景

[英]Stop JPanel's paintComponent method from painting the background

I'm making a snake game in Java.我正在 Java 中制作蛇游戏。

To make it efficient, I only paint the positions that have changed this frame (the first and last cells of the snake).为了提高效率,我只绘制改变了这一帧的位置(蛇的第一个和最后一个单元格)。

Here's my code:这是我的代码:

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

The only problem is that the paintComponent method is repainting the background and the middle of the snake is disappearing.唯一的问题是paintComponent方法正在重新绘制背景并且蛇的中间正在消失。

The black cell is the new head and the white one is the one that I'm deleting.黑色单元格是新头,白色单元格是我要删除的那个。 The middle cell was supposed to be black.中间的牢房应该是黑色的。

EDIT:编辑:

Everyone is telling me to draw the whole map but I really want to work on performance.每个人都告诉我画整个 map 但我真的很想提高性能。 This is what I've done so far:这是我到目前为止所做的:

private void paintChanges(List<GameChange> changes) {
    Graphics2D g2d = (Graphics2D) getGraphics();

    // Here I paint only the changes
}

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;

    // Here I paint everything
}

When the snake moves I only paint the changes but if the the frame gets repainted automatically the snake wont disappear.当蛇移动时,我只绘制变化,但如果框架自动重新绘制,蛇不会消失。 It appears to be working but I'm not sure if it's safe to use the getGraphics() method.它似乎正在工作,但我不确定使用getGraphics()方法是否安全。

This is obviously not your game but it may help dispel the notion that you need to do something special to increase painting efficiency.这显然不是你的游戏,但它可能有助于消除你需要做一些特别的事情来提高绘画效率的观念。

  • To create the snake, hold the left button down and drag out a curved line.要创建蛇,请按住左键并拖出一条曲线。
  • then release the button and just move the mouse around in the panel and watch the "snake" follow the mouse.然后释放按钮并在面板中移动鼠标并观察"snake"跟随鼠标。
  • you can add more points by dragging the mouse at any time.您可以随时通过拖动鼠标添加更多点。

This works by simply creating a list of points and drawing a line in between them.这可以通过简单地创建一个点列表并在它们之间画一条线来实现。 As the mouse moves it removes the first point and adds the current one to the end.当鼠标移动时,它会删除第一个点并将当前点添加到末尾。 The paint method just iterates thru the list for each mouse movement and draws all the lines, giving the appearance of movement. paint 方法只是为每次鼠标移动遍历列表并绘制所有线条,从而呈现出移动的外观。

There is one obvious (and perhaps other, not so obvious) flaws with this.这有一个明显的(也许还有其他不那么明显的)缺陷。 The number of points is constant but the snake expands and contracts in size since the points are spread out as the mouse moves faster so the lines between the points are longer.点的数量是恒定的,但蛇的大小expandscontracts ,因为随着鼠标移动得更快,点会分散开,因此点之间的线会更长。 But that is not related to painting but to the speed of the mouse movement.但这与绘画无关,而是与鼠标移动的速度有关。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM