您的问题中有几项 - 我将一次解决一项。
如何在 JavaFX 中获取鼠标在 x 和 y 中的位置?
将鼠标事件处理程序添加到要在其中跟踪鼠标位置的适当 JavaFX 组件。JavaFX 鼠标事件将报告多种不同类型的坐标。 x 和 y 坐标相对于被监控位置的节点的左上角。 sceneX 和 sceneY 坐标相对于场景左上角的 0,0 坐标。 screenX 和 screenY 坐标相对于当前屏幕的左上角 0,0 坐标。
这些坐标记录在MouseEvent 文档中。 Node 和 Scene 文档中提供了有关理解坐标系的额外信息。
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.*;
public class MouseLocationReporter extends Application {
private static final String OUTSIDE_TEXT = "Outside Label";
public static void main(String[] args) { launch(args); }
@Override public void start(final Stage stage) {
final Label reporter = new Label(OUTSIDE_TEXT);
Label monitored = createMonitoredLabel(reporter);
VBox layout = new VBox(10);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10px;");
layout.getChildren().setAll(
monitored,
reporter
);
layout.setPrefWidth(500);
stage.setScene(
new Scene(layout)
);
stage.show();
}
private Label createMonitoredLabel(final Label reporter) {
final Label monitored = new Label("Mouse Location Monitor");
monitored.setStyle("-fx-background-color: forestgreen; -fx-text-fill: white; -fx-font-size: 20px;");
monitored.setOnMouseMoved(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent event) {
String msg =
"(x: " + event.getX() + ", y: " + event.getY() + ") -- " +
"(sceneX: " + event.getSceneX() + ", sceneY: " + event.getSceneY() + ") -- " +
"(screenX: " + event.getScreenX()+ ", screenY: " + event.getScreenY() + ")";
reporter.setText(msg);
}
});
monitored.setOnMouseExited(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent event) {
reporter.setText(OUTSIDE_TEXT);
}
});
return monitored;
}
}
我尝试使用 AWT 的 MouseInfo(也导入了它),但它不起作用。
不要这样做。混合不同的图形工具包(例如 Swing/AWT 和 JavaFX)是一个高级主题。通常,如果您正在编写 JavaFX 应用程序,请避免从 java.awt 命名空间和 javax.swing 命名空间导入任何内容。如果您有一个大型的、现有的基于 Swing 的应用程序或框架,您需要与您的 JavaFX 应用程序进行互操作,那么您才真正需要使用它们。在这种情况下,您就没有这种情况。
我还在 Ensembles 中看到了它的代码(在“高级阶段”中拖动球窗,这就是我需要做的,拖动我未装饰的 JavaFX 阶段),但它也不起作用。
我尝试了 Ensemble Advanced Stage 样本并拖动该阶段对我有用。
另一个用于在 JavaFX 中拖动未装饰舞台的示例是对 How to draw a clock with JavaFX 2? 的回答,其中包含 associated sample code。使时钟样本的未装饰舞台可拖动的方法是:
/** makes a stage draggable using a given node */
public static void makeDraggable(final Stage stage, final Node byNode) {
final Delta dragDelta = new Delta();
byNode.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
// record a delta distance for the drag and drop operation.
dragDelta.x = stage.getX() - mouseEvent.getScreenX();
dragDelta.y = stage.getY() - mouseEvent.getScreenY();
byNode.setCursor(Cursor.MOVE);
}
});
byNode.setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
byNode.setCursor(Cursor.HAND);
}
});
byNode.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
stage.setX(mouseEvent.getScreenX() + dragDelta.x);
stage.setY(mouseEvent.getScreenY() + dragDelta.y);
}
});
byNode.setOnMouseEntered(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.isPrimaryButtonDown()) {
byNode.setCursor(Cursor.HAND);
}
}
});
byNode.setOnMouseExited(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.isPrimaryButtonDown()) {
byNode.setCursor(Cursor.DEFAULT);
}
}
});
}
我将 FXML 与控制器一起使用,我想这是主要问题。我应该切换回单文件的简单 JavaFX 吗?我知道 FXML 更适合布局 UI,但我无法让很多这样的代码工作。
对底层 JavaFX API 缺乏理解和熟悉可能是您的主要问题,而不是使用 FXML。但是,fxml 所暗示的额外复杂性以及网络上较轻的文档和示例可能会导致您的困难。如果使用 FXML 让您难以理解如何让一些 JavaFX 函数工作,我建议现在停止使用 FXML。使用 Java API 手动编写逻辑代码,遇到困难时参考Oracle JavaFX tutorials 和Ensemble sample code。
一旦您习惯了直接使用 JavaFX API 进行编码,就可以切换回使用 FXML 来处理包含许多 GUI 元素的大型项目。 FXML 元素和属性本身几乎完全基于标准 JavaFX API 的反映而构建。因此,如果您了解核心 JavaFX API,那么您也几乎了解 FXML 的所有内容。
请不要对这个答案发布后续 cmets(因为这个答案已经足够长了)。如果您有新问题,请创建一个新问题(每个问题一个问题)。