如何在QML应用中创建类似ContextMenu的控件
来源:互联网 发布:樱井知香喷泉图片下载 编辑:程序博客网 时间:2024/05/21 12:46
在我们先前的文章"如何在QML应用中创建一个Context Menu",我们使用了一个popup的方法来显示一个我们自己需要的context menu.那个方法虽好,但是显示起来和背景的颜色很相近,不容易看出来.当然我们可以通过一些方法来改进我的设计.在今天的例程中,我们通过另外一种方法来做一个同样的context menu.这个方法的好处是,我们可以随意来设计我们所需要的效果.我们从另外一个角度来实现同样的东西.我们设计的最终效果为:
我们可以通点击上图中的图标来弹出我们所需要的选项,在选项中,我们可以做出我们的选择.当选择完后,我们可以点击图标收回选项.基于这个设计我们还可以更进一步做更多的改进.比如点击区域以外的地方自动让选项列表消失.当然,我们也可以加入我们的动画效果.
上面图中的一个图标及一个文字,我们是通过一个AbstractButton控件来实现的.当然,我们也可以采用一个ListView来实现.
OptionValueButton.qml
import QtQuick 2.4import Ubuntu.Components 1.3AbstractButton { id: optionValueButton implicitHeight: units.gu(5) property alias label: label.text property alias iconName: icon.name property bool selected property bool isLast property int columnWidth property int marginSize: units.gu(1) width: marginSize + iconLabelGroup.width + marginSize Item { id: iconLabelGroup width: childrenRect.width height: icon.height anchors { left: (iconName) ? undefined : parent.left leftMargin: (iconName) ? undefined : marginSize horizontalCenter: (iconName) ? parent.horizontalCenter : undefined verticalCenter: parent.verticalCenter topMargin: marginSize bottomMargin: marginSize } Icon { id: icon anchors { verticalCenter: parent.verticalCenter left: parent.left } width: optionValueButton.height - optionValueButton.marginSize * 2 color: "white" opacity: optionValueButton.selected ? 1.0 : 0.5 visible: name !== "" } Label { id: label anchors { left: icon.name != "" ? icon.right : parent.left verticalCenter: parent.verticalCenter leftMargin: units.gu(0.5) } color: "white" opacity: optionValueButton.selected ? 1.0 : 0.5 width: paintedWidth } } Rectangle { anchors { left: parent.left bottom: parent.bottom } width: parent.columnWidth height: units.dp(1) color: "red" opacity: 0.5 visible: true }}
我们的Main.qml设计也比较简单.只是在这里面,我们使用了Item中mapFromItem来得到我们点击的控件的位置信息.利用这个位置信息,我们来定位我们的选项的optionValueSelector位置.整个设计如下:
Main.qml
import QtQuick 2.4import Ubuntu.Components 1.3/*! \brief MainView with a Label and Button elements.*/MainView { // objectName for functional testing purposes (autopilot-qt5) objectName: "mainView" // Note! applicationName needs to match the "name" field of the click manifest applicationName: "mapfromitem.liu-xiao-guo" width: units.gu(60) height: units.gu(85) theme.name :"Ubuntu.Components.Themes.SuruDark" property bool optionValueSelectorVisible: false Page { header: PageHeader { id: pageHeader title: i18n.tr("mapfromitem") } ListModel { id: model property int selectedIndex: 0 ListElement { icon: "account" label: "On" value: "flash-on" } ListElement { icon: "active-call" label: "Auto" value: "Auto" } ListElement { icon: "call-end" label: "Off" value: "flash-off" } } Column { id: optionValueSelector objectName: "optionValueSelector" width: childrenRect.width spacing: units.gu(1) property Item caller function toggle(model, callerButton) { if (optionValueSelectorVisible && optionsRepeater.model === model) { hide(); } else { show(model, callerButton); } } function show(model, callerButton) { optionValueSelector.caller = callerButton; optionsRepeater.model = model; alignWith(callerButton); optionValueSelectorVisible = true; } function hide() { optionValueSelectorVisible = false; optionValueSelector.caller = null; } function alignWith(item) { // horizontally center optionValueSelector with the center of item // if there is enough space to do so, that is as long as optionValueSelector // does not get cropped by the edge of the screen var itemX = parent.mapFromItem(item, 0, 0).x; var centeredX = itemX + item.width / 2.0 - width / 2.0; var margin = units.gu(1); if (centeredX < margin) { x = itemX; } else if (centeredX + width > item.parent.width - margin) { x = itemX + item.width - width; } else { x = centeredX; } // vertically position the options above the caller button y = Qt.binding(function() { return item.y - height - units.gu(2) }); console.log("x: " + x + " y: " + y) } visible: opacity !== 0.0 onVisibleChanged: if (!visible) optionsRepeater.model = null; opacity: optionValueSelectorVisible ? 1.0 : 0.0 Behavior on opacity {UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration}} Repeater { id: optionsRepeater delegate: OptionValueButton { anchors.left: optionValueSelector.left columnWidth: optionValueSelector.childrenRect.width label: model.label iconName: model.icon selected: optionsRepeater.model.selectedIndex == index isLast: index === optionsRepeater.count - 1 onClicked: { optionsRepeater.model.selectedIndex = index console.log(optionsRepeater.model.get(index).value) } } } } Icon { id: optionButton width: units.gu(3) height: width anchors.centerIn: parent name: model.get(model.selectedIndex).icon MouseArea { anchors.fill: parent onClicked: { console.log("optionValueSelectorVisible: " + optionValueSelectorVisible) optionValueSelector.toggle(model, optionButton) } } } Component.onCompleted: { console.log("width: " + width + " height: " +height) } }}
整个项目的源码在:https://github.com/liu-xiao-guo/mapfromitem
0 0
- 如何在QML应用中创建类似ContextMenu的控件
- 如何在QML应用中创建一个Context Menu
- 如何在QML应用中设计自己的Dialog
- 如何在Ubuntu QML应用中实现ComboBox的功能
- 如何在QML应用中读写文件
- 如何在QML应用中启动Scope
- 如何在web中实现类似excel的表格控件
- 如何在Ubuntu QML应用中判断应用的方位(landscape或portrait)
- 如何在QML应用中在触屏的时候感知触觉
- 如何在QML应用中显示在系统中的所有的字体
- 如何在Ubuntu QML应用中使用Push Notification
- 如何在QML应用中使用Javascript解析JSON
- 如何在QML应用中使用Javascript来解析XML
- 如何在Ubuntu QML应用中播放音乐
- 如何在Ubuntu QML应用中播放视频
- 如何在Ubuntu QML应用中震动(vibration)
- 如何在QML应用中实现一个Splash画面
- 如何在Ubuntu QML应用中进行语言录音
- AVL树的插入与删除
- Android通过HttpURLConnection与HttpClient联网代理网关设置
- 深入理解Interpreter模式
- 谷歌又惹新麻烦 法国将对其网络广告展开调查
- WPF 多线程设计
- 如何在QML应用中创建类似ContextMenu的控件
- SpringMVC Controller写法
- AWS Ubuntu Lampp + wordpress install
- jQuery常用插件总结
- 升级 HTTPS,价值何在?
- SLF4J
- java40java中的数组
- hdu 2145(最短路+排序)
- exit(),_exit(),_Exit()