微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java Graphics drawImage 在 JPanel 上有时很慢有时会暂停

如何解决Java Graphics drawImage 在 JPanel 上有时很慢有时会暂停

  • 操作系统:Windows 10 专业版
  • Java:OpenJDK 11.0.7

我创建了一个可以读取视频文件并在 JPanel 上播放的程序。目前我遇到了两个问题。

  1. Graphics.drawImage(Image,x,y,null) 有时很慢(大于 50 毫秒),有时很快(小于 5 毫秒)
  2. 在Graphics.drawImage的速度小于5毫秒期间,我有时仍然发现在JPanel上播放的视频暂停了50毫秒以上,这是肉眼可以感觉到的。

那么,有什么建议吗?

下面是关键代码和日志

public class UI {
  private static final Logger log = LoggerFactory.getLogger(UI.class);
  ...
  private reentrantreadwritelock postVideoFrameReadWriteLock       = new reentrantreadwritelock();
  private reentrantreadwritelock.ReadLock  postVideoFrameReadLock  = postVideoFrameReadWriteLock.readLock();
  private reentrantreadwritelock.WriteLock postVideoFrameWriteLock = postVideoFrameReadWriteLock.writeLock();
  private BufferedImage _lcdPanelImage ;
  private JPanel lcdPanel;
  ...
  public UI() {
    ...
    lcdPanel = new JPanel() {
      @Override
      public void paintComponent(Graphics g) {
        // super.paintComponent(g);
        long timer0 = System.currentTimeMillis(),timer1=0,timer2=-1,timer3 = 0;
        postVideoFrameReadLock.lock();
        if (_lcdPanelImage != null) {
          timer1 = System.currentTimeMillis();
          g.drawImage(_lcdPanelImage,null);
          timer2 = System.currentTimeMillis();
        }
        postVideoFrameReadLock.unlock();
        timer3 = System.currentTimeMillis();
        int diff = (int) (timer2-timer1);
        if (diff >5) {
          log.trace("    paint total cost:{} ms,drawImage cost: {} ms",(timer3- timer0),(timer2-timer1));
        }
      }
    };
    lcdPanel.setDoubleBuffered(true);
    ...
  }

  private void postOnLcdPanel(BufferedImage bufferedImage) {
    long timer0 = System.currentTimeMillis();
    postVideoFrameWriteLock.lock();
    _lcdPanelImage = bufferedImage;
    postVideoFrameWriteLock.unlock();
    long timer1 = System.currentTimeMillis();
    lcdPanel.repaint();
    long timer2 = System.currentTimeMillis();
    int diff1 = (int) (timer1 - timer0);
    int diff2 = (int) (timer2 - timer1);
    if (diff1 >0 || diff2 > 0) {
        log.trace(String.format("set and lock cost:%4d ms,repaint cost:%4d ms",diff1,diff2
        ));
    }

  }


  @Singleton
  private class displayVideoOnLcdPanelWorker implements Runnable {
    private final Logger log = LoggerFactory.getLogger(displayVideoOnLcdPanelWorker.class);
    private void tsleep(long lsec) {
        try {
            Thread.sleep(lsec);
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
        }
    }
    @Override
    public void run() {
        log.debug("displayVideoOnLcdPanelWorker starts ....");
        boolean running = true;
        long timer0 = System.currentTimeMillis(),playVideoCount = 0;
        final int targetSleepms = 25;
        float fps = 0;
        while (running) {
            try {
                //log.trace("videoQueue size:  {} .....",videoQueue.size());

                if (videoWaitPlayingQueue.size() == 0) {
                    Thread.sleep(5);
                    continue;
                }
                BufferedImage image = videoWaitPlayingQueue.poll(1,TimeUnit.MILLISECONDS);
                long timer1 = System.currentTimeMillis();
                postOnLcdPanel(image);
                long timer3 = System.currentTimeMillis();
                playVideoCount++;
                int playCost = (int) (timer3 - timer1);
                int diffSleep = targetSleepms -playCost;
                if (playCost > 10) {
                    log.trace(String.format("Play cost:%4d,videoWaitPlayingQueue:%d",playCost,videoWaitPlayingQueue.size()));
                }
                tsleep(diffSleep > 3? diffSleep: 3);
            } catch (InterruptedException ex) {
                log.error(ex.getMessage(),ex);
                break;
            }
        }
        log.debug("displayVideoOnLcdPanelWorker stops ....");
    }
  }

}

以下是相关日志

19:19:34.321 TRACE UI$displayVideoOnLcdPanelWorker: Play cost: 236,videoWaitPlayingQueue:200
19:19:40.858 TRACE                             UI:     paint total cost:227 ms,drawImage cost: 227 ms
19:19:40.858 TRACE                             UI: set and lock cost:   1 ms,repaint cost:   0 ms
19:19:50.798 TRACE                             UI:     paint total cost:182 ms,drawImage cost: 182 ms
19:19:52.596 TRACE                             UI: set and lock cost:   0 ms,repaint cost:   1 ms
19:19:52.710 TRACE                             UI:     paint total cost:114 ms,drawImage cost: 114 ms
19:19:52.710 TRACE                             UI: set and lock cost:   2 ms,repaint cost:   0 ms
19:20:26.387 TRACE                             UI:     paint total cost:101 ms,drawImage cost: 101 ms
19:20:28.086 TRACE                             UI:     paint total cost:105 ms,drawImage cost: 105 ms
19:20:28.087 TRACE                             UI: set and lock cost:   3 ms,repaint cost:   0 ms
19:20:39.319 TRACE                             UI: set and lock cost:   0 ms,repaint cost:   1 ms
19:21:05.526 TRACE                             UI:     paint total cost:284 ms,drawImage cost: 284 ms
19:21:07.556 TRACE                             UI:     paint total cost:112 ms,drawImage cost: 112 ms
19:21:07.556 TRACE                             UI: set and lock cost:   3 ms,repaint cost:   0 ms
19:21:32.687 TRACE                             UI:     paint total cost:129 ms,drawImage cost: 129 ms
19:21:32.687 TRACE                             UI: set and lock cost:   1 ms,repaint cost:   0 ms
19:21:37.217 TRACE                             UI: set and lock cost:   0 ms,repaint cost: 290 ms
19:21:37.217 TRACE UI$displayVideoOnLcdPanelWorker: Play cost: 290,videoWaitPlayingQueue:200
19:21:41.779 TRACE                             UI: set and lock cost:   0 ms,repaint cost: 302 ms

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。