2017-02-24 5 views
0

답변을 기반으로 투명 클릭 스 오버레이를 사용했습니다 (클릭 연결을 사용하려면 jna를 사용함) https://stackoverflow.com/a/28772306/1093872. 그러나 실제 보이는 오버레이는 항상 한 걸음 뒤에 있습니다. 구성 요소에서 repaint()이 호출되면 이전 업데이트에 표시된 업데이트가 표시됩니다.투명 스윙 오버레이를 올바르게 업데이트하는 방법은 무엇입니까?

처음에는 다른 스레드 때문에 메모리 불일치 문제가 의심됩니다. 그러나 SwingWorker을 사용하여 sure-to-be-correct 접근 방식을 시도했지만 여전히 동일한 문제에 직면했습니다.

The overlay only updated after the next call to repaint, although I used a generous 2000ms delay

AWTUtilities.setWindowOpaque(w, false);

내가 그 주석 또는 true로 설정 한 후하기 때문에, 어떤 방법으로 문제를 일으키는 것 같다, 문제는 사라지지만 불행하게도 창문도없는 투명 (분명히)입니다.

The update is correct after disabling the transparency

나는 문제가 (버퍼는 다음 페인트 전에 만 그림 후 교환되지 않음) 이중 버퍼링에 뭔가 관련이있을 수도 의심하지만 난 정말 모르겠어요. 또한 구성 요소에서 setDoubleBuffered(false)setDoubleBuffered(true)을 호출했지만 아무 것도 변경하지 않았습니다.

또한 문제는 jna 파트와 관련이 없다는 것을 깨달았습니다. 제거한 후에는 문제가 완전히 동일하기 때문입니다.

인덱스 인쇄는 도면과 동시에 발생하므로 paintComponent은 시간에 따라 호출되지만 그 다음 호출시에만 표시되는 것으로 나타납니다.

어떤 원인 일 수 있으며 해결 방법은 무엇입니까? Window w = new JWindow();-Window w = new Window(null); 변경 많은 시행 착오 내가 일하는 해결책을 발견 한 후

import com.sun.awt.AWTUtilities; 
import com.sun.jna.Native; 
import com.sun.jna.platform.win32.User32; 
import com.sun.jna.platform.win32.WinDef; 
import com.sun.jna.platform.win32.WinUser; 

import javax.swing.*; 
import java.awt.*; 

public class OverlayUpdateTest { 

    private static MyJComponent myJComponent; 

    public static void main(String[] args) { 
     setupOverlayWindow(); 

     new Thread(() -> { 
      for (int i = 0; i < 100; i++) { 
       myJComponent.increaseIndex(); 
       myJComponent.repaint(); 

       try { 
        Thread.sleep(2000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     }).start(); 
    } 

    private static void setupOverlayWindow() { 
     Window w = new Window(null); 

     myJComponent = new MyJComponent(); 
     w.add(myJComponent); 
     w.pack(); 
     w.setLocationRelativeTo(null); 
     w.setVisible(true); 
     w.setAlwaysOnTop(true); 
     /** 
     * This sets the background of the window to be transparent. 
     */ 
     AWTUtilities.setWindowOpaque(w, false); 
     setTransparent(w); 
    } 

    private static void setTransparent(Component w) { 
     WinDef.HWND hwnd = getHWnd(w); 
     int wl = User32.INSTANCE.GetWindowLong(hwnd, WinUser.GWL_EXSTYLE); 
     wl = wl | WinUser.WS_EX_LAYERED | WinUser.WS_EX_TRANSPARENT; 
     User32.INSTANCE.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, wl); 
    } 

    /** 
    * Get the window handle from the OS 
    */ 
    private static WinDef.HWND getHWnd(Component w) { 
     WinDef.HWND hwnd = new WinDef.HWND(); 
     hwnd.setPointer(Native.getComponentPointer(w)); 
     return hwnd; 
    } 

    private static class MyJComponent extends JComponent { 
     private int index = 0; 

     /** 
     * This will draw a black cross on screen. 
     */ 
     protected void paintComponent(Graphics g) { 
      g.setColor(Color.BLACK); 
      g.fillRect(0, getHeight()/2 - 10, getWidth(), 20); 
      g.fillRect(getWidth()/2 - 10, 0, 20, getHeight()); 
      g.setColor(Color.RED); 
      g.drawString("i: " + index, 10, getFont().getSize() + 10); 
      System.out.println("i: " + index); 
     } 

     public Dimension getPreferredSize() { 
      return new Dimension(100, 100); 
     } 

     void increaseIndex() { 
      index++; 
     } 
    } 
} 

답변

0

...


문제를 해결했다. 나는 이유를 모른다. 그러나 나는 그것에 만족한다.

관련 문제