2011-08-09 21 views
7

मैं SWT के लिए एक गैंट घटक लागू कर रहा हूं और इसे चित्रित करने के लिए थोड़ा सा लगता है (जैसे, आरेख के पूरे दृश्य भाग के लिए 200 एमएस)।सामग्री को धीमा करने के लिए धीमी गति से मिश्रित मिश्रित दिखता है बदसूरत

अब, जब मैं स्क्रॉल करता हूं, तो मैं केवल क्लिपिंग आयत के संबंध में आवश्यक चीज़ों को दोहराता हूं। यह तेजी से स्क्रॉल करते समय एप्लिकेशन को बहुत खराब लग रहा है, क्योंकि तब स्क्रॉलिंग के बाद भी दिखाई देने वाला हिस्सा ओएस द्वारा पहले स्थानांतरित किया जाता है, और जब मैंने शेष भाग (भाग जो स्क्रॉलिंग के दौरान दिखाई देता है) चित्रित करना समाप्त किया, तुरंत नया स्क्रॉलिंग चरण शुरू होता है, मेरे आरेख का आधा दाहिना ओर ले जाता है और मुझे दूसरे आधे हिस्से को दोबारा पेश करने देता है। स्क्रॉलिंग के दौरान यह मध्य में मेरे आरेख झिलमिलाहट की तरह दिखता है।

यह वास्तव में अच्छा नहीं लग रहा है। क्या इस से निकाल पाने के लिए कोई तरीका है? क्या यह सवाल समझ में आता है?

संपादित करें: यहां एक "छोटा" परीक्षण कार्यक्रम है जो वास्तव में वर्णित व्यवहार दिखाता है। इसे चलाने के लिए आपको क्लासपाथ में केवल SWT की आवश्यकता है।

package de.ikoffice.gui; 

import org.eclipse.swt.SWT; 
import org.eclipse.swt.custom.ScrolledComposite; 
import org.eclipse.swt.events.PaintEvent; 
import org.eclipse.swt.events.PaintListener; 
import org.eclipse.swt.graphics.Color; 
import org.eclipse.swt.graphics.GC; 
import org.eclipse.swt.graphics.Rectangle; 
import org.eclipse.swt.layout.GridData; 
import org.eclipse.swt.layout.GridLayout; 
import org.eclipse.swt.widgets.Canvas; 
import org.eclipse.swt.widgets.Composite; 
import org.eclipse.swt.widgets.Display; 
import org.eclipse.swt.widgets.Shell; 

public class SlowRepaintProblem { 

    public Color[] colors = new Color[501]; 

    public SlowRepaintProblem() { 
     Display display = Display.getDefault(); 
     for(int i=0; i<=500; i++) { 
      int r = (i * 10) % 256; 
      int g = (i * 20) % 256; 
      int b = (i * 30) % 256; 
      colors[i] = new Color(display,r,g,b); 
     } 

     Shell shell = new Shell(display); 
     shell.setText("SlowRepaintTest"); 
     ScrolledComposite comp = new ScrolledComposite(shell, 
       SWT.H_SCROLL | SWT.V_SCROLL | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND); 
     SlowRepaintingCanvas canvas = new SlowRepaintingCanvas(comp,SWT.NONE| SWT.NO_BACKGROUND); 
     comp.setContent(canvas); 
     canvas.setSize(5000,5000); 

     // Layouting 
     shell.setLayout(new GridLayout());   
     comp.setLayoutData(new GridData(GridData.FILL_BOTH)); 
     shell.setBounds(50, 50, 800, 600); 

     // Showing the control 
     shell.open(); 
     while (!shell.isDisposed()) { 
      try { 
       if (!shell.getDisplay().readAndDispatch()) { 
        shell.getDisplay().sleep(); 
       } 
      } catch (Throwable e) { 
       String message = e.getMessage(); 
       if(message == null || !e.getMessage().equals("Widget is diposed")) { 
        e.printStackTrace(); 
       } 
       break; 
      } 
     } 
    } 

    public static void main(String[] args) { 
     new SlowRepaintProblem(); // Evil constructor call to start main program flow. 
    } 

    class SlowRepaintingCanvas extends Canvas { 

     public SlowRepaintingCanvas(Composite parent, int style) { 
      super(parent, style); 

      addPaintListener(new PaintListener() { 
       @Override 
       public void paintControl(PaintEvent e) { 
        GC gc = e.gc; 
        Rectangle r = gc.getClipping(); 
        gc.setAlpha(255); 
//     gc.setBackground(ColorUtils.WHITE); 
//     gc.fillRectangle(r); 

        int x = r.x - (r.x % 10); 
        int width = (r.width + r.x - x) - (r.width + r.x - x) % 10 + 10; 
        int y = r.y - (r.y % 10); 
        int height = (r.height + r.y - y) - (r.height + r.y - y) % 10 + 10; 

        gc.setAlpha(128); 
        for(int i = x; i < x+width; i+= 10) { 
         gc.setBackground(colors[i/10]); 
         gc.fillRectangle(i, r.y, 10, r.height); 
        } 
        for(int j = y; j < y+height; j+= 10) { 
         gc.setBackground(colors[j/10]); 
         gc.fillRectangle(r.x, j, r.width, 10); 
        } 
       } 
      }); 
     } 

    } 

} 
+0

