QML QtQuick.Controls 2 MenuBar/Menu菜单样式自定义

版本:Qt5.12.5 ,参考Qt源码及文档示例

代码链接:https://github.com/gongjianbo/QmlComponentStyle.git  

在Qt5.12的文档中你可以搜索到三个MenuBar组件,这里我修改的是Control2中的菜单栏样式,对比如下:

因为菜单栏及菜单项是多个组件组合而成的,都需要进行了自定义来统一风格:

样式修改也没什么好讲的,就那几个固定的设置,要做的就是改改属性参数来实现界面效果。QML这个MenuBar有个好处就是能随便放在哪个位置,Menu也可以单独作为弹出式的菜单。直接放代码:

//basicmenu.qml 

//basicmenu.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.impl 2.12
import QtQuick.Templates 2.12 as T
import QtQuick.Window 2.12

T.Menu {
    id: control

    property color borderColor: "black"
    property color backgroundColor: "white"

    implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
                            contentWidth + leftPadding + rightPadding)
    implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
                             contentHeight + topPadding + bottomPadding)

    margins: 0
    overlap: 1
    font{
        family: "SimSun"
        pixelSize: 14
    }

    delegate: BasicMenuItem { }

    contentItem: ListView {
        implicitHeight: contentHeight
        model: control.contentModel
        interactive: Window.window ? contentHeight > Window.window.height : false
        clip: true
        currentIndex: control.currentIndex

        ScrollIndicator.vertical: ScrollIndicator {}
    }

    background: Rectangle {
        implicitWidth: 122
        implicitHeight: 32
        color: control.backgroundColor
        border.width: 1
        border.color: control.borderColor
    }

    T.Overlay.modal: Rectangle {
        color: Color.transparent(control.palette.shadow, 0.5)
    }

    T.Overlay.modeless: Rectangle {
        color: Color.transparent(control.palette.shadow, 0.12)
    }
}

//basicmenubar.qml 

//basicmenubar.qml
import QtQuick 2.12
import QtQuick.Templates 2.12 as T
import QtQuick.Controls 2.12
import QtQuick.Controls.impl 2.12

T.MenuBar {
    id: control

    property color backgroundColor: "white"
    property color borderColor: "black"

    implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
                            contentWidth + leftPadding + rightPadding)
    implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
                             contentHeight + topPadding + bottomPadding)

    font{
        family: "SimSun"
        pixelSize: 16
    }
    delegate: BasicMenuBarItem { }

    contentItem: Row {
        spacing: control.spacing
        Repeater {
            model: control.contentModel
        }
    }

    //背景在MenuBarItem之下,我把MenuBarItem的background高度去了1px
    background: Rectangle {
        implicitHeight: 30
        color: control.backgroundColor

        Rectangle {
            color: control.borderColor
            width: parent.width
            height: 1
            anchors.bottom: parent.bottom
        }
    }
}

//basicmenubaritem.qml 

//basicmenubaritem.qml
import QtQuick 2.12
import QtQuick.Templates 2.12 as T
import QtQuick.Controls 2.12
import QtQuick.Controls.impl 2.12

T.MenuBarItem {
    id: control

    property color textColor: control.highlighted ? "cyan" : "white"
    property color backgroundColor: control.down || control.highlighted ? "black" : "gray"

    implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
                            implicitContentWidth + leftPadding + rightPadding)
    implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
                             implicitContentHeight + topPadding + bottomPadding,
                             implicitIndicatorHeight + topPadding + bottomPadding)

    //spacing: 6
    padding: 0
    leftPadding: 12
    rightPadding: 12

    //icon.width: 24
    //icon.height: 24
    //icon.color: control.palette.buttonText

    contentItem: Text {
        text: control.text
        font: control.font
        //opacity: enabled ? 1.0 : 0.3
        color: control.textColor
        horizontalAlignment: Text.AlignLeft
        verticalAlignment: Text.AlignVCenter
        renderType: Text.NativeRendering
        elide: Text.ElideRight
    }

    background: Rectangle {
        implicitHeight: 30
        height: control.height-1
        color: control.backgroundColor
    }
}

//basicmenuitem.qml 

//basicmenuitem.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.impl 2.12
import QtQuick.Templates 2.12 as T
import QtQuick.Shapes 1.12

