簡體   English   中英

JavaFX 似乎丟失了我的事件處理程序?

[英]Does JavaFX seem to be losing my event handler?

我是 JavaFX 的新手,對 Java 整體來說還是個新手。 我正在設計用於自學項目的無向圖的圖形表示。 現在,我正在嘗試使節點可拖動,以便邊緣可以拉伸以與它們的節點保持連接。 在有連接的 2 個節點的情況下,我已經實現了這一點。 但是,添加三分之一會有些奇怪。

假設我們有這樣的情況:

Cell testOne = new Cell ("testOne", 123);
Cell testTwo = new Cell ("testTwo", 456);
Cell testThree = new Cell ("testThree", 200);

testOne.addConnection(testTwo);
testOne.addConnection(testThree);

我得到的是三個節點,兩條線隨機散布在它們的一般區域(值得注意的是節點以粗略的隨機方式定位)。 如果我在 testTwo 或 testThree 周圍移動,單條線將權衡連接到 testOne。 無論如何,第二行保持不變。 我不得不認為正在發生的事情是其中一個 EventHandlers 正在從它們各自的單元中“拔出”,否則其中一條線路在內存中丟失了。 這是繪制線條的代碼(我知道它真的很笨重)。 此方法位於 Graph 類中,該類控制類的圖形 (oop) 表示。 “cells”是存儲其所有節點的ArrayList,“connections”是Cell實例中的arrayList,用於跟蹤它所連接的所有節點,而“LinesBetween”是一個HashMap,Cell實例跟蹤一條線是否已經存在在兩個節點之間繪制。

public void drawAndManageEdgeLines(){
        if (cells.size() > 1) { //don't wanna make connections if there's only one cell, or none
            int count = 0;
            for (Cell cell : cells) { // for every cell on the graph
                List<Cell> connectionsList = cell.getConnections(); // look at that cell's connections
                if (!connectionsList.isEmpty()) {// validate that the cell is actually supposed to be connected to something
                    for (Cell connection : connectionsList) { // go through all their connections
                        if (!cell.getLinesBetween().get(connection) && cell.getLinesBetween().get(connection) != null) { //check to see whether there is already a line between them

                            Circle sourceCircle = cell.getCellView();
                            Circle targetCircle = connection.getCellView();

                            Bounds sourceBound = sourceCircle.localToScene(sourceCircle.getBoundsInLocal());
                            Bounds targetBound = targetCircle.localToScene(targetCircle.getBoundsInLocal());

                            double targetX = targetBound.getCenterX();
                            double targetY = targetBound.getCenterY();
                            double sourceX = sourceBound.getCenterX();
                            double sourceY = sourceBound.getCenterY();

                            edge = new Line(sourceX, sourceY, targetX, targetY);
                            edge.setStroke(Color.BLACK);
                            edge.setStrokeWidth(2);

                            getChildren().add(edge);

                            edge.toBack();
                            cell.setLinesBetweenEntry(connection, true);
                            connection.setLinesBetweenEntry(cell, true);
                            // these handlers control where the line is dragged to 
                            cell.addEventHandler(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
                                @Override
                                public void handle(MouseEvent e) {
                                    edge.setStartX(e.getSceneX()); //this is a really cool method
                                    edge.setStartY(e.getSceneY());
                                    e.consume();
                                }
                            });
                            System.out.println("on round " + count + " we got there: ");
                            connection.addEventHandler(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
                                @Override
                                public void handle(MouseEvent e) {
                                    edge.setEndX(e.getSceneX());
                                    edge.setEndY(e.getSceneY());
                                    e.consume();
                                }
                            });
                        }
                    }
                }
            }
        }
    }

如果沒有適當的最小可重復示例,很難判斷出了什么問題,但是您似乎使這比需要的更復雜。 如果您希望邊“鏈接”到節點,那么我建議您使用綁定。 這是一個概念驗證:

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class Main extends Application {

  @Override
  public void start(Stage primaryStage) {
    Circle node1 = new Circle(100, 100, 50, Color.FIREBRICK);
    Circle node2 = new Circle(900, 550, 50, Color.DARKBLUE);
    Circle node3 = new Circle(900, 100, 50, Color.DARKGREEN);

    addDragHandling(node1);
    addDragHandling(node2);
    addDragHandling(node3);

    Line edge1 = createEdge(node1, node2);
    Line edge2 = createEdge(node1, node3);

    Pane root = new Pane(edge1, edge2, node1, node2, node3);
    primaryStage.setScene(new Scene(root, 1000, 650));
    primaryStage.show();
  }

  private Line createEdge(Circle from, Circle to) {
    Line edge = new Line();
    edge.setStrokeWidth(2);
    edge.startXProperty().bind(from.centerXProperty());
    edge.startYProperty().bind(from.centerYProperty());
    edge.endXProperty().bind(to.centerXProperty());
    edge.endYProperty().bind(to.centerYProperty());
    return edge;
  }

  private void addDragHandling(Circle circle) {
    // changing cursors not necessary, only included to help indicate
    // when something can be dragged and is being dragged
    circle
        .cursorProperty()
        .bind(
            Bindings.when(circle.pressedProperty())
                .then(Cursor.CLOSED_HAND)
                .otherwise(Cursor.OPEN_HAND));

    double[] offset = {0, 0}; // (x, y)
    circle.setOnMousePressed(
        e -> {
          offset[0] = e.getX() - circle.getCenterX();
          offset[1] = e.getY() - circle.getCenterY();
          e.consume();
        });
    circle.setOnMouseDragged(
        e -> {
          circle.setCenterX(e.getX() - offset[0]);
          circle.setCenterY(e.getY() - offset[1]);
          e.consume();
        });
  }
}

注意我首先將邊添加到Pane以便在節點下繪制它們。 請參閱JavaFX 中的 Z 順序 此外,根據您用來表示圖形節點的Node ,您的拖動邏輯可能看起來有所不同。

由於您表示的是圖表,因此您的應用程序將更加復雜。 如果圖形是動態的並且您希望視圖實時更新,那么您需要保留對節點及其關聯邊的引用,以便隨意添加和刪除它們。 但請記住,視圖只是模型的可視化表示。 不要使用視圖來存儲模型信息(例如實際存在哪些節點和邊)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM