从集合中获取对象

Get Object from Collection

我正在用矩形构建网格。

我想单击其中一个矩形,它的颜色应该会改变。

但是,我不知道如何在创建 Main 中访问矩形。

主要:

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;

public class Main extends Application{

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

    public void changeColor(Pane p) {
         p.setOnMouseClicked(me -> {
            double posX = me.getX();
            double posY = me.getY();

            int colX = (int)(posX / 30);
            int colY = (int) (posY / 30);

            ObservableList<Node> children = p.getChildren();
            for( Node d : children) {
                    if(d.getLayoutX() == colX && d.getLayoutY() == colY) {
                        // how can i access my rectangle here?
                        // basically, i want to be able to do .setFill()
                    }
            }
        });
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Grid g = new Grid(30,30, 30);
        Pane window = g.render();
        Scene scene = new Scene(window, 500, 500);
        primaryStage.setScene(scene);
        primaryStage.show();
        this.changeColor(window);

    }
}

网格:

import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;


public class Grid {

    Integer width, height, squareSize; 
    Color fill = Color.ALICEBLUE, 
        stroke = Color.BLACK;

    public Grid(int x, int y, int squareSize){
        this.width = x; 
        this.height = y;
        this.squareSize = squareSize;
    }

    public Pane render() {
        Pane p = new Pane();
        Rectangle [][] rect = new Rectangle[this.width][this.height];
        for(int i = 0; i < this.width; i++) {
            for(int j = 0; j < this.height; j++) {
                rect[i][j] = new Rectangle();
                rect[i][j].setX(i * width);
                rect[i][j].setY(j * height);
                rect[i][j].setWidth(this.squareSize);
                rect[i][j].setHeight(this.squareSize);
                rect[i][j].setFill(this.fill);
                rect[i][j].setStroke(this.stroke);              
                p.getChildren().add(rect[i][j]);
            }
        }
        return p;
    }
}

有人可以帮我弄清楚如何在主文件中再次访问我的矩形吗?

与您当前的设计保持一致,您只需要测试鼠标是否在子项内单击以及该子项是否是 Rectangle 的实例;然后你可以施放和调用 setFill。但是,我建议更改 changeColor 的名称,因为该名称并不代表该方法的作用。

public void installChangeColorHandler(Pane pane) {
    pane.setOnMouseClicked(event -> {
        for (Node child : pane.getChildren()) {
            if (child instanceof Rectangle 
                    && child.contains(child.parentToLocal(event.getX(), event.getY()))) {
                ((Rectangle) child).setFill(/* YOUR COLOR */);
                event.consume();
                break;
            }
        }
    });
}

由于事件处理程序被添加到 Pane,因此 xy 鼠标坐标是相对于所述 Pane 的。但是由于您的 RectanglePane 的直接子代,我们可以调用 Node.parentToLocal 将这些坐标转换为 Rectangle 的 space1 。然后我们需要使用 Node.contains 测试 Rectangle 的边界是否包含这些坐标;如果是,请更改填充。

也就是说,您可能需要修改代码,以便将 an/the EventHandler 直接添加到 Rectangle。这样你就可以使用 Event.getSource()。例如2:

public Pane render(EventHandler<MouseEvent> onClick) {
    // outer loop...
        // inner loop...
            Rectangle r = new Rectangle();
            // configure r...
            r.setOnMouseClicked(onClick);
        // end inner loop...
    // end outer loop...
}

...

// may want to consume event
Pane window = new Grid(30, 30, 30).render(event ->
        ((Rectangle) event.getSource()).setFill(/* YOUR COLOR */));

1.即使它们不是直接子代,您仍然可以将坐标转换为本地 space。例如,您可以使用 Node.sceneToLocalMouseEvent 提供的场景坐标(即 getSceneX()/getSceneY())。
2。这仍然接近您的设计。但是,您可能需要重新考虑将事情纳入适当的 MVC(或其他)架构。