awt - Java: repeated calls to paintAll hangs program -


i'm implementing video capture in java program creating bufferedimages @ user-defined interval (for testing, 100ms), , using images make movie file. jframe trying record includes dashboard-like interface contained jlayeredpane. jframe has 2 canvas3ds. i'm telling each of these 3 things render or paint own linkedblockingdeque<bufferedimage>, , combine them later. dashboard set render every dashboardframerepaintfrequency frames.

thread capturethread = new thread(new runnable() {     public void run() {         final object lock = new object();             final thread capturedashboard = new thread(new runnable() {                 public void run() {                     while (m_iscapturingmovie) {                         synchronized (lock) {                             try {                                 lock.wait();                             } catch (interruptedexception e) {                                 e.printstacktrace();                             } {                                 system.err.println("calling getdashboardimage");                                 m_unsaveddash.add(getdashboardimage(m_dashboard.getwidth(), m_dashboard.getheight(), bufferedimage.type_int_argb));                                 system.err.println("capturedashboard returned calling m_unsaveddash.add...");                             }                         }                     }                 }             });             capturedashboard.start();              while (m_iscapturingmovie) {                 starttime = system.currenttimemillis();                 capturecanvases();                 if (++framecount > dashboardframerepaintfrequency) {                     framecount = 0;                     synchronized (lock) {                         lock.notify();                     }             }             endtime = system.currenttimemillis();             millistosleep = capturedelayinmillis - (endtime - starttime);             if (millistosleep > 0) {                 try {                     thread.sleep(millistosleep);                 } catch (interruptedexception e) {                     e.printstacktrace();                 }             }         }         synchronized (capturedashboard) {         capturedashboard.notify();         }     } }); 

i've found after 15-20 notify()s, program locks - stops recording canvases, stops responding keyboard input.. can still change window has focus, , buttons (such x button close window) still change visual state mouse rollover or clicking, don't execute commands.

from console output, seems capturedashboard thread, after 15-20 iterations, not return getdashboardimage method:

private bufferedimage getdashboardimage(int width, int height, int type) {     bufferedimage dashimg = new bufferedimage(m_dashboard.getwidth(), m_dashboard.getheight(), type);     graphics2d g = dashimg.creategraphics();     m_dashboard.paintall(g);     g.dispose();      return getscaledimage(width, height, dashimg); }  private bufferedimage getscaledimage(int width, int height, bufferedimage original) {     bufferedimage scaled = new bufferedimage(width, height, original.gettype());      affinetransform @ = new affinetransform();     at.scale((double) scaled.getwidth() / original.getwidth(), (double) scaled.getheight() / original.getheight());     affinetransformop scaleop;     if (at.getscalex() + at.getscaley() > 2.0) {         scaleop = new affinetransformop(at, affinetransformop.type_bicubic); // better quality enlargement     } else {         scaleop = new affinetransformop(at, affinetransformop.type_bilinear); // better quality ensmallment     }      scaled = scaleop.filter(original, scaled);     original.flush();     return scaled; } 

any ideas? i've been working @ few days , i'm stumped.

the problem needed call paintall awt dispatch thread.

so instead of:

m_dashboard.paintall(g); 

i needed have:

final graphics2d g = dashimg.creategraphics();  eventqueue.invokelater(new runnable() {     public void run () {         m_dashboard.paintall(g);     } }); 

this, however, caused program "get ahead of itself" , return bufferedimage before had been painted to, if program under heavy load. account this, added following:

final graphics2d g = dashimg.creategraphics(); final syncobj lock = new syncobj();  eventqueue.invokelater(new runnable() {     public void run () {         m_dashboard.paintall(g);         lock.donotify();     } });  lock.dowait(); g.dispose(); 

where syncobj simple:

class syncobj {     private boolean condition = false;     private object obj = new object();      public void dowait() {         synchronized (obj) {             while (!condition) {                 try {                     obj.wait();                 } catch (interruptedexception e) {                     e.printstacktrace();                 }             }             condition = false;         }     }      public void donotify() {         synchronized (obj) {             condition = true;             obj.notify();         }     } } 

Comments