我遇到了与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();
}
}
答案 0 :(得分:2)
这里有很多强耦合,看起来奇怪的是球可重复地将自己添加到要绘制的队列中。
拿出那块,让框架按照计划重新绘制。这包括重新绘制所有球,而不是试图跟上不断增加的队列。