Java中有没有一种方法可以点击JFrame



我试图为一个在浏览器窗口中运行的基于HTML的游戏制作一个覆盖层,并创建了一个不透明的JFrame。我希望在窗口上方覆盖的情况下仍然可以玩游戏。我尝试了一些我找到的解决方案,但这些对我不起作用。

我曾想过在我的JFrame上捕捉点击事件;模拟";点击游戏窗口。但遗憾的是,我不知道这怎么可能。

我当前的代码是使用JNA库来访问窗口的位置和比例(在我的测试代码TaskManager中(。如果可能的话,我可以用另一种纪念物或类似的东西。

到目前为止,这是我的代码:

import com.sun.jna.platform.DesktopWindow;
import com.sun.jna.platform.WindowUtils;
import javax.swing.*;
import java.awt.*;
public class Test {
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("title");
frame.setUndecorated(true);
frame.setBackground(new Color(255, 69, 0, 100));
frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Rectangle rect = null;
while (true) {
for (DesktopWindow desktopWindow : WindowUtils.getAllWindows(true)) {
if (desktopWindow.getTitle().contains("Task-Manager")) {
rect = desktopWindow.getLocAndSize();
frame.setSize(rect.width - 16, rect.height - 8);
frame.setLocation(rect.x + 8, rect.y);
frame.setVisible(true);
Thread.sleep(10);
}
}
}
}
}

JFrame是一个重量级组件。主机操作系统GUI系统中有一个窗口。主机操作系统图形用户界面将鼠标事件指向该窗口。也许对覆盖使用轻量级组件,然后禁用上面的鼠标事件会是一个更好的解决方案。

你捕捉点击事件的想法;模拟它";在你的游戏窗口应该相当容易。如果你的JFrame事件处理代码引用了你的游戏引擎,它可以确定窗口的相对位置,并告诉游戏引擎它应该像收到点击一样工作的对应点。也就是说,只需对正常接收到的点击事件和模拟事件调用游戏引擎的相同方法。

一个丑陋的破解(有明显的闪烁(是隐藏窗口并用Robot类发送点击。。。像这样:


import java.awt.AWTException;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.SwingUtilities;
public class ClickThrough  extends Frame implements MouseListener, MouseMotionListener {
private final Robot robot;
private Color bgColor = new Color(0x80808080, true);
private Point dragPoint;
public ClickThrough() throws AWTException {
setAlwaysOnTop(true);
robot = new Robot();
}
public static void main(String[] args) throws AWTException {
ClickThrough w = new ClickThrough();
w.setUndecorated(true);
w.setSize(200, 100);
w.setOpacity(0.7f);
w.addMouseListener(w);
w.addMouseMotionListener(w);
w.setVisible(true);
}
@Override
public void paint(Graphics g) {
int w = getWidth();
int h = getHeight();
g.setColor(Color.GRAY);
g.fillRect(0, 0, w, 16);
g.setColor(bgColor);
g.fillRect(0, 16, w, h-16);
g.setColor(Color.BLACK);
g.drawString("Go ahead, click on me...", 20, 50);
}
private void makeHole(MouseEvent e) {
// Tried making a shape with a hole where the mouse was clicked,... didn't work (macOS).
//setShape(windowWithHoleShape);
setVisible(false);
}
private void repairHole(MouseEvent e) {
//setShape(windowShape);
setVisible(true);
}
@Override
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
// give it a draggable area at the top
if (p.y < 16) {
dragPoint = p;
return;
}
dragPoint = null;
SwingUtilities.convertPointToScreen(p,this);
makeHole(e);
robot.mouseMove(p.x, p.y);
robot.mousePress(InputEvent.getMaskForButton(e.getButton()));
repairHole(e);
}
@Override public void mouseReleased(MouseEvent e) { }
@Override public void mouseClicked(MouseEvent e) { }
@Override public void mouseEntered(MouseEvent e) { }
@Override public void mouseExited(MouseEvent e) { }
@Override
public void mouseDragged(MouseEvent e) {
if (dragPoint != null) {
Point p = e.getPoint();
SwingUtilities.convertPointToScreen(p, this);
p.translate(-dragPoint.x, -dragPoint.y);
setLocation(p);
}
}
@Override
public void mouseMoved(MouseEvent e) { }
}

我试着通过设置窗口形状来查看是否可以在窗口上切一个洞,但至少在macOS上,这个洞不允许鼠标事件通过。

我还应该指出,如果您将GUI框架切换到JAvaFX,那么您可以选择在JavaFXWebView中运行基于HTML的游戏UI,这样您就可以将游戏和覆盖集成到一个连贯的应用程序中。您可以专门制作您的覆盖";鼠标透明";。国际海事组织认为,这将是一个比鼠标事件更好的方法。

最新更新