You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX中实现VBox展开与收起滑动效果的问题

JavaFX SplitPane左侧面板收起/展开问题解决

问题原因

SplitPane的布局逻辑由内部分隔器(Divider)的位置主导,而非单纯依赖子节点的maxWidth属性。你之前的实现中,收起时setMaxWidth(0)能生效是因为强制限制了面板宽度,但展开时仅恢复maxWidth不会触发SplitPane重新调整分隔器位置,导致面板无法显示。此外,手动调用adjustCenterPane设置contentPane宽度会干扰SplitPane的自动布局逻辑。

解决方案

1. 关键修改点

  • 记录左侧面板的原始宽度和分隔器初始位置,用于展开时恢复
  • 操作SplitPane的分隔器来控制面板的显示/隐藏,而非仅依赖节点尺寸属性
  • 移除手动调整contentPane宽度的逻辑,让SplitPane自动分配空间

2. 修改后的代码

FXML(添加SplitPane的fx:id)

<SplitPane fx:id="splitPane">
    <items>
        <VBox fx:id="leftPane" styleClass="resizable-vbox" onMousePressed="#handleMousePressed">
            <children>
                <Label text="Domain 1" />
            </children>
        </VBox>
        <AnchorPane>
            <VBox fx:id="contentPane" styleClass="resizable-vbox_content">
                <children>
                    <Label text="Domain 2" />
                </children>
            </VBox>
        </AnchorPane>
        <VBox fx:id="rightPane" styleClass="resizable-vbox">
            <children>
                <Label text="Domain 3" />
            </children>
        </VBox>
    </items>
</SplitPane>

控制器代码

import javafx.animation.FadeTransition;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.SplitPane;
import javafx.scene.layout.VBox;
import javafx.util.Duration;

public class SplitPaneController {
    @FXML
    private VBox leftPane;
    @FXML
    private SplitPane splitPane;
    private boolean leftPaneVisible = true;
    private double originalLeftWidth;
    private double originalDividerPosition;

    @FXML
    public void initialize() {
        // 初始化时记录左侧面板原始宽度和分隔器位置
        originalLeftWidth = leftPane.getPrefWidth();
        if (!splitPane.getDividers().isEmpty()) {
            originalDividerPosition = splitPane.getDividers().get(0).getPosition();
        }
    }

    @FXML
    private void handleMousePressed(MouseEvent event) {
        if (leftPaneVisible) {
            fadeOutVBox();
        } else {
            fadeInVBox();
        }
        leftPaneVisible = !leftPaneVisible;
    }

    private void fadeInVBox() {
        // 先恢复左侧面板的最大宽度,确保SplitPane能分配空间
        leftPane.setMaxWidth(200);
        // 恢复分隔器到初始位置,让左侧面板展开
        if (!splitPane.getDividers().isEmpty()) {
            splitPane.getDividers().get(0).setPosition(originalDividerPosition);
        } else {
            leftPane.setPrefWidth(originalLeftWidth);
        }
        // 执行淡入动画
        FadeTransition ft = new FadeTransition(Duration.seconds(0.3));
        ft.setNode(leftPane);
        ft.setFromValue(0);
        ft.setToValue(1);
        ft.setOnFinished(event -> leftPaneVisible = true);
        ft.play();
    }

    private void fadeOutVBox() {
        FadeTransition ft = new FadeTransition(Duration.seconds(0.3));
        ft.setNode(leftPane);
        ft.setFromValue(1);
        ft.setToValue(0);
        ft.setOnFinished(event -> {
            leftPane.setMaxWidth(0);
            // 将分隔器移到最左侧,确保面板完全收起
            if (!splitPane.getDividers().isEmpty()) {
                splitPane.getDividers().get(0).setPosition(0);
            }
            leftPaneVisible = false;
        });
        ft.play();
    }
}

CSS(保持原样式不变)

.resizable-vbox {
    -fx-background-color: lightgreen;
    -fx-padding: 10px;
    -fx-pref-width: 120px;
    -fx-min-width: 10px;
    -fx-max-width: 200px;
}

.right-pane {
    -fx-background-color: lightgray;
    -fx-padding: 10px;
    -fx-pref-width: 200px;
    -fx-min-width: 100px;
    -fx-max-width: 400px;
}
.resizable-vbox_content {
    -fx-background-color: lightgray;
    -fx-padding: 10px;
    -fx-pref-width: 200px;
    -fx-min-width: 100px;
    -fx-max-width: 400px;
}

说明

  • 展开操作时,先恢复maxWidth再调整分隔器位置,确保SplitPane为左侧面板分配空间,淡入动画才能正常显示
  • 收起操作时,动画结束后设置maxWidth(0)并移动分隔器到最左,彻底隐藏左侧面板
  • 移除adjustCenterPane方法,SplitPane会自动根据分隔器位置分配三个面板的宽度,避免手动布局冲突

内容的提问来源于stack exchange,提问作者Andres Sanchez Muñoz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 19:29:55