2014-02-24 139 views
0

我目前正試圖讓我們的應用程序的UI變得輕量級,並且正在嘗試將重量級服務器調用移動到他們自己的線程中。然後,我使用Display.getDefault.asyncExec()來更新小部件,它完美地工作。正確刷新小部件?

我想在服務器調用返回時向用戶顯示動畫。到那時,我正在使用另一個線程,它在另一個Display.getDefault.asyncExec()中顯示動畫。這也有效......但以一種奇怪的方式。當我運行應用程序時,小部件會非常沉重地閃爍,並且有時屏幕不會更新。事情是,當我運行一個原型版本,即沒有主應用程序,只是一個裸露的SWT應用程序,它完美的作品。任何想法爲什麼發生這種情況

基本工作流程::

showAnimation = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       while(true){ 
        synchronized (this) { 
         try {      
          Thread.sleep(1000); 
          drawCircles(); // basically the animation, also called in a Display.getDefault().asyncExec() 
         } 
         catch (InterruptedException e) 
         { 
          // do nothing, because this thread is meant to be interrupted! 
          // and then, break out of the infinite loop         
          System.out.println("Interrupted"); 
          break; 
         } 
        }     
       }        
      } 
     }); 

invokeLater = new Thread(new Runnable(){ 
    @Override 
    public void run(){ 
     // do the data base call here 
     System.out.println("Got data!"); 
     if(showAnimation.isAlive()) 
     { 
      showAnimation.interrupt(); 
     } 
    } 
}); 

,並在我看來 - >

showAnimation.start(); 
invokeLater.start(); 

我簡要地想知道我是否應該增加動畫線程的優先級,只是爲了看看是否可行。它沒有(也沒有意義增加線程的優先級,而不是縮小應用程序的瓶頸)。

任何想法?

P.S:本drawCircles()代碼 - >

public void drawCircles(){ 
     Display.getDefault().asyncExec(new Runnable() {       
      @Override 
      public void run(){ 
       int radius = 100; 
       int maxX = radius ; 
       int maxY = radius ; 
       int direction=0;       
       int centerX = table.getBounds().width/2; 
       int centerY = table.getBounds().height/2;  
       System.out.println("Drawing"); 
       Image image = new Image(Display.getDefault(),table.getBounds().width,table.getBounds().height); 
       GC gc = new GC(image);        
       gc.setAntialias(SWT.ON); 
       gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); 
       //gc.drawLine(0, centerY, shell.getBounds().width, centerY); 
       //gc.drawLine(centerX, 0, centerX, shell.getBounds().height); 
       // 1st circle 
       gc.drawOval(centerX-radius/2, centerY-radius - radius/2, maxX, maxY); 
       // 2nd circle 
       gc.drawOval(centerX - 2*radius + radius/2, centerY - radius/2, maxX, maxY); 
       // 3rd circle 
       gc.drawOval(centerX+radius/2, centerY-radius/2, maxX, maxY); 
       // 4th circle 
       gc.drawOval(centerX-radius/2, centerY + radius/2, maxX, maxY); 
       direction++; 
       direction %= 4; 
       switch(direction){        
       case 0:         
        gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); 
        gc.fillOval(centerX - 2*radius + radius/2, centerY - radius/2, maxX, maxY); 
        break; 
       case 1:         
        gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); 
        gc.fillOval(centerX-radius/2, centerY-radius - radius/2, maxX, maxY); 
        break;        
       case 2:         
        gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); 
        gc.fillOval(centerX+radius/2, centerY-radius/2, maxX, maxY); 
        break;  
       case 3 :          
        gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); 
        gc.fillOval(centerX-radius/2, centerY + radius/2, maxX, maxY); 
        break; 
       } 
       table.setBackgroundImage(image); 
       table.redraw(); 
       table.update();   
       image.dispose(); 
       gc.dispose(); 
      } 
     }); 
    } 
+0

