【问题标题】:Java JFrame repaint() flickeringJava JFrame repaint() 闪烁
【发布时间】:2017-01-18 17:38:51
【问题描述】:

我正在从 Ian Cinnamon 的《为邪恶的天才编程视频游戏》一书中学习 Java,还有这款赛车游戏。我了解它是如何工作的,但我有一个问题:每次刷新(Thread.sleep) 时它都会闪烁。我该如何解决?顺便说一句,我看到了 4 年前的帖子,但由于我是初学者,所以我不明白如何做,我认为我不应该恢复它。

这是代码,提前谢谢你:

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

public class RadicalRacing extends JFrame {

    final int WIDTH = 900, HEIGHT = 650;
    double p1Speed = .5, p2Speed = .5;
    final int UP = 0, RIGHT = 1, DOWN = 2, LEFT = 3;
    int p1Direction = UP;
    int p2Direction = UP;
    Rectangle left = new Rectangle(0, 0, WIDTH / 9, HEIGHT);
    Rectangle right = new Rectangle((WIDTH / 9) * 8, 0, WIDTH, HEIGHT);
    Rectangle top = new Rectangle(0, 0, WIDTH, HEIGHT / 9);
    Rectangle bottom = new Rectangle(0, (HEIGHT / 9) * 8, WIDTH, HEIGHT / 9);
    Rectangle center = new Rectangle((int) ((WIDTH / 9) * 2.5), (int) ((HEIGHT / 9) * 2.5), (int) ((WIDTH / 9) * 5), (HEIGHT / 9) * 4);
    Rectangle obstacle = new Rectangle(WIDTH / 2, (int) ((HEIGHT / 9) * 7), WIDTH / 10, HEIGHT);
    Rectangle obstacle2 = new Rectangle(WIDTH / 3, (int) ((HEIGHT / 9) * 5), WIDTH / 10, HEIGHT / 4);
    Rectangle obstacle3 = new Rectangle(2 * (WIDTH / 3), (int) ((HEIGHT / 9) * 5), WIDTH / 10, HEIGHT / 4);
    Rectangle obstacle4 = new Rectangle(WIDTH / 3, HEIGHT / 9, WIDTH / 10, HEIGHT / 9);
    Rectangle obstacle5 = new Rectangle(WIDTH / 2, (int) ((HEIGHT / 9) * 1.5), WIDTH / 30, HEIGHT / 4);
    Rectangle finish = new Rectangle(WIDTH / 9, (HEIGHT / 2) - HEIGHT / 9, (int) ((WIDTH / 9) * 1.5),
            HEIGHT / 70);
    Rectangle lineO = new Rectangle(WIDTH / 9, HEIGHT / 2, (int) ((WIDTH / 9) * 1.5) / 2, HEIGHT / 140);
    Rectangle lineI = new Rectangle(((WIDTH / 9) + ((int) ((WIDTH / 9) * 1.5) / 2)),
            (HEIGHT / 2) + (HEIGHT / 10), (int) ((WIDTH / 9) * 1.5) / 2, HEIGHT / 140);
    Rectangle p1 = new Rectangle(WIDTH / 9, HEIGHT / 2, WIDTH / 30, WIDTH / 30);
    Rectangle p2 = new Rectangle(((WIDTH / 9) + ((int) ((WIDTH / 9) * 1.5) / 2)), (HEIGHT / 2)
            + (HEIGHT / 10), WIDTH / 30, WIDTH / 30);

    public RadicalRacing() {
        super("Radical Racing");
        setSize(WIDTH, HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

        Move1 m1 = new Move1();
        Move2 m2 = new Move2();
        m1.start();
        m2.start();
    }

    public void paint(Graphics g) {
        super.paint(g);
        //draw the background
        g.setColor(Color.DARK_GRAY);
        g.fillRect(0, 0, WIDTH, HEIGHT);
        //green border
        g.setColor(Color.GREEN);
        //now, using rectangles, draw it
        g.fillRect(left.x, left.y, left.width, left.height);
        g.fillRect(right.x, left.y, left.width, left.height);
        g.fillRect(top.x, top.y, top.width, top.height);
        g.fillRect(bottom.x, bottom.y, bottom.width, bottom.height);
        g.fillRect(center.x, center.y, center.width, center.height);
        g.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);
        g.fillRect(obstacle2.x, obstacle2.y, obstacle2.width, obstacle2.height);
        g.fillRect(obstacle3.x, obstacle3.y, obstacle3.width, obstacle3.height);
        g.fillRect(obstacle4.x, obstacle4.y, obstacle4.width, obstacle4.height);
        g.fillRect(obstacle5.x, obstacle5.y, obstacle5.width, obstacle5.height);
        g.setColor(Color.WHITE);
        g.fillRect(lineO.x, lineO.y, lineO.width, lineO.height);
        g.fillRect(lineI.x, lineI.y, lineI.width, lineI.height);
        g.setColor(Color.YELLOW);
        g.fillRect(finish.x, finish.y, finish.width, finish.height);

        g.setColor(Color.BLUE);
        g.fillRect(p1.x, p1.y, p1.width, p1.height);
        g.setColor(Color.RED);
        g.fillRect(p2.x, p2.y, p2.width, p2.height);
    }

