web-dev-qa-db-ja.com

JavaFXでマウスの位置を取得する方法は?

私はJava(fx)の初心者です。
JavaFXのxとyでマウスの位置を取得するにはどうすればよいですか? AWTのMouseInfo(これもインポート)を使用してみましたが、機能しません。 Ensemblesでもそのコードを見ました(「高度なステージ」でボールウィンドウをドラッグします。これを行う必要があります。装飾されていないJavaFXステージをドラッグします)が、機能しません。私はコントローラーでFXMLを使用していますが、それが主な問題だと思います。単一ファイルの単純なJavaFXに戻す必要がありますか? UIのレイアウトにはFXMLの方が優れていることは知っていますが、そのようなコードの多くを機能させることはできません。または、コントローラーに他の種類のコードが必要ですか?可能な限り、コメント付きの適切なコードを提供してください。
検査するために私のコードが少し必要な場合は、遠慮なく質問してください。

8
Pratik Anand

あなたの質問にはいくつかの項目があります-私はそれらに一度に1つずつ取り組みます。

JavaFXのxとyでマウスの位置を取得するにはどうすればよいですか?

マウスの位置を追跡する適切なJavaFXコンポーネントにマウスイベントハンドラーを追加します。JavaFXマウスイベントは、複数の異なる種類の座標を報告します。 x座標とy座標は、位置が監視されているノードの左上隅を基準にしています。 sceneX座標とsceneY座標は、シーンの左上の0,0座標を基準にしています。 screenXおよびscreenY座標は、現在の画面の左上の0,0座標を基準にしています。

これらの座標は MouseEvent ドキュメントに記載されています。 Node および Scene のドキュメントには、座標系の理解に関する追加情報があります。

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名前空間から何かをインポートすることは避けてください。 JavaFXアプリケーションと相互運用する必要がある、大規模な既存のSwingベースのアプリケーションまたはフレームワークがある場合にのみ、これらを実際に使用する必要があります。この場合、そのような状況はありません。

Ensemblesでもそのコードを見ました(「高度なステージ」でボールウィンドウをドラッグします。これを行う必要があります。装飾されていないJavaFXステージをドラッグします)が、機能しません。

Ensemble Advanced Stageサンプルを試してみましたが、そのステージをドラッグするとうまくいきました。

JavaFXで装飾されていないステージをドラッグするための別のサンプルは、 JavaFX 2で時計を描画する方法は? への回答にあります 関連するサンプルコード 。装飾されていないステージをクロックサンプル用にドラッグ可能にするために使用される方法は次のとおりです。

/** 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に戻す必要がありますか? UIのレイアウトにはFXMLの方が優れていることは知っていますが、そのようなコードの多くを機能させることはできません。

基盤となるJavaFXAPIの理解と知識の欠如が、FXMLの使用ではなく、おそらく主な問題です。ただし、fxmlがさらに複雑になるということは、Web上のドキュメントやサンプルが軽いことを意味するため、困難につながる可能性があります。 FXMLを使用しているために、一部のJavaFX関数を機能させる方法を理解するのが難しい場合は、今のところFXMLの使用を停止することをお勧めします。 Java APIを使用して手動でロジックをコーディングし、 Oracle JavaFXチュートリアル および Ensembleサンプルコード を参照してください。あなたにとって難しい。

JavaFX APIに直接コーディングすることに慣れたら、多くのGUI要素を含む大規模なプロジェクトにFXMLを使用するように切り替えます。 FXML要素と属性自体は、標準のJavaFXAPIを反映してほぼ完全に構築されています。したがって、コアJavaFX APIを理解していれば、FXMLに関するほとんどすべてのことも理解できます。

この回答にフォローアップコメントを投稿しないでください(この回答はそのままで十分な長さです)。新しい質問がある場合は、新しい質問を作成します(質問ごとに1つの質問)。

24
jewelsea

残念ながら、JavaFx 8 WindowEventはマウスの(x、y)位置を提供しません。私は次のようにAWTMouseInfoを使用してこれを解決しました(そしてそれはうまく機能します):

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));
        });
3
George Forman

その目的でロボットを使用するのはどうですか?

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();
3
kiriloff