从集合中获取对象

时间:2019-04-07 19:32:12

标签: java javafx javafx-8

我正在用矩形构建网格。

我要单击其中一个矩形,其颜色应更改。

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

enter image description here

主要:

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;
    }
}

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

1 个答案:

答案 0 :(得分:1)

按照当前的设计,您只需要测试鼠标是否在子级中单击,以及该子级是否为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的空间 1 。然后,我们需要使用Rectangle测试Node.contains的边界是否包含那些坐标;如果可以,请更改填充。

也就是说,您可能需要修改代码,以便将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。即使他们不是直接的孩子,您仍然可以将坐标转换为局部空间。例如,您可以使用Node.sceneToLocalMouseEvent提供的场景坐标(即getSceneX() / getSceneY())。
2。这仍然与您的设计保持接近。但是,您可能需要将事情重新考虑为适当的MVC(或其他)体系结构。 Applying MVC With JavaFx