javafx-8 - 如何限制 JavaFx8 Polygon-Triangle 的 MouseEvents:仅触发三角形本身,而不是三角形布局矩形边界?
问题描述
我使用 Polygon 对象创建了一个三角形,以及允许在屏幕周围鼠标拖动三角形的 onMousePressed、Dragged、Release 事件。在我创建的 JavaFX 应用程序(用于独立笔记本电脑)游戏中运行良好。
问题是,我希望 Triangle MouseEvents 仅在三角形形状边界内触发,而不是在三角形之外触发。目前,事件似乎在 Polygon-Triangle 不可见 RECTANGLE 布局范围内的任何地方触发(即嵌入/包围三角形的不可见矩形)。此行为允许通过以下方式拖动三角形:1) 光标在三角形的外部和 2) 光标在 Polygon-Triangle 不可见矩形边界内的任何位置。
这种行为通过以下方式使用户感到困惑:1) 无意中拖动三角形,2) 阻止其他游戏片段的事件(被不可见的三角形矩形边界重叠。)使它们无法播放,直到三角形被拖出。
我已经使用 Ellipse 对象和“setPickOnBounds(true);”属性完成了对 Shape 的 MouseEvent 限制。似乎与 Polygon 对象不一样。
我在 stackOverflow.com 上进行了检查,我能找到的解决此问题的最接近的文章如下,它没有解决 MouseEvent 在 Shapes 内部/外部触发的问题。
StackOverflow.com: 1. 如何平滑拖动 JavaFX 多边形? 如何平滑拖动 JavaFX 多边形? 文章未涉及形状可点击区域。
- Android 自定义形状按钮
Android 自定义形状按钮
是 5 岁和 Android 特定的,javaFX8 和多边形是否有更有效的方法?此外,我的三角形尺寸是动态的,可以与嵌入的用户格式化 LabelText 的大小相匹配。
因此,要使用三角形图像文件,需要数百个三角形文件才能获得最佳选择。
请帮助...谢谢。迈克尔
我创建三角形的代码:
public static class StrategySelfNote_Element extends Group {
public Polygon triangle;
public Label label;
public StrategySelfNote_Element(int id) {
// Triangle ********************************************************************************
triangle = new Polygon();
triangle.setId(Integer.toString(id)+";StrategySelfNote");
triangle.setFill(Color.AQUA);
triangle.setCursor(Cursor.HAND);
triangle.setVisible(false);
triangle.setLayoutX(0);
triangle.setLayoutY(0);
triangle.setCache(true);
// NOTE: This allowed Ellipse to be Dragged by MouseEvent, else only by Label (not sure if required w/Triangle???)
triangle.setPickOnBounds(true);
// Label **********************************************************************************
label = new Label();
label.setId(Integer.toString(id)+";StrategySelfNote");
label.setFont(Font.font ("Calibri", FontWeight.BOLD, IntroQuestions.sizeFont_strategySelfNotes));//28
label.setWrapText(true);
label.setMaxWidth(MAX_WIDTH_STRATEGY_SELF_NOTE); // To Prevent HUGE TextRectangle
label.setMaxHeight(MAX_HEIGHT_STRATEGY_SELF_NOTE);
label.setAlignment(Pos.TOP_LEFT);
label.setStyle("-fx-background-color: aqua;"); // -fx-background-color: AQUA; // light-yellow
//-------------
label.setCursor(Cursor.HAND);
label.setVisible(false);
label.setLayoutX(0); //debug: TRY 0 like before---to FIX When Dragging to 3/4 Quad, FREEZES & PANs scrlPane !!!
label.setLayoutY(0);
label.setCache(true);
//-------------
getChildren().addAll(triangle, label);
//------------- paneElement
this.setLayoutX(0.0); //10-26
this.setLayoutY(0.0);
this.setId(Integer.toString(id)+";StrategySelfNote");
this.setPickOnBounds(true); // NOTE: This allows Polygon to be Dragged by MouseEvent, else only by Label
this.setVisible(false);
this.setCache(true);
//-----
this.setOnMousePressed(boardStrategySelfNote_OnMousePressedEventHandler);
this.setOnMouseDragged(boardStrategySelfNote_OnMouseDraggedEventHandler);
this.setOnMouseReleased(boardStrategySelfNote_OnMouseReleasedEventHandler);
this.addEventFilter(InputEvent.ANY, boardStrategySelfNote_OnMouseFilterEventHandler);
}
}
. . . 这是来自另一个函数,计算和设置三角形:
llStrategySelfNotes.get(strategySelfNote_id-1).groupStrategySelfNote_Element.triangle.getPoints().addAll(
triBottomLeftX, triBottomLeftY,
triBottomRightX, triBottomRightY,
triTopX, triTopY);
解决方案
更正我的初始描述:我说 Ellipse 对象 bounds-rectangle 没有捕获底层/重叠对象的鼠标事件。错误的。它们确实存在与三角形相同的问题(我现在假设,所有 javaFX Shape 对象子对象也是如此。)
***********我的肮脏解决方案************* 我找到了一个肮脏但大多数可行的解决方案来解决这个问题,显然是由所有 javaFX Shape 对象子级产生的。问题是由 Shape 对象 bounds-rectangle 捕获底层/重叠对象的鼠标事件引起的......我无法对鼠标事件触发进行编码以仅限制形状,同时仍然使重叠对象可点击:
1)内部三角形onMousedPressed事件处理程序:检查用户是否点击了OutsideTriangle-but-InsideTriangleRectBounds:(使用重心风格算法......stackOverflow上有很多可用的)
static boolean isInside(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3) {
double L1 = (x-x1)*(y3-y1) - (x3-x1)*(y-y1),
L2 = (x-x2)*(y1-y2) - (x1-x2)*(y-y2),
L3 = (x-x3)*(y2-y3) - (x2-x3)*(y-y3);
return (L1>0 && L2>0 && L3>0) || (L1<0 && L2<0 && L3<0);
}
isInTriangle = isInside (t.getX(), t.getY(),
triBottomLeftX, triBottomLeftY,
triBottomRightX, triBottomRightY,
triTopX, triTopY);
2) 如果高于 TRUE,则将 isClickedOutsideTriangle 标志设置为 TRUE,然后退出/返回事件处理程序而不消耗事件。
3) TEST isClickedOutsideTriangle 标志位于内部 onMousedDragged 事件处理程序的开头。如果为真,则从处理程序退出/返回,而不使用消耗()。
4) 在 Triangle onMousedReleased 事件处理程序内部: - 测试 Triangle bounds-rectangle 是否与任何游戏板元素相交。如果是:[为了保留用户指定的游戏部件 zIndex] - 保存所有元素 zIndex 值。-SORT Element zIndex values Ascending -SET sorted value Elements toFront() [这现在允许所有元素都是可点击的]
5) 如果 isClickedOutsideTriangle 标志为 TRUE,则重置为 FALSE。
警告:这个解决方案的一个不幸的副作用是:用户永远不会被允许让三角形重叠任何其他游戏元素,但其他游戏元素可以重叠三角形!
我仍在寻找使用 javaFX 对象属性/方法的更简单的解决方案,这将允许 1)Shape-object bounds-rectangle 底层元素的完全可点击性和 2)Shapes 的动态大小,由游戏期间的用户格式化决定???? ?
推荐阅读
- angular - Ionic 3 项目未通过抛出错误生成生产 apk
- javascript - 如何通过检查 React js 中的所有数据库值来设置按钮颜色?
- kdb - 根据标准在KDB中标记前N天的值?
- forms - Angular 7 FormControl将输入从数字转换为字符串
- python - 使用 pandas 合并数千个 csv 文件
- awk - 如果倒数第二个或倒数第二个字符是 CSV 第一列中的空格,则删除行
- c# - 添加光照处理后Shader不工作
- javascript - 当我在 chrome mobile 中向下滚动时,绝对定位的 DIV 会改变位置,如何解决这个问题?
- matplotlib - 我无法增加绘图的大小(图表)
- java - 如何在克隆对象时修复克隆错误