T.MenuItem {
    id: control

    property color textColor: control.highlighted ? "cyan" : "black"
    property color buttonColor: control.down ? "black": control.highlighted ? "gray": "transparent"
    property color indicatorColor: "black"
    property color arrowColor: "black"

    implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
                            implicitContentWidth + leftPadding + rightPadding)
    implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
                             implicitContentHeight + topPadding + bottomPadding,
                             implicitIndicatorHeight + topPadding + bottomPadding)

    padding: 0
    spacing: 6

    contentItem: Text {
        readonly property real arrowPadding: control.subMenu && control.arrow ? control.arrow.width + control.spacing : 0
        readonly property real indicatorPadding: control.checkable && control.indicator ? control.indicator.width + control.spacing : 0
        readonly property real left_pd: !control.mirrored ? indicatorPadding : arrowPadding
        //没有边距就贴在边上了
        leftPadding: left_pd<=0?6:left_pd
        rightPadding: control.mirrored ? indicatorPadding : arrowPadding

        horizontalAlignment: Text.AlignLeft
        verticalAlignment: Text.AlignVCenter
        renderType: Text.NativeRendering
        text: control.text
        font: control.font
        color: control.textColor
    }

    indicator: Item {
        x: control.mirrored ? control.width - width - control.rightPadding : control.leftPadding
        //y: control.topPadding + (control.availableHeight - height) / 2
        implicitWidth: 30
        implicitHeight: 30
        Rectangle {
            width: parent.width-8
            height: width
            anchors.centerIn: parent
            visible: control.checkable
            border.width: 1
            border.color: control.indicatorColor
            Rectangle {
                width: parent.width-8
                height: width
                anchors.centerIn: parent
                visible: control.checked
                color: control.indicatorColor
            }
        }
    }

    arrow: Shape {
        id: item_arrow
        x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding
        //y: control.topPadding + (control.availableHeight - height) / 2
        visible: control.subMenu
        implicitWidth: 30
        implicitHeight: 30
        ShapePath {
            strokeWidth: 0
            strokeColor: control.arrowColor
            fillRule: ShapePath.WindingFill
            fillColor: control.arrowColor
            startX: item_arrow.width/4
            startY: item_arrow.height*3/4
            PathLine { x:item_arrow.width/4; y:item_arrow.height/4 }
            PathLine { x:item_arrow.width/2; y:item_arrow.height/2 }
            PathLine { x:item_arrow.width/4; y:item_arrow.height*3/4 }
        }
    }

    background: Rectangle {
        implicitWidth: 120
        implicitHeight: 30
        x: 1
        y: 1
        width: control.width - 2
        height: control.height - 2
        color: control.buttonColor
    }
}

//basicmenuseparator.qml 

//basicmenuseparator.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.impl 2.12
import QtQuick.Templates 2.12 as T

T.MenuSeparator {
    id: control

    property color contentColor: "black"
    property color backgroundColor: "transparent"

    implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
                            implicitContentWidth + leftPadding + rightPadding)
    implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
                             implicitContentHeight + topPadding + bottomPadding)

    padding: 0
    topPadding: 4
    bottomPadding: 4
    contentItem: Rectangle {
        implicitWidth: 120
        implicitHeight: 1
        color: contentColor
    }
    background: Rectangle{
        color: backgroundColor
    }
}

//main.qml 使用

        MenuBar{
            width: 600
            Menu{
                title: "MenuA"
                Action{ text: "A"; checkable: true; checked: true }
                Action{ text: "B"; checkable: true; }
                MenuSeparator{}
                Menu{
                    title: "C"
                    Action{ text: "A" }
                    Action{ text: "B" }
                }
            }
            Menu{
                title: "Menu Test"
                Action{ text: "A" }
                Action{ text: "B" }
            }
        }

        BasicMenuBar{
            width: 600
            height: 30
            BasicMenu{
                title: "MenuA"
                Action{ text: "A"; checkable: true; checked: true }
                Action{ text: "B"; checkable: true; }
                BasicMenuSeparator{ }
                BasicMenu{
                    title: "C"
                    Action{ text: "A" }
                    Action{ text: "B" }
                }
            }
            BasicMenu{
                title: "Menu Test"
                Action{ text: "A" }
                Action{ text: "B" }
            }
        }
发布了95 篇原创文章 · 获赞 26 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/gongjianbo1992/article/details/102644250