我希望将一组节点置于VBox中心,如果超过父VBox的范围,则缩放该组。
我尝试了以下设置:ScrollPane包含一个VBox,它应该以一组节点为中心(例如Circles,Lines等)。
动态添加节点:myCustomPane.getContentPane().getChildren().addAll(ellipse, line)
不幸的是,(红色)组在窗口上既不居中也不可见。但是我确实看到了(橙色)ScalablePane,(蓝色)VBox和所有节点。
public class ScalablePane extends ScrollPane {
private Property<Group> contentPaneProperty = new SimpleObjectProperty<>();
public ScalablePane() {
setContentPane(new Group());
setPannable(true);
setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
setFitToHeight(true); // center
setFitToWidth(true); // center
setStyle("-fx-background-color: orange;");
}
public final void setContentPane(Group contentPane) {
contentPane.setManaged(false);
contentPane.setStyle("-fx-background-color: red;");
VBox vBox = new VBox();
vBox.setAlignment(Pos.CENTER);
vBox.setManaged(true);
vBox.getChildren().add(contentPane);
vBox.setStyle("-fx-background-color: blue;");
setContent(vBox);
contentPaneProperty.setValue(contentPane);
}
public Group getContentPane() {
return contentPaneProperty.getValue();
}
}
用法:
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
ScalablePane pane = new ScalablePane();
Circle circle = new Circle(200, 40, 20);
Circle circle2 = new Circle(100, 150, 20);
pane.getContentPane().getChildren().addAll(circle, circle2);
Scene scene = new Scene(pane, 400, 400);
primaryStage.setScene(scene);
primaryStage.sizeToScene();
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
更新:添加了拖动支持
我尝试为节点添加拖动支持,因此我可以检查内部窗格何时重新缩放。我还将Group更改为一个简单的Pane,这样我就可以看到内部窗格的边界。不幸的是,内部窗格(红色)不会捕捉到子节点。如何强制内容窗格,以获取其子项的大小,并在其大小超过父级边界时重新调整大小?
public class ScalablePane extends ScrollPane {
private final Pane contentPane;
private final Scale contentScaleTransform;
public ScalablePane() {
contentPane = new Pane();
contentScaleTransform = new Scale(1, 1);
initializeScrollPane();
initializeContentPane();
}
public void initializeScrollPane() {
setPannable(true);
setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
setFitToHeight(true); // center
setFitToWidth(true); // center
setStyle("-fx-background-color: orange;");
}
private final void initializeContentPane() {
contentPane.setStyle("-fx-background-color: red;");
VBox vBox = new VBox();
VBox.setMargin(contentPane, new Insets(10));
vBox.setAlignment(Pos.CENTER);
vBox.setManaged(true);
vBox.getChildren().add(contentPane);
vBox.setStyle("-fx-background-color: blue;");
setContent(vBox);
contentPane.layoutBoundsProperty()
.addListener(new ChangeListener<Bounds>() {
@Override
public void changed(ObservableValue<? extends Bounds> observable,
Bounds oldValue, Bounds newValue) {
double parentWidth = getContentPane().getParent().getLayoutBounds()
.getWidth() - 10;
double parentHeight = getContentPane().getParent().getLayoutBounds()
.getHeight() - 10;
if (parentHeight > 0 && parentWidth > 0) {
if (newValue.getHeight() > parentHeight
|| newValue.getWidth() > parentWidth) {
computeScale();
}
}
}
});
}
public void computeScale() {
double realWidth = getContentPane().prefWidth(getWidth());
double realHeight = getContentPane().prefHeight(getHeight());
double leftAndRight = getInsets().getLeft() + getInsets().getRight();
double topAndBottom = getInsets().getTop() + getInsets().getBottom();
double contentWidth = getWidth() - leftAndRight;
double contentHeight = getHeight() - topAndBottom;
double scaleX = contentWidth / realWidth;
double scaleY = contentHeight / realHeight;
double scale = Math.min(scaleX, scaleY);
getContentScaleTransform().setX(scale);
getContentScaleTransform().setY(scale);
getContentPane().resize(contentWidth / getContentScaleTransform().getX(),
contentHeight / getContentScaleTransform().getY());
}
public Pane getContentPane() {
return contentPane;
}
public final Scale getContentScaleTransform() {
return contentScaleTransform;
}
}
用法:
public class Main extends Application {
private double dragOriginalSceneX;
private double dragOriginalSceneY;
@Override
public void start(Stage primaryStage) {
try {
ScalablePane pane = new ScalablePane();
Circle circle = new Circle(200, 40, 20);
Circle circle2 = new Circle(100, 150, 20);
addDragSupport(circle, pane);
addDragSupport(circle2, pane);
pane.getContentPane().getChildren().addAll(circle, circle2);
Scene scene = new Scene(pane, 400, 400);
primaryStage.setScene(scene);
primaryStage.sizeToScene();
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
private void addDragSupport(Circle node, ScalablePane graphPane) {
node.setOnMousePressed(e -> {
dragOriginalSceneX = e.getSceneX()
/ graphPane.getContentScaleTransform().getX();
dragOriginalSceneY = e.getSceneY()
/ graphPane.getContentScaleTransform().getY();
});
node.setOnMouseDragged(e -> {
Circle circle = (Circle) e.getSource();
circle.setManaged(true);
double eventX = e.getSceneX()
/ graphPane.getContentScaleTransform().getX();
double eventY = e.getSceneY()
/ graphPane.getContentScaleTransform().getY();
double offsetX = eventX - dragOriginalSceneX;
double offsetY = eventY - dragOriginalSceneY;
double newX = circle.getCenterX() + offsetX;
double newY = circle.getCenterY() + offsetY;
circle.setCenterX(newX);
circle.setCenterY(newY);
// remember last coordinates
dragOriginalSceneX = eventX;
dragOriginalSceneY = eventY;
});
}
答案 0 :(得分:0)
我认为我按照您想要的方式工作,除了缩放尝试让我知道它是否有效也是你不能将css添加到一个组中这是一个小组可以做的事情的例子,如果你正在寻找更多 信息https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html#group
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
public class ScalablePane extends ScrollPane {
// private Property<Group> contentPaneProperty = new SimpleObjectProperty<>();
private Group contentPane = new Group();
public ScalablePane() {
setContentPane(/*new Group()*/);
setPannable(true);
setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
setFitToHeight(true); // center
setFitToWidth(true); // center
setStyle("-fx-background-color: orange;");
}
public final void setContentPane(/*Group contentPane*/) {
// contentPane.setManaged(false);
contentPane.setStyle("-fx-background-color: red;");
VBox vBox = new VBox();
vBox.setAlignment(Pos.CENTER);
vBox.setManaged(true);
vBox.getChildren().add(contentPane);
vBox.setStyle("-fx-background-color: blue;");
setContent(vBox);
// contentPaneProperty.setValue(contentPane);
}
public Group getContentPane() {
return contentPane;
}
}