    private class Move1 extends Thread implements KeyListener {

        public void run() {
            addKeyListener(this);
            while (true) {
                try {
                    repaint();
                    if (p1.intersects(right) || p1.intersects(left)
                            || p1.intersects(top) || p1.intersects(bottom)
                            || p1.intersects(obstacle) || p1.intersects(obstacle2)
                            || p1.intersects(obstacle3) || p1.intersects(obstacle4)
                            || p1.intersects(obstacle5) || p1.intersects(p2)) {
                        p1Speed = -4;
                    }
                    if (p1.intersects(center)) {
                        p1Speed = -2.5;
                    }
                    if (p1Speed <= 5) {
                        p1Speed += .2;
                    }
                    if (p1Direction == UP) {
                        p1.y -= (int) (p1Speed);
                    }
                    if (p1Direction == DOWN) {
                        p1.y += (int) (p1Speed);
                    }
                    if (p1Direction == LEFT) {
                        p1.x -= (int) (p1Speed);
                    }
                    if (p1Direction == RIGHT) {
                        p1.x += (int) (p1Speed);
                    }

                    Thread.sleep(75);
                } catch (Exception e) {
                    break;
                }
            }
        }

        public void keyPressed(KeyEvent event) {
        }

        public void keyReleased(KeyEvent event) {
        }

        public void keyTyped(KeyEvent event) {
            if (event.getKeyChar() == 'a') {
                p1Direction = LEFT;
            }
            if (event.getKeyChar() == 'd') {
                p1Direction = RIGHT;
            }
            if (event.getKeyChar() == 's') {
                p1Direction = DOWN;
            }
            if (event.getKeyChar() == 'w') {
                p1Direction = UP;
            }
        }
    }

    private class Move2 extends Thread implements KeyListener {

        public void run() {
            addKeyListener(this);
            while (true) {
                try {
                    repaint();
                    if (p2.intersects(right) || p2.intersects(left)
                            || p2.intersects(top) || p2.intersects(bottom)
                            || p2.intersects(obstacle) || p2.intersects(obstacle2)
                            || p2.intersects(obstacle3) || p2.intersects(obstacle4)
                            || p2.intersects(obstacle5) || p2.intersects(p1)) {
                        p2Speed = -4;
                    }
                    if (p2.intersects(center)) {
                        p2Speed = -2.5;
                    }
                    if (p2Speed <= 5) {
                        p2Speed += .2;
                    }
                    if (p2Direction == UP) {
                        p2.y -= (int) (p2Speed);
                    }
                    if (p2Direction == DOWN) {
                        p2.y += (int) (p2Speed);
                    }
                    if (p2Direction == LEFT) {
                        p2.x -= (int) (p2Speed);
                    }
                    if (p2Direction == RIGHT) {
                        p2.x += (int) (p2Speed);
                    }

                    Thread.sleep(75);
                } catch (Exception e) {
                    break;
                }
            }
        }

        public void keyPressed(KeyEvent event) {
        }

        public void keyReleased(KeyEvent event) {
        }

        public void keyTyped(KeyEvent event) {
            if (event.getKeyChar() == 'h') {
                p2Direction = LEFT;
            }
            if (event.getKeyChar() == 'k') {
                p2Direction = RIGHT;
            }
            if (event.getKeyChar() == 'j') {
                p2Direction = DOWN;
            }
            if (event.getKeyChar() == 'u') {
                p2Direction = UP;
            }
        }
    }

    public static void main(String[] args) {
        new RadicalRacing();
    }
}

【问题讨论】:

  • 您尝试了什么(例如,移除或更改睡眠)?发生了什么?你预计会发生什么?
  • 不要覆盖paint - 覆盖轻量级组件的paintComponent(例如JPanel)。见docs.oracle.com/javase/tutorial/uiswing/painting/closer.html
  • 如果这对你有帮助,请你批准这个冷笑。

标签: java


【解决方案1】:

您需要的是双缓冲。 正在发生的事情是程序绘制了一个屏幕,从而产生了闪烁的效果。 双缓冲是一种概念,您可以在屏幕上绘制画布,然后在画布准备就绪时将其放在前一个画布之上。

大多数 Swing 组件都使用 setDoubleBuffered 内置了此功能。

您也可以使用 BufferStrategies 或创建自己的类。

查看这篇文章了解更多信息: How to double buffer question

【讨论】:

  • 谢谢!!!我找到了这个关于双缓冲的教程,现在它可以工作了。 youtube.com/watch?v=4T3WJEH7zrc
  • @Albert 很高兴,如果这是正确答案,请批准。
  • @Albert 能否请您批准答案,以便其他人在搜索时更容易找到。
猜你喜欢
  • 2015-06-08
  • 2015-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-18
  • 1970-01-01
  • 2016-10-29
  • 1970-01-01
相关资源
最近更新 更多