Как сохранить узлы JavaFx в исходных положениях при изменении размера разделенной панели? - PullRequest
0 голосов
/ 26 мая 2020

В настоящее время у меня есть splitPane с 3 AnchorPanes, центральная панель (Graph) которой содержит некоторые круги, содержащиеся в StackPanes, которые я добавляю в центральную AnchorPane в моем коде. Когда я изменяю размер левого разделителя, содержимое центрального графа AnchorPane перемещается вместе с левым разделителем.

Есть ли способ предотвратить перемещение узлов в AnchorPane (или с помощью какой-либо другой панели) вместе с разделителем? Еще лучше было бы, если бы я мог перемещать текст «График», а узлы круга оставались бы неподвижными, но в этом нет необходимости. Я новичок в JavaFx и до сих пор не уверен, как именно работает каждая панель.

Вот два снимка экрана, показывающие процесс изменения размера, который я описываю. Заранее благодарим за любую помощь!

EDIT: решение Anko, приведенное ниже, отлично сработало для меня. Спасибо всем за помощь :)

Выстрел 1

enter image description here

Выстрел 2

enter image description here

Ответы [ 2 ]

0 голосов
/ 26 мая 2020

Если вы хотите, чтобы узлы в графе не перемещались при перемещении разделителей, я думаю, что наиболее логичный подход - сделать их не частью 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();
    }

}

и несколько снимков экрана:

enter image description here

enter image description here

enter image description here

Если вы хотите избежать скрывая части графика, это относительно легко сделать, установив минимальную / максимальную ширину панелей на графике (что ограничит перемещение разделителей).

0 голосов
/ 26 мая 2020

Добавьте 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()));
        }));
    }
}

F XML Файл:

<?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 when loaded preview when first divider moved to the left

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...