Ich möchte eine Gruppe von Knoten innerhalb einer VBox zentrieren und die Gruppe skalieren, wenn es die Grenzen der übergeordneten VBox überschreitet.JavaFX: Gruppe ist nicht zentriert in VBox
Ich habe folgendes Setup versucht: Ein ScrollPane enthält eine VBox, die eine Gruppe von Knoten (z. B. Kreise, Linien usw.) zentrieren soll.
Die Knoten werden dynamisch hinzugefügt: myCustomPane.getContentPane().getChildren().addAll(ellipse, line)
Leider weder die (rot) Gruppe zentriert ist auf dem Fenster noch sichtbar. Allerdings sehe ich die (orange) ScalablePane, die (blaue) VBox und alle Knoten.
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();
}
}
Verbrauch:
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);
}
}
Update: Drag-Unterstützung hinzugefügt
Ich habe versucht, per Drag-Unterstützung für meine Knoten hinzuzufügen, so kann ich überprüfen, wenn die Innenscheibe neu zu skalieren ist. Ich habe auch die Gruppe in ein einfaches Fenster geändert, damit ich die Grenzen des inneren Fensters sichtbar machen kann. Leider fängt der innere Bereich (rot) nicht an den Kindknoten an. Wie kann ich den Inhaltsbereich erzwingen, die Größe seiner untergeordneten Elemente zu übernehmen und die Größe neu festzulegen, wenn die Größe die übergeordneten Grenzen überschreitet?
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;
}
}
Verbrauch:
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;
});
}
für mehr Informationen suchen kann ich Ihre Klasse zu kompilieren. Es hat Fehler. – Sedrick
'contentScaleTransform = new Scale (1, 1);' zeigt einen Fehler an: Wo wird es deklariert? – Sedrick
Entschuldigung, ich habe gerade einen Auszug der Klasse gepostet, da die ganze Skalierungsfunktionalität für das Problem nicht so wichtig ist. Ich habe vergessen, die Linie zu entfernen, wo die Skala definiert ist. – Tunguska