创建不规则形状的JavaFX组件

创建不规则形状的JavaFX组件,javafx,Javafx,我正在尝试为JavaFX制作一个不规则形状的组件,并且体验到非常奇怪的行为 package pkg; import javafx.application.Application; import javafx.scene.Scene; import javafx.stage.Stage; import java.io.IOException; import javafx.event.EventHandler; import javafx.scene.input.MouseEvent; impo

我正在尝试为JavaFX制作一个不规则形状的组件,并且体验到非常奇怪的行为

package pkg;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;

public class App extends Application {

    private static Scene scene;

    @Override
    public void start(Stage stage) throws IOException {
        Pane pane = new Pane();
        for (int x = 50; x < 150; x += 50) {
            for (int y = 50; y < 150; y += 50) {
                pane.getChildren().add(new Triangle(x, y));
            }
        }
        scene = new Scene(pane, 640, 480);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

    private static class Triangle extends Region {

        Polygon p;

        public Triangle(int x, int y) {
            super();
            p = new Polygon(x - 25, y + 25, x, y - 25, x + 25, y + 25);
            setOnMouseEntered(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent t) {
                    p.setFill(Color.RED);
                    System.out.println("x: " + x + " y: " + y);
                }
            });
            setOnMouseExited(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent t) {
                    p.setFill(Color.BLACK);
                }
            });
            setShape(p);
            getChildren().add(p);
        }
    }
}
package-pkg;
导入javafx.application.application;
导入javafx.scene.scene;
导入javafx.stage.stage;
导入java.io.IOException;
导入javafx.event.EventHandler;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.Pane;
导入javafx.scene.layout.Region;
导入javafx.scene.paint.Color;
导入javafx.scene.shape.Polygon;
公共类应用程序扩展应用程序{
私人静态场景;
@凌驾
public void start(Stage)引发IOException{
窗格=新窗格();
对于(int x=50;x<150;x+=50){
对于(整数y=50;y<150;y+=50){
getChildren()添加(新三角形(x,y));
}
}
场景=新场景(窗格,640480);
舞台场景;
stage.show();
}
公共静态void main(字符串[]args){
发射();
}
私有静态类三角形扩展区域{
多边形p;
公共三角形(整数x,整数y){
超级();
p=新多边形(x-25,y+25,x,y-25,x+25,y+25);
SetOnMouseCentered(新事件处理程序(){
@凌驾
公共无效句柄(MouseEvent t){
p、 设置填充(颜色:红色);
System.out.println(“x:+x+”y:+y);
}
});
setOnMouseExited(新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent t){
p、 设置填充(颜色:黑色);
}
});
固定形状(p);
getChildren().add(p);
}
}
}
依赖项:

<dependencies>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>15.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-fxml</artifactId>
        <version>13</version>
    </dependency>
</dependencies>

org.openjfx
javafx控件
15.0.1
org.openjfx
javafx-fxml
13
运行此操作时,将创建4个三角形,每个三角形都具有鼠标悬停行为

package pkg;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;

public class App extends Application {

    private static Scene scene;

    @Override
    public void start(Stage stage) throws IOException {
        Pane pane = new Pane();
        for (int x = 50; x < 150; x += 50) {
            for (int y = 50; y < 150; y += 50) {
                pane.getChildren().add(new Triangle(x, y));
            }
        }
        scene = new Scene(pane, 640, 480);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

    private static class Triangle extends Region {

        Polygon p;

        public Triangle(int x, int y) {
            super();
            p = new Polygon(x - 25, y + 25, x, y - 25, x + 25, y + 25);
            setOnMouseEntered(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent t) {
                    p.setFill(Color.RED);
                    System.out.println("x: " + x + " y: " + y);
                }
            });
            setOnMouseExited(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent t) {
                    p.setFill(Color.BLACK);
                }
            });
            setShape(p);
            getChildren().add(p);
        }
    }
}
但是,当您将鼠标悬停在每个三角形上时,它们都会表现为右下角三角形正在被触发

这是不直观的。我不知道是什么在做那件事


这里发生了什么,以及如何使这些组件独立反应?

