2017-11-30 8 views
0

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; 
    }); 
    } 
+0

für mehr Informationen suchen kann ich Ihre Klasse zu kompilieren. Es hat Fehler. – Sedrick

+0

'contentScaleTransform = new Scale (1, 1);' zeigt einen Fehler an: Wo wird es deklariert? – Sedrick

+0

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

Antwort

0

Ich glaube, ich habe diese Arbeit so, wie Sie außer Skalierung wollen versuchen Sie es mal lassen Sie mich wissen, ob es funktioniert auch nicht hier CSS zu einer Gruppe hinzufügen kann, ist ein Beispiel eine Gruppe von Dingen tun können, wenn Sie 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; 
    } 
} 
+0

Vielen Dank! Ich wusste nicht, dass ich keine Stile auf eine Gruppe anwenden kann. Also habe ich angenommen, dass die Box nicht da ist. – Tunguska

+0

Ich habe mein Beispiel mit Drag-Unterstützung und einer Skalierungsfunktion erweitert. Aber es gibt noch zwei Probleme: Der Inhaltsbereich nimmt nicht die Größe seiner untergeordneten Elemente an, und die untergeordneten Knoten verlassen die Grenzen des Inhaltsbereichs, wenn ich sie umherbewege. – Tunguska