I am building an editor in JavaFx in which the user can add modules. Each module has a number of inputs which are JavaFX-circles and can be moved via Drag and Drop. Between the circles there can be lines (from the center of one circle to the center of another circles).
I also looked at this question, but the problem is, that my circles are not children of the node the lines are drawn in.
So I have the following code (I am using ControlsFX for drawing borders):
public class EditorTest extends Application
{
private Pane editorPane;
@Override
public void start(Stage primaryStage) throws Exception
{
VBox root = new VBox();
MenuBar menuBar = new MenuBar();
menuBar.getMenus().add(new Menu("Test"));
editorPane = new Pane();
root.getChildren().add(menuBar);
root.getChildren().add(editorPane);
editorPane.setPrefSize(1000, 700);
initBindings();
Scene scene = new Scene(root);
editorPane.requestFocus();
primaryStage.setScene(scene);
primaryStage.show();
}
private void initBindings()
{
editorPane.setOnMouseClicked((event) ->
{
if (event.getButton() == MouseButton.SECONDARY)
{
Module moduleInput = new Module();
Node inputGui = moduleInput.getGui();
inputGui.setLayoutX(event.getX());
inputGui.setLayoutY(event.getY());
Module moduleOutput = new Module();
Node outputGui = moduleOutput.getGui();
outputGui.setLayoutX(event.getX() + 200);
outputGui.setLayoutY(event.getY());
Wire line = new Wire();
line.setInput(moduleInput.getPort());
line.setOutput(moduleOutput.getPort());
editorPane.getChildren().add(inputGui);
editorPane.getChildren().add(outputGui);
editorPane.getChildren().add(line);
}
});
}
public static void main(String[] args)
{
launch(args);
}
}
This is the class for the lines:
public class Wire extends Line
{
private Port input;
private Port output;
public Wire()
{
super();
setStroke(Color.GREEN);
setStrokeWidth(3);
}
public void setInput(Port input)
{
this.input = input;
input.connectWire(this);
update();
}
public void setOutput(Port output)
{
this.output = output;
output.connectWire(this);
update();
}
public void update()
{
if (input != null)
{
Point2D centerInput = input.localToScene(input.getCenterX(), input.getCenterY());
System.out.println(centerInput);
setStartX(centerInput.getX());
setStartY(centerInput.getY());
}
if (output != null)
{
Point2D centerOutput = output.localToScene(output.getCenterX(), output.getCenterY());
setEndX(centerOutput.getX());
setEndY(centerOutput.getY());
}
}
}
This is for inputs:
public class Port extends Circle
{
private Wire connLine;
public Port()
{
super(10, Color.ALICEBLUE);
setStroke(Color.BLACK);
}
public void connectWire(Wire connLine)
{
this.connLine = connLine;
}
public void update()
{
if (connLine != null)
connLine.update();
}
}
This are the modules:
public class Module extends Pane
{
private double oldX;
private double oldY;
private Port circle;
public Module()
{
HBox root = new HBox(5);
root.setAlignment(Pos.CENTER);
circle = new Port();
root.getChildren().add(circle);
getChildren().add(root);
}
public Node getGui()
{
Node returnPane = Borders.wrap(this).lineBorder().title("Test").buildAll();
returnPane.setOnMousePressed((event) ->
{
if (event.getButton() == MouseButton.PRIMARY)
{
oldX = returnPane.getLayoutX() - event.getSceneX();
oldY = returnPane.getLayoutY() - event.getSceneY();
}
});
returnPane.setOnMouseDragged((event) ->
{
if (event.getButton() == MouseButton.PRIMARY)
{
double newX = event.getSceneX() + oldX;
if (newX > 0 && newX < returnPane.getScene().getWidth())
{
returnPane.setLayoutX(newX);
}
double newY = event.getSceneY() + oldY;
if (newY > 0 && newY < returnPane.getScene().getHeight())
{
returnPane.setLayoutY(newY);
}
}
});
returnPane.layoutXProperty().addListener((obs, newValue, oldValue) ->
{
circle.update();
});
returnPane.layoutYProperty().addListener((obs, newValue, oldValue) ->
{
circle.update();
});
return returnPane;
}
public Port getPort()
{
return circle;
}
}
So I think the problem is somewhere in the update
method of the Wire
because of the translation from local to parent coordinates, but with local to scene transformation it does not work because of the other nodes. I also do not understand why it doesn't work with localToParent
, because in the coordinate space of the module gui it should be correct...
Another point I dont understand is why the line is always on a wrong position before I move the nodes in the beginning.
If I add a ScrollPane
around it there are even bigger problems, so the lines are shifted by the way I scrolled.
So how can I translate the coordinates appropriately to connect the line to the centers of the ports, and it is possible to put this into a ScrollPane
?