[英]How do I keep JavaFx nodes in their original positions when resizing a split pane?
I currently have a splitPane with 3 AnchorPanes, the center pane (Graph) of which contains some Circles contained in StackPanes that I add to the center AnchorPane in my code.我目前有一个带有 3 个 AnchorPane 的 splitPane,其中的中心窗格(图表)包含 StackPanes 中包含的一些 Circles,我在代码中添加到中心 AnchorPane。 When I resize the left divider, the contents of the center graph AnchorPane move with the left divider.
当我调整左分隔线的大小时,中心图 AnchorPane 的内容会随着左分隔线移动。
Is there a way I can keep the nodes in the AnchorPane (or by using some other pane) from moving with the divider?有没有办法让 AnchorPane 中的节点(或使用其他窗格)不随分隔线移动? Even better would be if I could have the "Graph" text move and the circle nodes remain stationary, but that's not necessary.
如果我可以让“图形”文本移动并且圆形节点保持静止,那就更好了,但这不是必需的。 I'm new to JavaFx and still not sure how each pane works exactly.
我是 JavaFx 的新手,但仍然不确定每个窗格的工作原理。
Here are two screenshots showing the process of resizing that I'm describing.这是两个屏幕截图,显示了我正在描述的调整大小的过程。 Thanks in advance for any help!
提前感谢您的帮助!
EDIT: Anko's solution below worked wonderfully for me.编辑:下面的 Anko 解决方案对我来说非常有用。 Thank you to everyone for helping out:)
谢谢大家帮忙:)
Shot 1第 1 枪
Shot 2射击 2
Add a ChangeListener
to the first Divider
, calculate and set LayoutX
of the objects in the middle pane like in this small example:将
ChangeListener
添加到第一个Divider
,计算并设置中间窗格中对象的LayoutX
,如下面的小示例所示:
Controller Class: Controller Class:
package sample;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.SplitPane;
import javafx.scene.shape.Ellipse;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable {
@FXML
private SplitPane splitPane;
@FXML
private Ellipse ellipse;
@Override
public void initialize(URL location, ResourceBundle resources) {
splitPane.getDividers().get(0).positionProperty().addListener(((observable, oldValue, newValue) -> {
ellipse.setLayoutX(ellipse.getLayoutX() + (splitPane.getWidth() * oldValue.doubleValue() - splitPane.getWidth() * newValue.doubleValue()));
}));
}
}
FXML File: FXML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Ellipse?>
<SplitPane fx:id="splitPane" dividerPositions="0.4, 0.9" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<items>
<AnchorPane />
<AnchorPane>
<children>
<Ellipse fx:id="ellipse" fill="DODGERBLUE" layoutX="150.0" layoutY="150.0" radiusX="100.0" radiusY="80.0" stroke="BLACK" strokeType="INSIDE" />
</children>
</AnchorPane>
<AnchorPane />
</items>
</SplitPane>
Preview:预习:
If you want the nodes in the graph not to move when the dividers are moved, I think the most logical approach is to make them not a part of the SplitPane
.如果您希望图表中的节点在移动分隔线时不移动,我认为最合乎逻辑的方法是让它们不属于
SplitPane
。 Use a StackPane
, with the actual graph at the lowest z-order and the SplitPane
at a higher z-order;使用
StackPane
,实际图形位于最低 z 顺序, SplitPane
位于较高 z 顺序; style the panes contained in the SplitPane
so the center pane is transparent and the left and right panes opaque, and make the SplitPane
itself have a transparent background.设置
SplitPane
中包含的窗格的样式,使中央窗格透明,左右窗格不透明,并使SplitPane
本身具有透明背景。
This approach relies on standard layout mechanisms, and avoids the need to use listeners to modify the layout after the system updates it.这种方式依赖于标准的布局机制,避免了系统更新后需要使用监听器来修改布局。
Here's a mock-up of this approach:这是这种方法的模型:
import java.io.IOException;
import java.util.stream.Stream;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
/**
* JavaFX App
*/
public class App extends Application {
@Override
public void start(Stage stage) throws IOException {
BorderPane root = new BorderPane();
// menu bar in top, status in bottom...
StackPane graphStack = new StackPane();
Pane graphPane = new Pane();
populateGraphPane(graphPane);
VBox controls = new VBox(5,
new Label("Controls"),
new Button("A Button"),
new TextField()
);
AnchorPane graphOverlay = new AnchorPane();
Label graphLabel = new Label("Graph");
AnchorPane.setTopAnchor(graphLabel, 5.0);
AnchorPane.setLeftAnchor(graphLabel, 5.0);
graphOverlay.getChildren().add(graphLabel);
VBox details = new VBox(5, new Label("Details"));
SplitPane split = new SplitPane(controls, graphOverlay, details);
graphStack.getChildren().addAll(graphPane, split);
split.setDividerPositions(0.33, 0.67);
// Styles: IRL do this in an external CSS style sheet
// Make the background white, but make the overlay transparent so we see the graph below it:
graphPane.setStyle("-fx-background-color: white ;");
controls.setStyle("-fx-background-color: white ; -fx-color: red ; -fx-focus-color: #FF7F50 ; -fx-faint-focus-color: #FF7F5022 ; -fx-padding: 5 ; ");
details.setStyle("-fx-background-color: white ; -fx-padding: 5 ;");
graphOverlay.setStyle("-fx-background-color: transparent ;");
split.setStyle("-fx-background-color: transparent ;");
root.setStyle("-fx-text-background-color: red ;");
root.setCenter(graphStack);
Scene scene = new Scene(root, 800, 600);
stage.setScene(scene);
stage.show();
}
private void populateGraphPane(Pane graph) {
Circle top = new Circle(400, 200, 20, Color.WHITE);
Circle left = new Circle(300, 373, 20, Color.WHITE);
Circle right = new Circle(500, 373, 20, Color.WHITE);
Line leftLine = new Line(390, 217, 310, 356);
Line rightLine = new Line(410, 217, 490, 356);
Line bottomLine = new Line(320, 373, 480, 373);
Stream.of(top, left, right).forEach(c -> {
c.setStroke(Color.RED);
c.setStrokeWidth(3);
});
Stream.of(leftLine, rightLine, bottomLine).forEach(l -> {
l.setStroke(Color.RED);
l.setStrokeWidth(3);
});
Group group = new Group();
group.getChildren().addAll(top, left, right, leftLine, rightLine, bottomLine);
graph.getChildren().add(group);
}
public static void main(String[] args) {
launch();
}
}
and some screenshots:和一些截图:
If you want to avoid obscuring parts of the graph, it's relatively easy to do so by setting min/max widths on the panes in the graph (which will restrict the movement of the dividers).如果您想避免遮挡图表的某些部分,可以通过在图表中的窗格上设置最小/最大宽度来相对容易地做到这一点(这将限制分隔线的移动)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.