Java闪烁的JPanel

时间:2013-12-11 12:21:01

标签: java swing jpanel flicker

我遇到了与JPanel中的闪烁​​有关的问题。我不知道为什么但是窗户里的球不时闪烁。我尝试了几个东西,比如双缓冲,BufferStrategy,Canvas但它们都没有用。 主要思想是使用线程池,当球绑定几次时删除它并创建另一个线程。同时必须有很多球。

这是我的代码:

public class BallWindow extends JFrame {

private static final long serialVersionUID = 1L;
private BallPanel panel;
private final int WINDOW_WIDTH = 700;
private final int WINDOW_HEIGHT = 700;

public BallWindow() {
    super("Balls");
    this.panel = new BallPanel();
    this.panel.setPreferredSize(new Dimension(WINDOW_WIDTH, WINDOW_HEIGHT));
    this.add(panel);
    this.pack();
}

public int getPanelWidth() {
    return panel.getWidth();
}

public int getPanelHeight() {
    return panel.getHeight();
}

public void initGUI() {
    this.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setVisible(true);
}
//Balls have to tell to the window to paint them, just once
public void drawMe(BallThread ball) {
    this.panel.drawMe(ball);
}
}


class BallPanel extends JPanel {

private static final long serialVersionUID = 1L;
private Queue<BallThread> queue;

public BallPanel() {
     this.queue = new LinkedList<>();
}

public void drawMe(BallThread ball) {
    this.queue.add(ball);
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    while(queue.peek() != null) {
        queue.poll().drawBall(g2);
    }
} 
}

这是球(它们是线程):

public class BallThread implements Runnable {

private int x;
private int y;
private int dx;
private int dy;
private int diameter;
private int bounces;
private BallWindow window;

public BallThread(int x, int y, int dx, int dy, int diameter, int lBounces, BallWindow window) {
    this.x = x;
    this.y = y;
    this.dx = dx;
    this.dy = dy;
    this.diameter = diameter;
    this.bounces = lBounces;
    this.window = window;
}

public int getX() {
    return x;
}

public void setX(int x) {
    this.x = x;
}

public int getY() {
    return y;
}

public void setY(int y) {
    this.y = y;
}

public void setWindow(BallWindow window) {
    this.window = window;
}

public void drawBall(Graphics2D g) {
    g.setColor(Color.BLUE);
    g.fillOval(this.x, this.y, this.diameter, this.diameter);
}

private void move() {
    this.x += this.dx;
    this.y += this.dy;
    bounce();
    this.window.drawMe(this);
}

private void bounce() {
    if(this.x < 0) {
        this.x = 0;
        this.dx = -dx;
        this.bounces--;
    } else if(this.x+diameter > this.window.getPanelWidth()) {
        this.x = this.window.getPanelWidth()-diameter;
        this.dx = -dx;
        this.bounces--;
    }

    if(this.y < 0) {
        this.y = 0;
        this.dy = -dy;
        this.bounces--;
    } else if(this.y+diameter > this.window.getPanelHeight()) {
        this.y = this.window.getPanelHeight()-diameter;
        this.dy = -dy;
        this.bounces--;
    }
}

@Override
public void run() {
    while(this.bounces > 0) {
        this.move();
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    GameLoop.decreaseThreadsWorking();
}

}

游戏循环:

public class GameLoop {

private final int N_BALLS = 20;
private static int nThreadsNow = 0;
private BallWindow window;
private ExecutorService poolThreads;

public GameLoop() {
    this.poolThreads = Executors.newFixedThreadPool(N_BALLS);
    gameLoop();
}

private void gameLoop() {
    window = new BallWindow();
    window.initGUI();

    while(true) {
        while(GameLoop.nThreadsNow < this.N_BALLS) {
            BallThread ball = BallFactory.getInstance().getBall(window);
            this.poolThreads.execute(ball);
            GameLoop.nThreadsNow++;
        }
        window.repaint();

        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public static void decreaseThreadsWorking() {
    GameLoop.nThreadsNow--;
}

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

1 个答案:

答案 0 :(得分:2)

这里有很多强耦合,看起来奇怪的是球可重复地将自己添加到要绘制的队列中。

拿出那块,让框架按照计划重新绘制。这包括重新绘制所有球,而不是试图跟上不断增加的队列。