Javafx 设置SplitPane的分隔符位置

Javafx 设置SplitPane的分隔符位置,javafx,javafx-8,Javafx,Javafx 8,我想将拆分窗格的分隔符设置为某个默认位置。这不起作用,分隔器停留在中间: public void start(Stage primaryStage) throws Exception{ SplitPane splitPane = new SplitPane(new Pane(), new Pane()); // Report changes to the divider position splitPane.getDividers().get(0).positionP

我想将拆分窗格的分隔符设置为某个默认位置。这不起作用,分隔器停留在中间:

public void start(Stage primaryStage) throws Exception{

    SplitPane splitPane = new SplitPane(new Pane(), new Pane());

    // Report changes to the divider position
    splitPane.getDividers().get(0).positionProperty().addListener(
            o -> System.out.println(splitPane.getDividerPositions()[0])
    );

    // Doesn't work:
    splitPane.setDividerPositions(0.8);

    // The docs seem to recommend the following (with floats instead of
    // doubles, and with one number more than there are dividers, which is
    // weird), but it doesn't work either:
    //splitPane.setDividerPositions(0.8f, 0.2f);

    primaryStage.setScene(new Scene(splitPane));
    primaryStage.setMaximized(true);
    primaryStage.show();
}
输出:

0.8
0.5

它表明有什么东西将它重置到中间

我怎样才能做到这一点呢?

试试看

splitPane.setDividerPosition(0, percentage);

参数设置为dividerposition(int dividerIndex,双百分比)

问题似乎是在
阶段最大化期间设置
拆分窗格
宽度时,会重置分隔器位置。随后通过收听窗口的showing属性设置分隔符位置,如下所示:

primaryStage.showingProperty().addListener(新的ChangeListener()){
@凌驾

阶段
初始化过程中,公共空隙发生了变化(可观察值),窗口大小多次变化,直到布局完成。每次变化都会修改分隔器位置。如果要控制分隔器位置,则必须在
阶段
完全初始化后进行设置:

private boolean m_stageShowing = false;

@Override
public void start(Stage primaryStage) throws Exception {
    SplitPane splitPane = new SplitPane(new Pane(), new Pane());

    ChangeListener<Number> changeListener = new ChangeListener<Number>() {
        @Override
        public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
            splitPane.setDividerPositions(0.8);
            if (m_stageShowing) {
                observable.removeListener(this);
            }
        }
    };
    splitPane.widthProperty().addListener(changeListener);
    splitPane.heightProperty().addListener(changeListener);

    primaryStage.setScene(new Scene(splitPane));
    primaryStage.setMaximized(true);
    primaryStage.show();
    m_stageShowing = true;
}
private boolean m_stageshow=false;
@凌驾
public void start(Stage primaryStage)引发异常{
SplitPane SplitPane=new SplitPane(new Pane(),new Pane());
ChangeListener ChangeListener=新的ChangeListener(){
@凌驾

public void changed(observevalue我有同样的问题,上面的解决方案对我来说不可靠。 因此,我为SplitPane创建了一个自定义外观:

public class DumbSplitPaneSkin extends SplitPaneSkin {

  public DumbSplitPaneSkin(SplitPane splitPane) {
    super(splitPane);
  }

  @Override
  protected void layoutChildren(double x, double y, double w, double h) {
    double[] dividerPositions = getSkinnable().getDividerPositions();
    super.layoutChildren(x, y, w, h);
    getSkinnable().setDividerPositions(dividerPositions);
  }
}

此外观可以通过css或重写SplitPane.createDefaultSkin()使用。您也可以通过编程将其设置为SplitPane.setSkin(新DumbSplitPaneSkin(SplitPane));

您只需使用

Platform.runLater(new Runnable() { @Override public void run() { splitPane.setDividerPositions(0.8); } }); Platform.runLater(新的Runnable(){ @凌驾 公开募捐{ splitPane.setDividerPositions(0.8); } }); 这不是100%可靠的解决方案,因为
run()
方法在JFX线程中未指定的时间执行,但对于简单的初始化情况,它可以正常工作。

以下是我的结果:

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.*;

/**
 * SplitPane, Dialogbox example
 * @author Pataki István
 */
public class SimpleDocking extends Application {

  private double splitPosition = 0;
  private SplitPane rootPane = new SplitPane();
  private MyDialog dialog;
  private BorderPane dockedArea;

  @Override
  public void start(final Stage stage) throws Exception {
    rootPane.setOrientation(Orientation.VERTICAL);
    rootPane.setBorder(new Border(new BorderStroke(
                                    Color.GREEN,
                                    BorderStrokeStyle.SOLID,
                                    new CornerRadii(5),
                                    new BorderWidths(3))
    ));

    dockedArea = new BorderPane(new TextArea("Some docked content"));
    final FlowPane centerArea = new FlowPane();
    final Button undockButton = new Button("Undock");
    centerArea.getChildren().add(undockButton);
    rootPane.getItems().addAll(centerArea, dockedArea);
    stage.setScene(new Scene(rootPane, 300, 300));
    stage.show();

    dialog = new MyDialog(stage);
    undockButton.disableProperty().bind(dialog.showingProperty());
    undockButton.setOnAction(new EventHandler<ActionEvent>() {
      @Override
      public void handle(ActionEvent actionEvent) {
        handler(stage);
      }
    });
  }

  private void handler(Stage stage) {
    splitPosition = rootPane.getDividerPositions()[0];
    rootPane.getItems().remove(dockedArea);
    dialog.setOnHidden(windowEvent -> {
      rootPane.getItems().add(dockedArea);
      rootPane.setDividerPositions(splitPosition);
    });
    dialog.setContent(dockedArea);
    dialog.show(stage);
  }

  private class MyDialog extends Popup {
    private BorderPane root;

    private MyDialog(Window parent) {
      root = new BorderPane();
      root.setPrefSize(200, 200);
      root.setStyle("-fx-border-width: 1; -fx-border-color: gray");
      root.setTop(buildTitleBar());
      setX(parent.getX() + 50);
      setY(parent.getY() + 50);
      getContent().add(root);
    }

    public void setContent(Node content) {
      root.setCenter(content);
    }

    private Node buildTitleBar() {
      BorderPane pane = new BorderPane();
      pane.setStyle("-fx-background-color: burlywood; -fx-padding: 5");
      final Delta dragDelta = new Delta();

      pane.setOnMousePressed(mouseEvent -> {
        dragDelta.x = getX() - mouseEvent.getScreenX();
        dragDelta.y = getY() - mouseEvent.getScreenY();
      });

      pane.setOnMouseDragged(mouseEvent -> {
        setX(mouseEvent.getScreenX() + dragDelta.x);
        setY(mouseEvent.getScreenY() + dragDelta.y);
      });

      Label title = new Label("My Dialog");
      title.setStyle("-fx-text-fill: midnightblue;");
      pane.setLeft(title);

      Button closeButton = new Button("X");
      closeButton.setOnAction(actionEvent -> hide());
      pane.setRight(closeButton);
      return pane;
    }
  }

  private static class Delta {
    double x, y;
  }

  public static void main(String[] args) throws Exception {
    launch();
  }
}
导入javafx.application.application;
导入javafx.event.ActionEvent;
导入javafx.event.EventHandler;
导入javafx.geometry.Orientation;
导入javafx.scene.*;
导入javafx.scene.control.*;
导入javafx.scene.layout.*;
导入javafx.scene.paint.Color;
导入javafx.stage.*;
/**
*拆分窗格,对话框示例
*@作者Pataki István
*/
公共类SimpleDock扩展了应用程序{
私有双拆分位置=0;
private SplitPane rootPane=new SplitPane();
私人对话;
私人边境区;
@凌驾
public void start(final Stage)引发异常{
根窗格。设置方向(方向。垂直);
根窗格.setOrder(新边框)(新边框笔划(
颜色,绿色,
BorderStrokeStyle.SOLID,
新的转弯半径(5),
新边框宽度(3))
));
dockedArea=新边框窗格(新文本区域(“某些停靠内容”);
最终流程窗格中心区域=新流程窗格();
最终按钮解锁按钮=新按钮(“解锁”);
centerArea.getChildren().add(撤消按钮);
rootPane.getItems().addAll(centerArea,dockedArea);
舞台场景(新场景(根窗格,300300));
stage.show();
dialog=新建MyDialog(阶段);
undockButton.disableProperty().bind(dialog.showingProperty());
撤销Button.setOnAction(新的EventHandler(){
@凌驾
公共无效句柄(ActionEvent ActionEvent){
处理者(阶段);
}
});
}
专用void处理程序(阶段){
splitPosition=rootPane.getDividerPositions()[0];
rootPane.getItems().remove(dockedArea);
对话框.setOnHidden(windowEvent->{
rootPane.getItems().add(dockedArea);
rootPane.setDividerPositions(splitPosition);
});
dialog.setContent(dockdarea);
对话.表演(舞台);
}
私有类MyDialog扩展弹出窗口{
私有边界根;
私有MyDialog(窗口父级){
root=新边框窗格();
root.setPrefSize(200200);
root.setStyle(“-fx边框宽度:1;-fx边框颜色:灰色”);
setTop(buildTitleBar());
setX(parent.getX()+50);
setY(parent.getY()+50);
getContent().add(根目录);
}
公共内容(节点内容){
root.setCenter(内容);
}
私有节点buildTitleBar(){
BorderPane=新的BorderPane();
窗格设置样式(“-fx背景色:burlywood;-fx填充:5”);
最终增量dragDelta=新增量();
pane.setOnMousePressed(鼠标事件->{
dragDelta.x=getX()-mouseEvent.getScreenX();
dragDelta.y=getY()-mouseEvent.getScreenY();
});
pane.setonMouseDrawed(mouseEvent->{
setX(mouseEvent.getScreenX()+dragDelta.x);
setY(mouseEvent.getScreenY()+dragDelta.y);
});
标签标题=新标签(“我的对话框”);
title.setStyle(“-fx文本填充:午夜蓝;”);
窗格。设置左(标题);
按钮关闭按钮=新按钮(“X”);
setOnAction(actionEvent->hide());
窗格。设置右键(关闭按钮);
返回窗格;
}
}
私有静态类增量{
双x,y;
}
公共静态void main(字符串[]args)引发异常{
发射();
}
}

这是您希望的工作方式。

因为您通常在splitpane中至少有一些内容,例如vbox,只需设置最小和最大宽度,它就会自动设置分隔器。

正如其他人指出的,问题是当舞台最大化时,分隔器位置会重置

您可以通过将
resizeableWithParent
设置为
false
来防止这种情况

示例

假设您有一个
SplitPane
,其中包含两个嵌套容器。以下是fxml摘录:

<SplitPane fx:id="splitPane" dividerPositions="0.25">
        <VBox fx:id="leftSplitPaneContainer" />
        <FlowPane fx:id="rightSplitPaneContainer"/>
</SplitPane>
然后,您只需在两个容器上调用
SplitPane.setResizeableWithParent()
,即可防止重置t
@FXML
private SplitPane splitPane;
@FXML
private VBox leftSplitPaneContainer;
@FXML
private FlowPane rightSplitPaneContainer;
public void initialize(){
        SplitPane.setResizableWithParent(leftSplitPaneContainer, false);
        SplitPane.setResizableWithParent(rightSplitPaneContainer, false);
    }