如何将工具提示添加到JavaFX画布的矩形区域
在我的JavaFX应用程序中,我有一个带有多列的如何将工具提示添加到JavaFX画布的矩形区域,javafx,tooltip,javafx-8,Javafx,Tooltip,Javafx 8,在我的JavaFX应用程序中,我有一个带有多列的TableView,其中一列以图形形式显示数据。为此,我创建了一个CanvasCell对象,它创建并管理自己的Canvas来处理绘图。绘图部分工作得很好 我现在想在画布/单元格中的一些区域上放置工具提示。每个单元格可能有多个工具提示(这会阻止我在单元格级别添加工具提示),它们应该只在图形的特定区域触发。然而,我根本无法让它正常工作。我似乎不太了解显示节点层次结构的交互作用(请阅读“全部”),因此无法将工具提示放置在实际工作的任何位置 JavaFX的
TableView
,其中一列以图形形式显示数据。为此,我创建了一个CanvasCell
对象,它创建并管理自己的Canvas
来处理绘图。绘图部分工作得很好
我现在想在画布
/单元格
中的一些区域上放置工具提示
。每个单元格可能有多个工具提示
(这会阻止我在单元格
级别添加工具提示
),它们应该只在图形的特定区域触发。然而,我根本无法让它正常工作。我似乎不太了解显示节点层次结构的交互作用(请阅读“全部”),因此无法将工具提示放置在实际工作的任何位置
JavaFX的文档很少,而Google+在我尝试过的所有搜索中都是空白的。有没有人知道如何做这类事情,或者我现在应该把它当作“不可选择的”一笔勾销
对于信息,CanvasCell
在updateItem()
上的扩展Canvas
对象内调用draw()
函数。我试图在其中创建工具提示的代码位于draw()
函数中,看起来像:
Rectangle rect = new Rectangle(leftVal, topVal, width, height);
gc.fillRect(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
Tooltip tooltip = new Tooltip("Tooltip Text");
Tooltip.install(rect, tooltip);
但这段代码写得比其他任何东西都更有希望,在接口中没有生成任何有用的东西
如果有人能给我指出正确的方向,我将非常感激。我有@Slaw建议的相同解决方案。我的想法是使其更加集中,以便可以传递要显示工具提示的节点及其区域
在下面的演示中,您可以将setToolTips()用作多个节点的静态实用性方法
注意:逻辑的某些部分来自工具提示核心实现;)
导入javafx.animation.animation;
导入javafx.animation.KeyFrame;
导入javafx.animation.Timeline;
导入javafx.application.application;
导入javafx.geometry.Bounds;
导入javafx.geometry.Rectangle2D;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.control.Tooltip;
导入javafx.scene.layout.StackPane;
导入javafx.stage.stage;
导入javafx.util.Duration;
导入java.util.HashMap;
导入java.util.Map;
公共类MultiTooltipDemo扩展了应用程序{
私人双人滑鼠;
私人双人滑鼠;
私有静态int工具提示\u XOFFSET=10;
私有静态int工具提示_YOFFSET=7;
@凌驾
public void start(Stage)引发异常{
StackPane root=新的StackPane();
场景sc=新场景(根,600600);
第二阶段(sc);
stage.show();
StackPane box1=新的StackPane();
框1.setMaxSize(200200);
框1.setStyle(“-fx背景色:红、蓝、黄、绿;-fx背景插图:01100、01000100、10010000100;”);
root.getChildren().add(框1);
映射工具提示=新建HashMap();
工具提示。放置(“我是红色的”,新矩形2D(0,0,100,100));
工具提示。放置(“我是蓝色的”,新矩形2D(100,0,100,100));
工具提示。放置(“我是黄色的”,新矩形2D(01000100));
工具提示。放置(“我是绿色的”,新矩形2D(100100100100));
设置工具提示(框1,工具提示);
}
专用void集合工具提示(节点、贴图工具提示){
持续时间openDelay=持续时间。毫秒(1000);
持续时间hideDelay=持续时间。毫秒(5000);
工具提示工具提示=新工具提示();
Timeline hideTimer=新的Timeline();
getKeyFrames().add(新关键帧(hideDelay));
hideTimer.setOnFinished(事件->{
toolTip.hide();
});
Timeline activationTimer=新时间线();
activationTimer.getKeyFrames().add(新关键帧(openDelay));
activationTimer.setOnFinished(事件->{
Bounds NodeScreenbunds=node.localToScreen(node.getBoundsInLocal());
double nMx=nodeScreenBounds.getMinX();
double nMy=nodeScreenBounds.getMinY();
工具提示。setText(“”);
工具提示。forEach((str,bounds)->{
double mnX=nMx+bounds.getMinX();
double mnY=nMy+bounds.getMinY();
double mxX=mnX+bounds.getWidth();
double mxY=mnY+bounds.getHeight();
如果(lastMouseX>=mnX&&lastMouseX=mnY&&lastMouseY{
双buffPx=2;
double eX=e.getScreenX();
双eY=e.getScreenY();
//显示工具提示时不隐藏鼠标的轻微移动
if(hideTimer.getStatus()==Animation.Status.RUNNING){
if(lastMouseX-buffPx=eX&&lastMouseY-buffPx=eY){
回来
}
}
lastMouseX=e.getScreenX();
lastMouseY=e.getScreenY();
toolTip.hide();
hideTimer.stop();
activationTimer.playFromStart();
});
node.setOnMouseExited(e->{
toolTip.hide();
activationTimer.stop();
hideTimer.stop();
});
}
公共静态void main(字符串[]args){
应用程序启动(args);
}
}
我有与@Slaw建议的解决方案相同的解决方案。我的想法是使其更加集中,以便您可以传递要显示工具提示的节点及其区域
在下面的演示中,您可以将setToolTips()用作多个节点的静态实用性方法
注意:逻辑的某些部分来自工具提示核心实现;)
导入javafx.animation.animation;
导入javafx.animation.KeyFrame;
导入javafx.animation.Timeline;
导入javafx.application.application;
导入javafx.geometry.Bounds;
导入javafx.geometry.Rec
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.util.HashMap;
import java.util.Map;
public class MultiTooltipDemo extends Application {
private double lastMouseX;
private double lastMouseY;
private static int TOOLTIP_XOFFSET = 10;
private static int TOOLTIP_YOFFSET = 7;
@Override
public void start(Stage stage) throws Exception {
StackPane root = new StackPane();
Scene sc = new Scene(root, 600, 600);
stage.setScene(sc);
stage.show();
StackPane box1 = new StackPane();
box1.setMaxSize(200, 200);
box1.setStyle("-fx-background-color:red, blue, yellow, green; -fx-background-insets: 0 100 100 0, 0 0 100 100, 100 100 0 0, 100 0 0 100;");
root.getChildren().add(box1);
Map<String, Rectangle2D> tooltips = new HashMap<>();
tooltips.put("I am red", new Rectangle2D(0, 0, 100, 100));
tooltips.put("I am blue", new Rectangle2D(100, 0, 100, 100));
tooltips.put("I am yellow", new Rectangle2D(0, 100, 100, 100));
tooltips.put("I am green", new Rectangle2D(100, 100, 100, 100));
setToolTips(box1, tooltips);
}
private void setToolTips(Node node, Map<String, Rectangle2D> tooltips) {
Duration openDelay = Duration.millis(1000);
Duration hideDelay = Duration.millis(5000);
Tooltip toolTip = new Tooltip();
Timeline hideTimer = new Timeline();
hideTimer.getKeyFrames().add(new KeyFrame(hideDelay));
hideTimer.setOnFinished(event -> {
toolTip.hide();
});
Timeline activationTimer = new Timeline();
activationTimer.getKeyFrames().add(new KeyFrame(openDelay));
activationTimer.setOnFinished(event -> {
Bounds nodeScreenBounds = node.localToScreen(node.getBoundsInLocal());
double nMx = nodeScreenBounds.getMinX();
double nMy = nodeScreenBounds.getMinY();
toolTip.setText("");
tooltips.forEach((str, bounds) -> {
double mnX = nMx + bounds.getMinX();
double mnY = nMy + bounds.getMinY();
double mxX = mnX + bounds.getWidth();
double mxY = mnY + bounds.getHeight();
if (lastMouseX >= mnX && lastMouseX <= mxX && lastMouseY >= mnY && lastMouseY <= mxY) {
toolTip.setText(str);
}
});
if (!toolTip.getText().isEmpty()) {
toolTip.show(node.getScene().getWindow(), lastMouseX + TOOLTIP_XOFFSET, lastMouseY + TOOLTIP_YOFFSET);
hideTimer.playFromStart();
}
});
node.setOnMouseMoved(e -> {
double buffPx = 2;
double eX = e.getScreenX();
double eY = e.getScreenY();
// Not hiding for slight mouse movements while tooltip is showing
if (hideTimer.getStatus() == Animation.Status.RUNNING) {
if (lastMouseX - buffPx <= eX && lastMouseX + buffPx >= eX && lastMouseY - buffPx <= eY && lastMouseY + buffPx >= eY) {
return;
}
}
lastMouseX = e.getScreenX();
lastMouseY = e.getScreenY();
toolTip.hide();
hideTimer.stop();
activationTimer.playFromStart();
});
node.setOnMouseExited(e -> {
toolTip.hide();
activationTimer.stop();
hideTimer.stop();
});
}
public static void main(String[] args) {
Application.launch(args);
}
}
node.setOnMouseMoved(e -> {
tooltips.forEach((color, bounds) -> {
if (bounds.contains(e.getX(), e.getY())) {
tooltip.setText(color.toString());
}
});
});
import javafx.application.Application;
import javafx.scene.shape.Rectangle;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.StackPane;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.stage.Stage;
import java.util.HashMap;
import java.util.Map;
/**
* @see https://stackoverflow.com/a/53785468/230513
* @see https://stackoverflow.com/a/53753537/230513
*/
public class CanvasTooltipDemo extends Application {
@Override
public void start(Stage stage) throws Exception {
StackPane root = new StackPane();
Scene sc = new Scene(root, 400, 400);
stage.setScene(sc);
Canvas canvas = new Canvas(200, 200);
root.getChildren().add(canvas);
Map<Color, Rectangle> tooltips = new HashMap<>();
tooltips.put(Color.RED, new Rectangle(0, 0, 100, 100));
tooltips.put(Color.BLUE, new Rectangle(100, 0, 100, 100));
tooltips.put(Color.YELLOW, new Rectangle(0, 100, 100, 100));
tooltips.put(Color.GREEN, new Rectangle(100, 100, 100, 100));
GraphicsContext gc = canvas.getGraphicsContext2D();
tooltips.forEach((color, bounds) -> {
gc.setFill(color);
gc.fillRect(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
});
setToolTips(canvas, tooltips);
stage.show();
}
private void setToolTips(Node node, Map<Color, Rectangle> tooltips) {
Tooltip tooltip = new Tooltip();
Tooltip.install(node, tooltip);
node.setOnMouseMoved(e -> {
tooltips.forEach((color, bounds) -> {
if (bounds.contains(e.getX(), e.getY())) {
tooltip.setText(color.toString());
}
});
});
node.setOnMouseExited(e -> {
tooltip.hide();
});
}
public static void main(String[] args) {
Application.launch(args);
}
}