我是java(fx)的初学者。
如何在JavaFX中获得x和y中的鼠标位置?我尝试使用AWT的MouseInfo
(也导入了它),但它不起作用。我也在Ensembles中看到了它的代码(在“高级阶段”拖动球窗,这就是我需要做的,拖动我未修饰的JavaFX阶段),但它也不起作用。我正在使用带控制器的FXML,我猜这是主要问题。我应该切换回单文件简单的JavaFX吗?我知道FXML更适合布局用户界面,但我不能让很多这样的代码工作。或者我的控制器是否需要其他类型的代码?请尽可能提供适当的代码和评论
如果您需要我的一些代码进行检查,请随时询问。
答案 0 :(得分:23)
你的问题中有几个项目 - 我会一次解决一个问题。
如何在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更适合布局用户界面,但我不能让很多这样的代码工作。
缺乏对底层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的所有内容。
请不要对此答案发表后续评论(因为这个答案足够长)。如果您有新问题,请创建一个新问题(每个问题一个问题)。
答案 1 :(得分:3)
为此目的使用机器人怎么样?
http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Robot.html
使用机器人,与将事件发布到AWT事件队列不同。事件在本机事件队列中生成。实际上,使用Robot.mouseMove
,您不仅可以设置鼠标位置,还可以获得位置。
要获得鼠标位置,您可以坚持使用MouseInfo
import java.awt.MouseInfo;
// get the mouse's position
Point p = MouseInfo.getPointerInfo().getLocation();
这不起作用:你和Mac在一起吗?您的JavaFX版本是哪个?似乎是FX8纠正的问题。仅限mac,您可以使用
com.sun.glass.ui.Robot robot =
com.sun.glass.ui.Application.GetApplication().createRobot();
// getPosition of the mouse in Mac
int x = robot.getMouseX();
int y = robot.getMouseY();
答案 2 :(得分:2)
遗憾的是,JavaFx 8 WindowEvent不提供鼠标的(x,y)位置。我通过使用像这样的AWT MouseInfo解决了这个问题(并且工作正常):
Tooltip t = new Tooltip();
Tooltip.install(yournode, t);
t.setOnShowing(ev -> {// called just prior to being shown
Point mouse = java.awt.MouseInfo.getPointerInfo().getLocation();
Point2D local = yournode.screenToLocal(mouse.x, mouse.y);
// my app-specific code to get the chart's yaxis value
// then set the text as I want
double pitch = yaxis.getValueForDisplay(local.getY()).doubleValue();
double freq = AudioUtil.pitch2frequency(pitch);
t.setText(String.format("Pitch %.1f: %.1f Hz %.1f samples", pitch, freq, audio.rate / freq));
});