當你說閃爍,這聽起來像動畫直接完成屏幕無緩衝。向我們展示您的動畫代碼。也許drawCircles? – anonymous

+0

@anonymous:updated –

+0

它每次調用drawCircles時創建一個新的線程。這不是很好,但我不認爲這是閃爍的原因。 DrawCircles似乎沒有采用任何緩衝。也許這可能對你有幫助? http://stackoverflow.com/questions/17783525/triple-buffer-heavy-flickering。 – anonymous

回答

1

爲了解決這個問題,我結束了使用雙緩衝,通過在GC繪製的圖像,再後來更新的paintEvent GC。這大大減少了閃爍,即使開啓了抗鋸齒功能。

基本上,創建一個PaintListener ::

final PaintListener paint = new PaintListener() { 

      @Override 
      public void paintControl(PaintEvent e) { 
       int radius = 100; 
       int maxX = radius ; 
       int maxY = radius ;        
       int centerX = e.width/2; 
       int centerY = e.height/2; 
       Image image = new Image(Display.getDefault(),e.width,e.height); 
       GC gc = new GC(image);        
       gc.setAntialias(SWT.ON); 
       gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); 
       //gc.drawLine(0, centerY, shell.getBounds().width, centerY); 
       //gc.drawLine(centerX, 0, centerX, shell.getBounds().height); 
       // 1st circle 
       gc.drawOval(centerX-radius/2, centerY-radius - radius/2, maxX, maxY); 
       // 2nd circle 
       gc.drawOval(centerX - 2*radius + radius/2, centerY - radius/2, maxX, maxY); 
       // 3rd circle 
       gc.drawOval(centerX+radius/2, centerY-radius/2, maxX, maxY); 
       // 4th circle 
       gc.drawOval(centerX-radius/2, centerY + radius/2, maxX, maxY); 
       direction++; 
       direction %= 4; 
       switch(direction){        
       case 0:     
        gc.setAlpha(255); 
        gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); 
        gc.fillOval(centerX - 2*radius + radius/2, centerY - radius/2, maxX, maxY); 
        break; 
       case 1: 
        gc.setAlpha(170); 
        gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); 
        gc.fillOval(centerX-radius/2, centerY-radius - radius/2, maxX, maxY); 
        break;        
       case 2:    
        gc.setAlpha(80); 
        gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); 
        gc.fillOval(centerX+radius/2, centerY-radius/2, maxX, maxY); 
        break;  
       case 3 :    
        gc.setAlpha(20); 
        gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); 
        gc.fillOval(centerX-radius/2, centerY + radius/2, maxX, maxY); 
        break; 
       } 
       e.gc.drawImage(image, 0, 0); 
       image.dispose(); 
       gc.dispose(); 
      } 
     }; 

動畫線程可以寫爲::

showAnimation = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       while(true){ 
        synchronized (this) { 
         try {      
          Thread.sleep(100); 
          Display.getDefault().asyncExec(new Runnable() {        
           @Override 
           public void run() { 
            table.addPaintListener(paint); 
            table.redraw(); 
            table.update(); 
            table.removePaintListener(paint); 
           } 
          }); 

         } 
         catch (InterruptedException e) 
         { 
          // do nothing, because this thread is meant to be interrupted! 
          // and then, break out of the infinite loop 
          break; 
         } 
        }     
       }        
      } 
     }); 

我並移除聽衆,因爲通知是給一些問題(吸引更多的次數超過要求!)。然後,數據庫調用可以在這樣另一個線程進行::

invokeLater = new Thread(new Runnable() { 

      @Override 
      public void run() {   
       //Fetching records from Service 
       try 
       { 
        // database call here 
        if(showAnimation.isAlive()) 
        { 
         showAnimation.interrupt(); 
        } 

       } 
         } 
      }); 

這結束了對我的工作。如果任何人都可以在這個改進,請告訴我:)

+0

謝謝巴茲和匿名:) –