java - 我的 JFrame 闪烁

标签 java swing jframe repaint

我正在尝试制作一个简单的 Java 游戏 -- 驾驶汽车通过赛道。我的老师习惯于使用矩形之类的东西。我的问题是当我使用 repaint() 方法时,我的框架会闪烁。我试图在汽车改变方向时使用重绘方法,但没有任何效果。有什么建议吗?

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.net.URL;

import javax.swing.JFrame;


@SuppressWarnings("serial") 
public class MAP extends JFrame
{
    //the URL and Img designed for the images
    URL cLeft,cRight,cUp;
    Image img1,img2,img3;

    //these will keep track of each player’s speed:
    double p1Speed =.5, p2Speed =.5;

    //constant for the screen size and used for the drawing the terrain
    final int WIDTH = 900, HEIGHT = 650;

    //these are ints that represent directions:
    final int UP = 0, RIGHT = 1, DOWN = 2, LEFT = 3;
    //these will keep track of the player’s directions (default = up)
    int p1Direction = 0;

    //this is the rectangle for player 1’s (outer) car:
    Rectangle p1 = new Rectangle(WIDTH/9,HEIGHT/2, WIDTH/30,WIDTH/30);

    //draw the terrain
    Rectangle left = new Rectangle(0,0,WIDTH/9,HEIGHT);
    Rectangle right = new Rectangle((WIDTH/9)*9,0,WIDTH/9,HEIGHT);
    Rectangle top = new Rectangle(0,0,WIDTH, HEIGHT/9);
    Rectangle bottom = new Rectangle(0,(HEIGHT/9)*9,WIDTH,HEIGHT/9);
    Rectangle center = new Rectangle((int)((WIDTH/9)*2.5),(int)((HEIGHT/9)*2.5), (int)((WIDTH/9)*5),(HEIGHT/9)*4);

