2013-05-19 87 views
2

我是java(fx)的初學者。
如何獲得JavaFX中x和y的鼠標位置?我嘗試使用AWT的MouseInfo(也導入它),但它不起作用。我還在Ensembles中看到了它的代碼(在「高級階段」拖動球窗,這就是我需要做的,拖動我的未修改的JavaFX階段),但它也不起作用。我使用FXML和控制器,我猜這是主要問題。我應該切換回單文件簡單的JavaFX嗎?我知道FXML更適合佈置用戶界面,但我無法獲得許多此類代碼的工作。或者我需要一些其他類型的代碼用於我的控制器?請儘可能給出正確的代碼和評論。
如果您需要一點我的代碼來檢查,請隨時詢問。如何在JavaFX中獲取鼠標的位置?

回答

2

如何使用機器人來達到這個目的?

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(); 
+0

我在Windows 8 x64,JavaFX 2(jdk v7u21)。我昨天正在下載jdk 8,但當時我的愚蠢網絡已經死亡。 –

+0

我可以在Windows上使用該機器人(僅用於測試自動化還是可以在現實世界中使用它?)?儘管MouseInfo和point都起作用,但它將x和y都放在一起。(java.awt.Point [x = 449,y = 323])我需要將它們分開。怎麼做? –

+0

是的。 awt.point:你有兩個字段x和y – octoback

19

有你的問題的幾個項目 - 我將解決他們一次一個。

如何獲得JavaFX中x和y的鼠標位置?

將鼠標事件處理程序添加到要跟蹤鼠標位置的相應JavaFX組件中。JavaFX鼠標事件將報告多種不同類型的座標。 x和y座標相對於正在監視位置的節點的左上角。場景X和場景Y座標相對於場景的左上角0,0座標。 screenX和screenY座標相對於當前屏幕的左上角0,0座標。

這些座標記錄在MouseEvent文檔中。在瞭解NodeScene文檔中的座標系統時有額外的信息。

mouselocationmonitor

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應用程序互操作,那麼您只需要使用這些應用程序或框架。在這種情況下,你沒有這種情況。

我也看到了在合奏它的代碼(即拖在「高級階段」球窗口,這就是我需要做的,拖我未修飾的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 tutorialsEnsemble sample code

一旦您可以直接編寫JavaFX API,切換回使用FXML來處理包含許多GUI元素的較大項目。 FXML元素和屬性本身幾乎完全是基於標準JavaFX API的反映而構建的。因此,如果您瞭解核心JavaFX API,那麼您也可以理解FXML的幾乎所有內容。

請不要發佈後續評論到這個答案(因爲這個答案是足夠長的,因爲它是)。如果您有新問題,請創建一個新問題(每個問題一個問題)。

+1

你真棒爵士Jewelsea(:總是會加倍努力,謝謝 – Elltz

+0

@jewelsea我可以用這個技巧來顯示Windows 8的菜單嗎?(當鼠標移動到角落時顯示菜單) – UnKnown

+1

@UnKnown不,你不能就我所知,鼠標事件只能傳遞給一個場景,如果你有一個全屏應用程序,那麼你可以做到這一點,但如果你的應用程序被窗口化或最小化,並且你想顯示一個基於鼠標的菜單移動到屏幕的角落你不能這樣做,我不確定你會怎麼做,你可能希望爲此創建一個新的問題。 – jewelsea

1

不幸的是,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)); 
     });