पहले उत्तर में प्रश्न और टिप्पणियां पढ़ने के बाद, वास्तव में कोई भी तरीका नहीं है [एसएससीसीई] (http://sscce.org/) के बिना आपकी मदद कैसे करें। आपको अपने गैंट आरेख कोड का पर्दाफाश करने की ज़रूरत नहीं है, बस किसी भी डमी सीजी के साथ एसएससीसीई बनाएं और हमें समस्या को ठीक दिखाने के लिए उसी स्क्रॉलिंग तकनीक का उपयोग करें .. – Sorceror

+0

ठीक है, मैं समस्या दिखाने वाला एक न्यूनतम काम करने वाला उदाहरण बनाने की कोशिश करूंगा। – Daniel

+0

क्या आपने [डबल-बफरिंग और पेज-फ़्लिपिंग] (http://download.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html) तकनीकों का प्रयास किया है, और क्या आप कह रहे हैं कि वे आपके लिए काम नहीं कर रहे हैं? –

उत्तर

7

एसडब्ल्यूटी पेंटिंग बहुत तेज़ है और यूआई की कमी आमतौर पर पेंट विधियों को धीमा करने के लिए ट्रैक की जा सकती है। इसलिए, अपने आरेख को खींचने वाले एल्गोरिदम को अनुकूलित करने का प्रयास करें! एक दृष्टिकोण कैशिंग हो सकता है - एक छवि में चित्र सामग्री आकर्षित:

Image cache = new Image(Display.getCurrent(), width, height); 
GC gc = new GC(cache); 

और केवल आवश्यक छवि भागों फिर से रंगना जब स्क्रॉल:

gc.drawImage(cache, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight); 

एक बार आरेख परिवर्तन - और उसके बाद ही - कैश फिर से रंगना अपनी जटिल पेंट विधि का उपयोग कर छवि।

HTH

+0

ठीक है, मैं इसे आज़मा दूंगा। – Daniel

+0

भी काम नहीं करता है। अभी भी पहले के रूप में बदसूरत लग रहा है, क्योंकि छवि से प्रतिलिपि करना मैन्युअल रूप से इसे प्रस्तुत करने के रूप में धीमा लगता है। – Daniel

+0

क्या आपने क्लिपिंग क्षेत्र को drawImage() में विशेषताओं के साथ सिंक किया था, यानी क्या आपने पूरे चित्र को चित्रित करने के बजाय केवल कैश की गई छवि के आवश्यक सबग्रायन की प्रतिलिपि बनाई थी? – Henrik

0

मैं पेंटिंग बफ़र होना एक Image उपयोग करने के लिए हेनरिक के सुझाव ले लिया और अपने SSCCE में इसे लागू किया। मैं अब अपने सिस्टम पर बहुत कम झिलमिलाहट देखता हूं।

 addPaintListener(new PaintListener() { 
      @Override 
      public void paintControl(PaintEvent e) { 
       GC gc = e.gc; 
       Rectangle r = gc.getClipping(); 

       int x = r.x - (r.x % 10); 
       int width = (r.width + r.x - x) - (r.width + r.x - x) % 10 + 10; 
       int y = r.y - (r.y % 10); 
       int height = (r.height + r.y - y) - (r.height + r.y - y) % 10 + 10; 

       Image image = new Image(gc.getDevice(),width,height); 
       GC igc = new GC(image); 

       // Without buffering, this code was necessary to prevent "ghost" 
       // scrollbars on window resize, but with buffering it is no longer 
       // required...it does affect the visual results however. 
       //igc.setAlpha(255); 
       //igc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_BLACK)); 
       //igc.fillRectangle(image.getBounds()); 

       igc.setAlpha(128); 
       for(int i = x; i < x+width; i+= 10) { 
        igc.setBackground(colors[i/10]); 
        igc.fillRectangle(i-x, 0, 10, height); 
       } 
       for(int j = y; j < y+height; j+= 10) { 
        igc.setBackground(colors[j/10]); 
        igc.fillRectangle(0, j-y, width, 10); 
       } 

       gc.drawImage(image, x, y); 
       igc.dispose(); 
       image.dispose(); 
      } 
     }); 
+0

ओह, हेनरिक के उत्तर के नीचे टिप्पणी इतिहास को और अधिक बारीकी से पढ़ें, ऐसा लगता है कि आपने पहले से ही एक छवि बफर की कोशिश की है और इससे पर्याप्त मदद नहीं मिली है? अगर कोई और इसे उपयोगी पाता है तो मैं अपना जवाब यहां छोड़ दूंगा ... –

+0

लेकिन आप सही हैं। यहाँ बहुत कम झिलमिलाहट। आश्चर्य की बात है, अगर मैं अपने गैंट में एक ही तकनीक लागू करता हूं, तो यह 3 गुना धीमा हो जाता है। मुझे देखना होगा कि इसमें मुझे एक और त्रुटि है या नहीं। – Daniel

संबंधित मुद्दे