    //these obstacles will obstruct the path and make navigating harder
    Rectangle obstacle = new
    Rectangle(WIDTH/2,(int)((HEIGHT/9)*7),WIDTH/10,HEIGHT/9);
    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/30,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);

    //the constructor:
    public MAP() {

        //the following code creates the JFrame
        super("Radical Racing");
        setSize(WIDTH,HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        setResizable(false);

        try {
            cUp = this.getClass().getResource("carUp.jpg");
            cLeft = this.getClass().getResource("carLeft.jpg");
            cRight = this.getClass().getResource("carRight.jpg");
        } catch(Exception e) {
        }

        //attach the URLs to the images
        img1 = Toolkit.getDefaultToolkit().getImage(cUp);
        img2 = Toolkit.getDefaultToolkit().getImage(cLeft);
        img3 = Toolkit.getDefaultToolkit().getImage(cRight);

        repaint();
        Move1 m1 = new Move1();
        m1.start();
    }

    //this will draw the cars and the race track
    public void paint(Graphics g) {
        super.paint(g);

        //draw the background for the racetrack
        g.setColor(Color.DARK_GRAY);
        g.fillRect(0,0,WIDTH,HEIGHT);

        //when we draw, the border will be green
        g.setColor(Color.GREEN);

        //fill rectangle
        g.fillRect(left.x,left.y,left.width,left.height);
        g.fillRect(right.x,right.y,right.width,right.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,obstacle3.width,obstacle4.height);
        g.fillRect(obstacle5.x,obstacle5.y,obstacle5.width,obstacle5.height);

        //set the starting line color to white
        g.setColor(Color.WHITE);

        //now draw the starting line
        g.fillRect(lineO.x,lineO.y,lineO.width,lineO.height);
        g.fillRect(lineI.x,lineI.y,lineI.width,lineI.height);

        //set the color of the finish line to yellow
        g.setColor(Color.YELLOW);

        //now draw the finish line
        g.fillRect(finish.x,finish.y,finish.width,finish.height);

        //set the color to blue for p1
        g.setColor(Color.WHITE);

        //now draw the actual player
        g.fill3DRect(p1.x,p1.y,p1.width,p1.height,true);

        //draw the images for the player
        if(p1Direction==UP)
        g.drawImage(img1,p1.x,p1.y,this);
        if(p1Direction==LEFT)
            g.drawImage(img2,p1.x,p1.y,this);
        if(p1Direction==RIGHT)
    g.drawImage(img3,p1.x,p1.y,this);
    }

    private class Move1 extends Thread implements KeyListener {
        public void run() {
            //now, this should all be in an infinite loop, so the process
            //repeats
            addKeyListener(this);
            while(true) {
                //now, put the code in a try block. This will let the
                //program exit
                //if there is an error.

                try {
                    //first, refresh the screen:
                    repaint();
                    //increase speed a bit
                    //  if(p1Speed<=5)
                    //  p1Speed+=.2;
                    //p1.y-=(int) p1Speed;
                    if(p1.intersects(left) || p1.intersects(right) || p1.intersects(top) || p1.intersects(bottom) || p1.intersects(obstacle) || p1.intersects(obstacle2)|| p1.intersects(obstacle3) || p1.intersects(obstacle4) || p1.intersects(obstacle5)) {
                        p1Speed = -5;
                    }
                    //if the car hits the center, do the same as above
                    //but make the speed -2.5.
                    if(p1.intersects(center)) {
                        p1Speed = -5;
                    }
                    //increase speed a bit
                    if(p1Speed<=5)
                        p1Speed+=.2;
                    //these will move the player based on direction
                    if(p1Direction==UP) {
                        p1.y-=(int)p1Speed;
                        //repaint();
                    }
                    if(p1Direction==DOWN) {
                        p1.y+=(int)p1Speed;
                        //repaint();
                    }
                    if(p1Direction==LEFT) {
                        p1.x-=(int)p1Speed;
                        //repaint();
                    }
                    if(p1Direction==RIGHT) {
                        p1.x+=(int)p1Speed;
                        //repaint();
                    }
                    //this delays the refresh rate:
                    Thread.sleep(200);

                } catch(Exception e) {
                    //if there is an exception (an error), exit the loop.
                    break;
                }
            }
        }

        @Override
        public void keyPressed(KeyEvent arg0) {
            // TODO Auto-generated method stub
        }

        @Override
        public void keyReleased(KeyEvent arg0) {
            // TODO Auto-generated method stub
        }

        @Override
        public void keyTyped(KeyEvent event) {
            if(event.getKeyChar()=='a') {
                p1Direction = LEFT;
                repaint();
            }
            if(event.getKeyChar()=='s') {
                p1Direction = DOWN;
                repaint();
            }
            if(event.getKeyChar()=='d') {
                p1Direction = RIGHT;
                repaint();
            }
            if(event.getKeyChar()=='w') {
                p1Direction = UP;
                repaint();
            }
        }
    }
    //this starts the program by calling the constructor:
    public static void main (String[ ] args) {
        new MAP();
    }
}

最佳答案

不要直接在 JFrame 的 paint 方法中绘制。取而代之的是在 JPanel 或 JComponent 中绘制并覆盖其 paintComponent 方法,因为 Swing 默认情况下会进行双缓冲,这将使您能够利用这一点。

关于java - 我的 JFrame 闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8508371/

相关文章:

java - 在java中删除选定的图像

java - 按下 JButton 时 Swing 获取 JTextField

java - 如何将 JSONArray 分配给变量?

java - Akka BalancingDispatcher 配置

java - 自定义 ListView 滚动 - 仅 Imageviews

JavaFX2 : Nullpointer in AbstractTimer

java - 在一维中调整 JFrame 的大小

窗口打开时运行的 Java 方法

java - 从 swingWorker 处理框架

java - JsonMappingException : No suitable constructor found for type [simple type, 类 com.fasterxml.jackson.databind.node.ObjectNode]