I'm writing a program that when it's started one of the anchorpane's is opened at the cursor position. I've made it with a method, which is called in the initialize(), and it's working fine. The problem is that, in the main, when i hide the primaryStage, or close it, and i instantiate an stage again to be shown, it won't get the cursor position anymore, and the UI keeps appearing in the same position as the first time. It's like the Controller keeps running. Somebody knows why does it happens? And how can i solve this? There's a way i can change the position in the controller whenever the anchorPane is started or visible? Or stop that which keeps running? A solution that keeps it open would be better for performance. I'm using Jnativehook to call it, and scenebuilder. Thanks. JDK 21, JAVAFX 21.0.1, JNativeHook 2.2.2.
Main:
package MRE;
import java.io.IOException;
import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.NativeHookException;
import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application implements NativeKeyListener{
private Stage primaryStage;
public static boolean shortcutIsPressed;
public static void main(String[] args) {
Platform.setImplicitExit(false);
nativeKeyListener();
}
@Override
public void start(Stage primaryStage) throws Exception {
}
public void testStage() throws IOException {
primaryStage = new Stage();
Parent root = FXMLLoader.load(getClass().getResource("/MRE/test.fxml"));
Scene scene = new Scene(root);
//SHOW STAGE
primaryStage.setAlwaysOnTop(true);
primaryStage.setScene(scene);
primaryStage.show();
}
//JNATIVEHOOK///////////////////////////////////////////////////////////////////////
public void nativeKeyPressed(NativeKeyEvent e) {
// System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
Platform.runLater( () -> {
if (e.getKeyCode() == NativeKeyEvent.VC_F5) {
shortcutIsPressed = true;
// System.out.println("F5: " + isPressed);
if(shortcutIsPressed = true) {
if(primaryStage == null) {
try {
testStage();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
} );
}
public void nativeKeyReleased(NativeKeyEvent e) {
System.out.println("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
Platform.runLater( () -> {
if (e.getKeyCode() == NativeKeyEvent.VC_F5) {
shortcutIsPressed = false;
if(primaryStage != null) {
primaryStage.hide();
primaryStage = null;
// Platform.exit();
}
}
});
}
public void nativeKeyTyped(NativeKeyEvent e) {
// System.out.println("Key Typed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public static void nativeKeyListener() {
//NATIVEKEYLISTENER
try {
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
GlobalScreen.addNativeKeyListener(new Main());
}
}
Controller:
package MRE;
import java.io.IOException;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
public class Controller {
@FXML
private AnchorPane aPaneInside;
@FXML
private AnchorPane aPaneOutside;
@FXML
private Button btn;
public void initialize() throws IOException {
setUiPosition();
}
public void setUiPosition() {
aPaneInside.setLayoutX(Utils.cursorPoint.getX()-aPaneInside.getPrefWidth()/2);
aPaneInside.setLayoutY(Utils.cursorPoint.getY()-aPaneInside.getPrefHeight()/2);
}
}
Utils:
package MRE;
import java.awt.MouseInfo;
import java.awt.Point;
public class Utils {
public static Point cursorPoint = MouseInfo.getPointerInfo().getLocation();
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="aPaneOutside" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="1080.0" prefWidth="1920.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="MRE.Controller">
<children>
<AnchorPane fx:id="aPaneInside" layoutX="860.0" layoutY="440.0" prefHeight="200.0" prefWidth="200.0" style="-fx-background-color: blue;">
<children>
<Button fx:id="btn" layoutX="74.0" layoutY="88.0" mnemonicParsing="false" text="Button" />
</children>
</AnchorPane>
</children>
</AnchorPane>
module-info:
module MRE {
requires javafx.fxml;
requires javafx.graphics;
requires javafx.controls;
requires java.desktop;
requires com.github.kwhat.jnativehook;
opens MRE to javafx.graphics, javafx.fxml;
}
public static Point cursorPoint =
MouseInfo.getPointerInfo().getLocation();
is a static member -> that will only be set when the Utils
class is first loaded.
Use a static method in Utils
instead:
public static Point getCursorPoint() {
return MouseInfo.getPointerInfo().getLocation();
};
That will get you the current cursor location whenever you call it.