我正在制作JavaFX应用程序而我想要执行以下操作。
我提供了几个按钮,当按下它们时,GUI将最小化并等待来自JNativeHook库的mouseClick。当单击鼠标时,它需要将协调器中继回到javaFx控制器,GUI最大化并表示gui中的数据,并且让我可以使用它来执行其他操作。
我已经将这种行为用于一个按钮,但它并不好。如果我想要更多按钮,我当前的实现将无法工作,如下所示,它需要很多重复的代码,我需要在layoutController中为每个按钮创建一个特定的mouseListener和方法(除了buttonHandlers) 。我显然不想要这个,基本上我正在寻找一个小框架让我的buttonHandle方法中的下一个NativeMouseEvent中继数据在控制器中
这就是我得到的,带按钮的JavaFX layoutController具有以下句柄
@FXML
private void handleGetPos() {
try {
mouseManager.startMousePosChecker(cntrl);
mainGUI.minimizeGUI();
} catch (Exception e) {
e.printStackTrace();
}
}
layoutController将自身作为cntrl
传递给我的mouseManager,管理器只是(un)将nativeHook注册到GlobalScreen
并向其添加一个新的mouseListener并传递layoutController cntrl
。 (如果我想使用另一个layoutControllers,那么将控制器传递给它也是愚蠢的,因为它们的类型不同)
GlobalMouseListener mouseListener = new GlobalMouseListener();
mouseListener.setLayoutController(cntrl);
GlobalScreen.getInstance().addNativeMouseListener(mouseListener);
在mouseListener中发生这种情况:
public void nativeMouseClicked(NativeMouseEvent e) {
Platform.runLater(() -> {
cntrl.setMousePos(ConvTypes.toStr(e.getX()), ConvTypes.toStr(e.getY()), e.getX(), e.getY() );
});
}
这很丑陋,当事件发生时,它将x,y坐标作为字符串传递给我的layoutController中的特定方法:
public void setMousePos(String sX, String sY, int x, int y) {
xPos.setText(sX);
yPos.setText(sY);
mainGUI.maximizeGUI();
mouseManager.stopMousePosChecker();
//other stuff
显然,这种实现不适用于多个按钮。因此,我想用mouseManager构建一个小框架。哪个注册/取消注册nativeHook并只生成一个mouseListener,它将数据返回给mouseManager。然后,此mouseManager会向需要它的任何人提供必要的数据。如果我纠正这听起来像一个自定义事件类? (尝试制作一个,但我不知道如何实现它我的layoutController或如何将它包装在globalMouseEvents周围)
无论如何,我认为它会变成这样的东西,或者是lambda的东西? (注意我实际上不知道):
@FXML
private void handleButton() {
xPos.setText(mouseManager<MouseEvent>() {
@Override
public void handle(MouseEvent e) {
//necessery stuff goes here
所以是的,我不知道如何开始如何在任何buttonHandle()方法或实际的任何方法中返回数据。我知道我当前的代码很糟糕,我想让它变得更好并重用代码而不是重复的代码,但这个问题目前让我头疼...
这是一篇很长的帖子,感谢阅读和帮助!
答案 0 :(得分:1)
不确定我是否完全理解,但你可以这样做:
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseListener;
import org.jnativehook.GlobalScreen;
import javafx.scene.input.MouseEvent ;
import javafx.application.Platform ;
import javafx.event.EventType ;
import javafx.geometry.Point2D ;
import javafx.beans.property.ReadOnlyObjectWrapper ;
import javafx.beans.property.ReadOnlyObjectProperty ;
public class GlobalMouseListener implements NativeMouseListener {
private final EventType<MouseEvent> eventType ;
private final ReadOnlyObjectWrapper<Point2D> mouseLocation = new ReadOnlyObjectWrapper<>();
/**
* @param eventType The type of event to listen for. Should be one of
* MouseEvent.MOUSE_CLICKED, MouseEvent.MOUSE_PRESSED, or MouseEvent.MOUSE_RELEASED.
* The mouseLocationProperty() will be updated if a global mouse event
* matching the semantic type of the provided eventType occurs.
*/
public GlobalMouseListener(EventType<MouseEvent> eventType) {
this.eventType = eventType ;
GlobalScreen.addNativeMouseListener(this);
}
public ReadOnlyObjectProperty<Point2D> mouseLocationProperty() {
return mouseLocation.getReadOnlyProperty() ;
}
public final Point2D getMouseLocation() {
return mouseLocationProperty().get();
}
@Override
public void nativeMouseClicked(NativeMouseEvent e) {
if (eventType == MouseEvent.MOUSE_CLICKED) {
Platform.runLater(() -> mouseLocation.set(new Point2D(e.getX(), e.getY())));
}
}
@Override
public void nativeMousePressed(NativeMouseEvent e) {
if (eventType == MouseEvent.MOUSE_PRESSED) {
Platform.runLater(() -> mouseLocation.set(new Point2D(e.getX(), e.getY())));
}
}
@Override
public void nativeMouseReleased(NativeMouseEvent e) {
if (eventType == MouseEvent.MOUSE_RELEASED) {
Platform.runLater(() -> mouseLocation.set(new Point2D(e.getX(), e.getY())));
}
}
public void cleanup() {
GlobalScreen.removeNativeMouseListener(this);
}
}
然后你的按钮处理程序只需要
@FXML
public void handleGetPos() {
GlobalMouseListener gml = new GlobalMouseListener(MouseEvent.MOUSE_CLICKED);
gml.mouseLocationProperty().addListener((obs, oldLocation, newLocation) -> {
double x = newLocation.getX();
double y = newLocation.getY();
gml.cleanup();
// restore window and process x, y...
});
mainGUI.minimizeGUI();
}
如果您真的想最小化样板代码,可以定义
private void processMouseLocation(BiConsumer<Double, Double> pointProcessor) {
GlobalMouseListener gml = new GlobalMouseListener(MouseEvent.MOUSE_CLICKED);
gml.mouseLocationProperty().addListener((obs, oldLocation, newLocation) -> {
double x = newLocation.getX();
double y = newLocation.getY();
gml.cleanup();
// restore window...
pointProcessor.accept(x, y);
});
mainGUI.minimizeGUI();
}
然后每个按钮处理程序都缩减为
@FXML
public void handleGetPos() {
processMouseLocation((x, y) -> {
// code to handle mouse press at x,y...
});
}
这都是未经测试的(编译和运行,我只是在这里输入),但我认为它应该足以让你开始。关键是你只是为鼠标位置公开一个属性,并从每个按钮处理程序中监听它,在它发生变化时执行特定于按钮的代码。您的本机鼠标侦听器只需在相关事件发生时更新属性;它不需要对控制器等的引用。