我根据答案使用透明点击覆盖(使用jna启用点击)
https://stackoverflow.com/a/28772306/1093872。
然而,实际的可见叠加总是落后一步,即。当在组件上调用repaint()
时,将显示应在先前更新中显示的更新。
起初,由于线程不同,我怀疑内存不一致问题。但我也使用SwingWorker
尝试sure-to-be-correct方法,但仍面临同样的问题。
AWTUtilities.setWindowOpaque(w, false);
似乎以某种方式导致了问题,因为在我将其注释掉或将其设置为true后,问题就会消失,但不幸的是窗口也不透明(显然)。
我怀疑这个问题可能与双缓冲有关(缓冲区在下一次绘制之后只绘制后没有交换),但我真的不知道。我还尝试在组件上调用setDoubleBuffered(false)
和setDoubleBuffered(true)
,但这不会改变任何内容。
此外,我意识到问题与jna部分无关,因为在删除之后,问题仍然完全相同。
请注意,索引打印与绘图同时发生,因此我知道paintComponent
会及时调用,但可见更新仅在下次调用时发生。
关于可能是什么原因以及如何解决这个问题的任何想法?
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 :(得分:0)
经过多次反复试验,我找到了一个有效的解决方案......
将Window w = new Window(null);
更改为Window w = new JWindow();
解决了这个问题。我不知道为什么,但我很高兴。