版本: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" }
}
}