默认情况下,区域边界将从
[0,0]
开始,并扩展以填充所有子级所需的空间。因此,您创建的最后一个三角形实际上具有覆盖所有其他三角形的边界,并且由于它是堆栈中的最顶端(因为您最后添加它),因此它接收所有鼠标事件

如果将每个三角形向后推(这不是一个特别好的解决方案),您将看到您想要的:

    for (int x = 50; x < 150; x += 50) {
        for (int y = 50; y < 150; y += 50) {
            Triangle t = new Triangle(x, y);
            pane.getChildren().add(t);
            t.toBack();
        }
    }
三角形
构造函数。仅当鼠标位于
三角形的不透明部分上时,才会触发鼠标事件

也许您应该创建只占用它们真正需要的空间的区域。您可能还需要
setPickOnBounds(false)
调用,因此三角形只响应鼠标位于三角形部分上(而不是包含它的整个矩形区域):

私有静态类三角形扩展区域{
多边形p;
公共三角(){
超级();
p=新多边形(0,50,25,0,50,50);
SetOnMouseCentered(新事件处理程序(){
@凌驾
公共无效句柄(MouseEvent t){
p、 设置填充(颜色:红色);
}
});
setOnMouseExited(新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent t){
p、 设置填充(颜色:黑色);
}
});
固定形状(p);
getChildren().add(p);
setPickOnBounds(false);
}
}
然后,您可以按照通常的方式在其包含窗格中放置三角形:

    Pane pane = new Pane();
    for (int x = 25; x < 125; x += 50) {
        for (int y = 25; y < 125; y += 50) {
            Triangle t = new Triangle();
            pane.getChildren().add(t);
            t.setLayoutX(x);
            t.setLayoutY(y);
        }
    }
Pane Pane=new Pane();
对于(int x=25;x<125;x+=50){
对于(整数y=25;y<125;y+=50){
三角形t=新三角形();
pane.getChildren().add(t);
t、 setLayoutX(x);
t、 setLayoutY(y);
}
}
它们还将使用布局窗格:

    GridPane pane = new GridPane();
    for (int x = 0; x < 2; x++) {
        for (int y = 0; y < 2; y++) {
            Triangle t = new Triangle();
            pane.add(t, x, y);
        }
    }
GridPane=new GridPane();
对于(int x=0;x<2;x++){
对于(int y=0;y<2;y++){
三角形t=新三角形();
窗格。添加(t,x,y);
}
}

默认情况下,该区域的边界将从
[0,0]
开始,并扩展以填充所有子级所需的空间。因此,您创建的最后一个三角形实际上具有覆盖所有其他三角形的边界,并且由于它是堆栈中的最顶端(因为您最后添加它),因此它接收所有鼠标事件

如果将每个三角形向后推(这不是一个特别好的解决方案),您将看到您想要的:

    for (int x = 50; x < 150; x += 50) {
        for (int y = 50; y < 150; y += 50) {
            Triangle t = new Triangle(x, y);
            pane.getChildren().add(t);
            t.toBack();
        }
    }
三角形
构造函数。仅当鼠标位于
三角形的不透明部分上时,才会触发鼠标事件

也许您应该创建只占用它们真正需要的空间的区域。您可能还需要
setPickOnBounds(false)
调用,因此三角形只响应鼠标位于三角形部分上(而不是包含它的整个矩形区域):

私有静态类三角形扩展区域{
多边形p;
公共三角(){
超级();
p=新多边形(0,50,25,0,50,50);
SetOnMouseCentered(新事件处理程序(){
@凌驾
公共无效句柄(MouseEvent t){
p、 设置填充(颜色:红色);
}
});
setOnMouseExited(新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent t){
p、 设置填充(颜色:黑色);
}
});
固定形状(p);
getChildren().add(p);
setPickOnBounds(false);
}
}
然后,您可以按照通常的方式在其包含窗格中放置三角形:

    Pane pane = new Pane();
    for (int x = 25; x < 125; x += 50) {
        for (int y = 25; y < 125; y += 50) {
            Triangle t = new Triangle();
            pane.getChildren().add(t);
            t.setLayoutX(x);
            t.setLayoutY(y);
        }
    }
Pane Pane=new Pane();
为了