QML 分隔线:Rectangle、菜单与工具栏分隔线用法

文章来源声明: 原文作者:Quz; 来源站点:掘金; 原文链接:https://juejin.cn/post/7691876916195278863; 本文基于上述来源整理/加工,觅优补充点评,仅供技术学习交流。版权归原作者所有。
觅优短评

四个 Demo 覆盖从基础 Rectangle 到 Menu/ToolSeparator 的完整选型,封装 Divider 的思路尤其值得借鉴,适合 QML 界面开发时快速查表与复用。

界面里常用一条细细的分隔线做内容分区,而在QML里最简单的做法是画一条宽/高为1的 `Rectangle`,菜单和工具栏里则有现成的 `MenuSeparator`、`ToolSeparator`,需要特殊效果时还能用 `Repeater` 拼出虚线。这篇文章用四个 demo 把这几种做法都过一遍。

qml_separator.gif

Rectangle 分隔线——演示代码

import QtQuick
import QtQuick.Layouts

FadeInAnimation {
    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 15

        // ... 省略标题组件 TitleSeparator ...

        // 水平分隔线
        Divider {
            isVertical: false
        }

        RowLayout {
            Layout.fillWidth: true
            Layout.fillHeight: true

            Rectangle {
                Layout.fillWidth: true
                Layout.fillHeight: true
                color: "lightblue"
            }

            // 垂直分隔线
            Divider {
                isVertical: true
            }

            Rectangle {
                Layout.fillWidth: true
                Layout.fillHeight: true
                color: "lightgreen"
            }
        }

        Item { Layout.fillHeight: true }
    }
}

这个 Demo 里用到的 Divider 是工程里自封装的小组件,代码很短:

import QtQuick

Rectangle {
    property bool isVertical: false
    property color dividerColor: "#d5d5d5"
    property int dividerWidth: 1

    implicitWidth: isVertical ? dividerWidth : parent ? parent.width : 1
    implicitHeight: isVertical ? (parent ? parent.height : 1) : dividerWidth
    color: dividerColor
}

Divider 的本质就是一个 Rectangle,核心是 isVertical 这个开关:水平时宽度撑满父容器、高度只有一条线的粗细;垂直时反过来,宽度只有一条线的粗细、高度撑满。颜色和粗细都暴露成属性,想换随时改。把分隔线封装成组件的好处是,一个工程里所有分隔线都长一个样,改一处全局生效。

新手容易忽略一点:implicitWidth 和 implicitHeight 是"建议尺寸",ColumnLayout、RowLayout 这些布局排位置时会参考它们。Divider 的横竖转换其实就是把这两个建议尺寸对调,所以外面完全不用管它的宽高。

适用场景:页面里的分区线、表单分组线、任何要一条自定义线的场景。

菜单分隔线——演示代码

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

FadeInAnimation {
    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 15

        // ... 省略标题组件 TitleSeparator ...

        Menu {
            id: menu
            width: 120
            MenuItem { text: "复制" }
            MenuItem { text: "粘贴" }
            MenuSeparator { }
            MenuItem { text: "设置" }
            MenuItem { text: "帮助" }
        }

        Button {
            text: "点击显示菜单"
            onClicked: menu.popup()
        }

        Item { Layout.fillHeight: true }
    }
}

菜单里把"复制、粘贴"和"设置、帮助"用一条 MenuSeparator 隔开,两组功能一目了然。菜单平时不显示,点击按钮调 menu.popup() 才弹出来。MenuSeparator 不需要任何参数,放在哪就分隔到哪。

适用场景:右键菜单、下拉菜单里的功能分组。

工具栏分隔线——演示代码

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

FadeInAnimation {
    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 15

        // ... 省略标题组件 TitleSeparator ...

        ToolBar {
            Layout.fillWidth: true

            RowLayout {
                anchors.fill: parent
                ToolButton { text: "Act1" }
                ToolButton { text: "Act2" }
                ToolSeparator {}
                ToolButton { text: "Act3" }
                ToolButton { text: "Act4" }
                ToolSeparator {}
                Item {
                    Layout.fillWidth: true
                }
            }
        }

        Item { Layout.fillHeight: true }
    }
}

ToolSeparator 和 MenuSeparator 用法一样,插在按钮中间就能把按钮分成一组一组,比如"Act1、Act2"一组、"Act3、Act4"一组。它自带一条细竖线,样式跟工具栏风格统一,不用自己调。

适用场景:工具栏、菜单栏里的按钮分组。

自定义虚线分隔线——演示代码

import QtQuick
import QtQuick.Layouts

FadeInAnimation {
    ColumnLayout {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 15

        // ... 省略标题组件 TitleSeparator ...

        RowLayout {
            Layout.fillWidth: true
            Layout.fillHeight: true
            spacing: 10

            Rectangle {
                Layout.fillWidth: true
                Layout.fillHeight: true
                color: "lightpink"
            }

            // 自定义虚线分隔线
            Item {
                Layout.fillHeight: true
                width: 20

                Column {
                    anchors.centerIn: parent
                    spacing: 4
                    Repeater {
                        model: 5
                        Rectangle {
                            width: 4
                            height: 4
                            radius: 2
                            color: "darkgray"
                        }
                    }
                }
            }

            Rectangle {
                Layout.fillWidth: true
                Layout.fillHeight: true
                color: "lightyellow"
            }
        }
    }
}

虚线没有现成组件,思路是用 Repeater 重复生成几个灰色小圆点,放进 Column 里纵向排成一列,圆点之间留点间距,看起来就是一条虚线。小圆点带圆角,想换成方形虚线去掉圆角就行。整条线只占很窄的一列,插在两个色块中间,视觉上刚刚好。

什么场景用哪个

场景用哪个
页面里一条普通横线/竖线`Rectangle` 或自封装 `Divider`
菜单里给选项分组`MenuSeparator`
工具栏里给按钮分组`ToolSeparator`
虚线等特殊样式`Repeater` 自绘

已验证环境: