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

基于JavaFX实现Windows 10风格悬停展开侧边导航栏

实现Windows 10风格悬停展开侧边菜单(JavaFX)

核心思路

  • 用布尔属性统一管理菜单悬停状态,让VBox宽度与按钮文字显示同步绑定到该状态
  • 借助JavaFX属性绑定机制,避免手动处理UI同步问题
  • 通过StackPane布局实现侧边菜单展开时覆盖内容区域的效果

实现步骤及代码示例

1. FXML布局(SceneBuilder创建)

以StackPane为根容器,左侧放置菜单VBox,下方放置主内容区域。每个菜单项用HBox包裹图标与文字:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.image.ImageView?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.Region?>

<StackPane xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.MenuController">
    <!-- 主内容区域,会被菜单覆盖 -->
    <Label text="主内容区域" style="-fx-font-size: 24px;"/>
    
    <!-- 侧边菜单VBox -->
    <VBox fx:id="menuBox" style="-fx-background-color: #2c3e50; -fx-padding: 10px;" 
          prefWidth="60" minWidth="60" maxWidth="200">
        <padding>
            <Insets top="20" left="5" right="5" bottom="20"/>
        </padding>
        <spacing>15</spacing>
        
        <!-- 菜单项1 -->
        <HBox spacing="10" alignment="CENTER_LEFT">
            <ImageView fitWidth="40" fitHeight="40" url="/icons/home.png"/>
            <Label fx:id="homeLabel" text="主页" style="-fx-text-fill: white; -fx-font-size: 14px;"/>
        </HBox>
        
        <!-- 菜单项2 -->
        <HBox spacing="10" alignment="CENTER_LEFT">
            <ImageView fitWidth="40" fitHeight="40" url="/icons/settings.png"/>
            <Label fx:id="settingsLabel" text="设置" style="-fx-text-fill: white; -fx-font-size: 14px;"/>
        </HBox>
        
        <!-- 菜单项3 -->
        <HBox spacing="10" alignment="CENTER_LEFT">
            <ImageView fitWidth="40" fitHeight="40" url="/icons/help.png"/>
            <Label fx:id="helpLabel" text="帮助" style="-fx-text-fill: white; -fx-font-size: 14px;"/>
        </HBox>
        
        <!-- 占位元素,让菜单项顶部对齐 -->
        <Region VBox.vgrow="ALWAYS"/>
    </VBox>
</StackPane>

2. Controller逻辑

在Controller中定义悬停状态属性,绑定VBox宽度与标签可见性,处理鼠标事件:

package com.example;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;

public class MenuController {
    @FXML
    private VBox menuBox;
    @FXML
    private Label homeLabel;
    @FXML
    private Label settingsLabel;
    @FXML
    private Label helpLabel;

    // 菜单悬停状态属性
    private final BooleanProperty isMenuHovered = new SimpleBooleanProperty(false);

    public void initialize() {
        // 绑定标签可见性到悬停状态
        homeLabel.visibleProperty().bind(isMenuHovered);
        settingsLabel.visibleProperty().bind(isMenuHovered);
        helpLabel.visibleProperty().bind(isMenuHovered);
        
        // 绑定VBox宽度:未悬停60px,悬停200px
        menuBox.prefWidthProperty().bind(isMenuHovered.map(hovered -> hovered ? 200.0 : 60.0));
        
        // 绑定鼠标进入/退出事件,更新悬停状态
        menuBox.setOnMouseEntered(event -> isMenuHovered.set(true));
        menuBox.setOnMouseExited(event -> isMenuHovered.set(false));
        
        // 确保VBox能接收鼠标事件(设置背景,透明也可)
        menuBox.setStyle("-fx-background-color: #2c3e50; -fx-padding: 10px; -fx-cursor: hand;");
    }
}

3. 主启动类

package com.example;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class MainApp extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(MainApp.class.getResource("menu-view.fxml"));
        Scene scene = new Scene(fxmlLoader.load(), 800, 600);
        stage.setTitle("Windows 10风格菜单");
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

关键注意点

  • 必须给VBox设置背景(哪怕是透明),否则鼠标事件无法触发,默认VBox不接收鼠标事件
  • 使用属性绑定替代手动修改UI状态,确保菜单宽度与文字显示完全同步
  • StackPane布局默认让VBox覆盖在内容区域上方,符合Windows开始菜单的覆盖逻辑

内容的提问来源于stack exchange,提问作者Haris Veerabadran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 04:25:27