Canvas: hover over text output

别来无恙 提交于 2020-12-13 04:59:04

问题


I want to hover over a shape I created in Canvas (JavaFx) and when hovering over with the mouse I want a text output pop-up to display. Is there a built in function for this? I can't find how to do it anywhere...


回答1:


Unlike with the scene graph, a Canvas has no notion of what it contains. It's nothing but a two-dimensional array of pixels and provides no further distinctions than that. If you want to know if and when the mouse hovers over a "shape" in the Canvas you'll have to keep track of where the "shape" is and do the necessary computations manually. Here's an example which shows a popup at the mouse's location only while within the drawn rectangle:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Popup;
import javafx.stage.Stage;

public class App extends Application {

  @Override
  public void start(Stage primaryStage) {
    // used to test if mouse is within the rectangle
    var bounds = new Rectangle2D(200, 100, 100, 100);

    var canvas = new Canvas(500, 300);
    // draw rectangle using above bounds
    canvas.getGraphicsContext2D().setFill(Color.FIREBRICK);
    canvas
        .getGraphicsContext2D()
        .fillRect(bounds.getMinX(), bounds.getMinY(), bounds.getWidth(), bounds.getHeight());

    var popup = createPopup();
    canvas.setOnMouseMoved(
        e -> {
          // test if local mouse coordinates are within rectangle
          if (bounds.contains(e.getX(), e.getY())) {
            // convert local coordinates to screen coordinates
            var point = canvas.localToScreen(e.getX(), e.getY());
            // show the popup at the mouse's location on the screen
            popup.show(canvas, point.getX(), point.getY());
          } else if (popup.isShowing()) {
            // hide popup if showing and mouse no longer within rectangle
            popup.hide();
          }
        });

    primaryStage.setScene(new Scene(new Pane(canvas)));
    primaryStage.show();
  }

  private Popup createPopup() {
    var content = new StackPane(new Label("Hello, World!"));
    content.setPadding(new Insets(10, 5, 10, 5));
    content.setBackground(
        new Background(new BackgroundFill(Color.WHITE, new CornerRadii(10), null)));
    content.setEffect(new DropShadow());

    var popup = new Popup();
    popup.getContent().add(content);

    return popup;
  }
}

As you can see, this is relatively simple for a static image consisting of a single, rectangular shape. This can quickly become more complicated just by making the image dynamic, let alone by having to test the bounds of irregular shapes.

An easier approach would be to use the scene graph. Instead of drawing to a Canvas you would add a Rectangle to a layout. Then you can use the Node API to know when the mouse enters and exits the Rectangle (e.g. setOnMouseXXX, hover property, etc.). It also makes it easier to use something like a Tooltip, which can simply be "installed" on the Node.



来源:https://stackoverflow.com/questions/62692538/canvas-hover-over-text-output

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!