22 Temmuz 2020 Çarşamba

Thread İçinde Swing Bileşenine Çizim

Giriş
Bir seferinde bir ekran bileşenini periyodik bir şekilde çizmek gerekti. Periyodik olması için yeni bir thread başlatıldı. Swing sınıfının Timer metodu kullanılmadı çünkü flicker (titreme) yaratacağı düşünüldü. Ben bu çözümün en doğru çözüm olduğundan emin değilim ancak yine de not almak istedik. Bu yönteme Double Buffering artı Offscreen Drawing deniliyor.

Swing aslınd kendisi de Double Buffering yöntemini kullanıyor. Açıklaması şöyle
Double buffering means that instead of drawing directly on the screen, Swing first performs drawing operations in an offscreen buffer and then copies the completed work to the display in a single painting operation, as shown in Figure 20-5. It takes the same amount of time to do the drawing work, but once it’s done, double buffering instantaneously updates our display so that the user does not perceive any flickering or progressively rendered output.

You’ll see how to implement this technique yourself when we use an offscreen buffer later in this chapter. However, Swing does this kind of double buffering for you whenever you use a Swing component in a Swing container. AWT components do not have automatic double buffering capability.

It is interesting to take our example and turn off double buffering to see the effect. Each Swing JComponent has a method called setDoubleBuffered() that can be set to false in order to disable the technique. Or you can disable it for all components using a call to the Swing RepaintManager, as we’ve indicated in comments in the example. Try uncommenting that line of DragImage and observe the difference in appearance.
Aslında Swing otomatik olarak double buffer kullansa bile biz çizme işlemini bir başka thread içinde yaptığımız için, yine kendi elimizde bir Graphics2D nesnesi yaratmak gerekti.

Thread
Thread şu işleri yapıyordu

1. renderBuffer() metodu
Bu metod double buffering şeklinde çalışıyordu. İki tane Graphics2D nesneni dönüşümlü olarak kullanıyordu. Sırası gelen Graphics2D nesnesine çizim yapıldı. Örneğin indeks 0 ise birinci buffer'a çizim yapıldı. 1 ise ikinci buffer'a çizim yapıldı Metod şöylee
public void renderBuffer(){

  Graphics2D bufferedImageGraphics = (index == 0) : imageGraphics1 : imageGraphis2;
  ...
}
swapBuffer metodu
İndeks 0 ise 1, 1 ise 0 yapıldı

3 repaint metodu
Bu metod aslında paint() metodunu tetikliyor. Bu çağrı paint metodunu da asenkron olarak tetikliyor. Açıklaması şöyle
methods like repaint(), revalidate() are safe to use within any thread. Those methods actually queue requests to EDT(Event Dispatch Thread) to call paint() and validate(). So if you call repaint() many times using different threads, it will queue the request to call paint() method..
paint() metodu içinde yeni buffer çiziliyor. İndeks 0 ise ikinci buffer çiziliyor, 1 ise birinci buffer çiziliyor. Metod şöyle
public void paint(Graphics g) {

  if (firstTime){
    Dimension size = getSize();
    g.fillRect(0,0,size.width,size.height);

    BufferedImage image1 = (BufferedImage)createImage(size.width,size.height);
    Graphics2D imageGraphics1 = image1.createGraphics();

    BufferedImage image2 = (BufferedImage)createImage(size.width,size.height);
    Graphics2D imageGraphics2 = image2.createGraphics();

    firstTime = false;
  }

  BufferedImage bufferedImage = (index == 0) imageGraphics2 : imageGraphics1;

  Graphics2D g2 = (Graphics2D)g;
  g2.drawImage(bufferedImage,0,0,this);
}



Hiç yorum yok:

Yorum Gönder