[英]Java Canvas when I resize the JFrame, the canvas stops drawing
更詳細地講,我在JFrame上附加了一個componentResized事件(該事件包含畫布,什么都沒有),在該事件中,調用一個方法來相應地設置畫布的邊界。 這很好,除了在我調整畫布大小時,它什么都沒有顯示。 我只是看到JFrame的背面。 一旦我停止調整JFrame的大小,畫布就會再次繪制良好。
public class MyCanvas implements ComponentListener {
public static void main(String[] args) {
new MyCanvas("MyCanvas",new Dimension(300,300));
}
private static final int frameRate = 30;
private JFrame frame;
private JPanel panel;
private Canvas canvas;
private BufferStrategy strategy;
private int delta;
private boolean running = false;
private int frameCount = 0;
public MyCanvas(String name, Dimension size) {
frame = new JFrame(name);
panel = (JPanel) frame.getContentPane();
canvas = new Canvas();
frame.setSize(size);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(size);
panel.setLayout(null);
canvas.setBounds(0,0,size.width,size.height);
panel.add(canvas);
canvas.setIgnoreRepaint(true);
frame.setResizable(true);
frame.pack();
frame.addComponentListener(this);
canvas.createBufferStrategy(2);
strategy = canvas.getBufferStrategy();
running = true;
frame.setVisible(true);
long lastLoopTime = 0;
while (running) {
frameCount++;
delta = (int) (System.currentTimeMillis() - lastLoopTime);
lastLoopTime = System.currentTimeMillis();
Graphics2D graphics = (Graphics2D) strategy.getDrawGraphics();
graphics.setColor(Color.black);
graphics.fillRect(0,0,getSize().width,getSize().height);
graphics.dispose();
strategy.show();
try {
Thread.sleep(1000/frameRate);
} catch (InterruptedException e) {}
}
}
public final Dimension getSize() {
return frame.getSize();
}
public final void setSize(Dimension size) {
frame.setSize(size);
canvas.setBounds(0,0,size.width,size.height);
}
public synchronized void componentResized(ComponentEvent e) {
setSize(frame.getSize());
}
public synchronized void componentHidden(ComponentEvent e) {
// unused
}
public synchronized void componentShown(ComponentEvent e) {
// unused
}
public synchronized void componentMoved(ComponentEvent e) {
// unused
}
}
編輯
經過一段時間的代碼調整后,我想出了一個解決方案:
public class MyCanvas {
public static void main(String[] args) {
new MyCanvas("MyCanvas",new Dimension(400,400));
}
private static final int frameRate = 1000 / 30;
private JFrame frame;
private JPanel panel;
private int delta;
private long lastLoopTime;
private boolean running = false;
private int frameCount = 0;
private BufferedImage backBuffer = null;
private int lastPaintFrame = -1;
public MyCanvas(String name, Dimension size) {
frame = new JFrame(name);
panel = new JPanel() {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
redraw(g);
}
};
frame.setContentPane(panel);
frame.setSize(size);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(size);
panel.setLayout(null);
frame.setResizable(true);
running = true;
frame.setVisible(true);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
backBuffer = new BufferedImage(screenSize.width,screenSize.height,BufferedImage.TYPE_INT_ARGB);
lastLoopTime = System.nanoTime();
while (running) {
long thisLoopTime = System.nanoTime();
delta = (int) ((thisLoopTime - lastLoopTime) / 1000000);
draw(backBuffer.getGraphics());
frameCount++;
lastLoopTime = thisLoopTime;
redraw(panel.getGraphics());
try {
Thread.sleep(1000/30);
} catch (InterruptedException e) {}
}
}
private final void redraw(Graphics g) {
if (g != null && backBuffer != null) {
g.drawImage(backBuffer,0,0,null);
}
}
int x = 30;
public final void draw(Graphics g) {
g.setColor(Color.darkGray);
g.fillRect(0,0,getSize().width,getSize().height);
g.setColor(Color.gray);
g.fillRect(0,0,500,500);
g.setColor(Color.blue);
g.fillRect(x,30,300,300);
x++;
}
public final Dimension getSize() {
return frame.getSize();
}
public final void setSize(Dimension size) {
frame.setSize(size);
}
}
但是,這還不能完全解決,因為它仍然具有奇數個圖形故障,盡管並非始終如一,但似乎只有在從面板的paintComponent方法調用重繪時才會出現。 這些故障表現為奇怪的彩色矩形(通常是黑色或灰色),然后迅速消失。 我真的不確定這可能是什么...也許雙緩沖有問題嗎? 順便說一句,如果我在paintComponent中拋出了運行時異常,它會完美運行。
如果您想提出一個新的問題,請告訴我。
我找到了解決方案:繪制和更新的不同循環:
public class MyCanvas {
public static void main(String[] args) {
new MyCanvas("MyCanvas",new Dimension(400,400));
}
private static final int frameRate = 1000 / 30;
private JFrame frame;
private JPanel panel;
private int delta;
private long lastLoopTime;
private volatile boolean running = false;
private int frameCount = 0;
public MyCanvas(String name, Dimension size) {
frame = new JFrame(name);
panel = new JPanel() {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
if (running) repaint();
}
};
frame.setContentPane(panel);
frame.setSize(size);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(size);
panel.setLayout(null);
frame.setResizable(true);
running = true;
frame.setVisible(true);
lastLoopTime = System.nanoTime();
new Thread(()->{
while (running) {
update();
frameCount++;
try {
Thread.sleep(frameRate);
} catch (InterruptedException e) {}
}
},"Game Loop").start();
}
int x = 30;
public final void update() {
x++;
}
public final void draw(Graphics g) {
g.setColor(Color.darkGray);
g.fillRect(0,0,getSize().width,getSize().height);
g.setColor(Color.gray);
g.fillRect(0,0,500,500);
g.setColor(Color.blue);
g.fillRect(x,30,300,300);
}
public final Dimension getSize() {
return frame.getSize();
}
public final void setSize(Dimension size) {
frame.setSize(size);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.