我目前有一个带有3个AnchorPanes的splitPane,其中央窗格(图形)包含StackPanes中包含的一些Circle,这些圆已在我的代码中添加到中央AnchorPane中。当我调整左分隔线的大小时,中心图AnchorPane的内容随左分隔线移动。
有没有一种方法可以使AnchorPane中的节点(或通过使用其他窗格)不随分隔器一起移动?更好的是,如果我可以移动“图形”(Graph)文本并且使圆形节点保持静止,但这不是必需的。我是JavaFx的新手,仍然不确定每个窗格的工作原理。
这里有两个屏幕快照,显示了我正在描述的调整大小的过程。预先感谢您的帮助!
编辑:Anko的以下解决方案对我来说效果很好。谢谢大家的帮助:)
拍摄1
拍摄2
如果您希望图形中的节点在分隔线移动时不移动,我认为最合乎逻辑的方法是使它们不成为SplitPane
的一部分。使用StackPane
,实际图形的Z阶最低,而SplitPane
的Z阶更高。对SplitPane
中包含的窗格进行样式设置,以使中心窗格透明,而左右窗格不透明,并使SplitPane
本身具有透明背景。
此方法依赖于标准布局机制,并且避免了在系统更新布局后使用侦听器修改布局的需求。
这里是这种方法的模型:
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();
}
}
和一些屏幕截图:
如果要避免遮挡图形的某些部分,通过在图形的窗格中设置最小/最大宽度(这会限制分隔线的移动),这样做相对容易。
在第一个ChangeListener
中添加Divider
,计算并设置中间窗格中对象的LayoutX
,就像这个小示例一样:
控制器类:
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文件:
<?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>
预览: