我正在设计一个带有可拖动节点的图形结构的UI。在图中,我有一个名为relation的组件(它是一个窗格),它显示了两个节点之间的链接。我希望关系能够保持并在线中间移动。
当前的UI设计如下所示
而预期的一个是:
修改线的末端坐标时,需要刷新节点的位置。为了避免每次布局传递多次触发计算,我建议从父级的layoutChildren
方法执行此操作,但您也可以从侦听器到startX
,endY
,...属性执行此操作。这将导致一些不必要的计算。
至于计算节点的位置:节点的中心需要与线的中点对齐,所以你需要为qazxsw poi求解下面的等式:
markTopLeft
markTopLeft + (markWidth, markHeight) / 2 = (lineStart + lineEnd) / 2
markTopLeft = (lineStart + lineEnd - (markWidth, markHeight)) / 2
public class PostProcessPane extends Pane {
private final Set<Node> modifiedChildren = new HashSet<>();
private final Set<Node> modifiedChildrenUnmodifiable = Collections.unmodifiableSet(modifiedChildren);
private final List<Consumer<Set<Node>>> postProcessors = new ArrayList<>();
public List<Consumer<Set<Node>>> getPostProcessors() {
return postProcessors;
}
private final ChangeListener listener = (o, oldValue, newValue) -> modifiedChildren.add((Node) ((ReadOnlyProperty) o).getBean());
private void initListener() {
getChildren().addListener((ListChangeListener.Change<? extends Node> c) -> {
while (c.next()) {
if (c.wasRemoved()) {
for (Node n : c.getRemoved()) {
n.boundsInParentProperty().removeListener(listener);
}
}
if (c.wasAdded()) {
for (Node n : c.getAddedSubList()) {
n.boundsInParentProperty().addListener(listener);
}
}
}
});
}
public PostProcessPane() {
initListener();
}
public PostProcessPane(Node... children) {
super(children);
initListener();
for (Node n : children) {
n.boundsInParentProperty().addListener(listener);
}
}
@Override
protected void layoutChildren() {
super.layoutChildren();
if (!modifiedChildren.isEmpty()) {
for (Consumer<Set<Node>> processor : postProcessors) {
processor.accept(modifiedChildrenUnmodifiable);
}
modifiedChildren.clear();
}
}
}