簡體   English   中英

當我調整JFrame的大小時,Java Canvas停止繪制

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM