qml自定义消息弹窗messagebox

  • Post author:
  • Post category:其他


环境:qt creator 5.7.0

之前我写过在

qt widgets中自定义messageBox

,感觉在qml文件中使用消息对话框不像qt widgets中那么方便和友好,虽然说qml中有基础组件

MessageDialog

可以调用,但好像不能自定义其样式而显得格格不入,感觉就很鸡肋。于是自己重写了个消息弹窗供大家参考和指正,从而进一步优化。

先看效果图:

在这里插入图片描述

在这里插入图片描述

至于样式呢就留给大家根据自己的界面风格去添加和优化了,我只提供基础的框架。



实现原理:



消息类型:

首先就是定义消息类型了,比如以下代码就定义了6种消息类型,0x01 << 2表示把1往左移2位,其实就是1变成了4,不懂的去补习语法

property var mb_OK      : 0x01 << 2
property var mb_SAVE    : 0x01 << 3
property var mb_YES     : 0x01 << 4
property var mb_NO      : 0x01 << 5
property var mb_CANCEL  : 0x01 << 6
property var mb_RELOGIN : 0x01 << 7



动态创建按钮:

不同的消息弹窗可能有不同的按钮组合,当然不能写死了,这就需要在qml中动态创建了。使用

createObject

就可以实现,比如下面代码:

RowLayout{
   id:id_layout
}
Component
{
    id:id_comp
    Button{
        property var type: 0x01
        onClicked: checkd(type)
    }
}

function checkd(_type)
{
    root.retValue = _type
    root.close()
}

function add_one(type, text){
var obj = id_comp.createObject(id_layout,{"Layout.alignment" : Qt.AlignHCenter, "Layout.preferredWidth" : 60, "Layout.preferredHeight" : 30,"text" : text})
obj.type = type
}

调用add_one函数,传入消息类型type和文本text,然后创建Button控件,点击Button则调用checkd函数,check函数中将消息类型_type赋给弹窗的返回值变量retValue,关闭弹窗后我们会根据这个变量retValue判断用户点击了哪个按钮,是不是感觉有点麻烦?其实并没有,只是简单的逻辑处理罢了,不多说了,直接上代码,毕竟看代码才是我们程序员的喜欢的事情。


新建一个消息框文件CMsgBox.qml

//CMsgBox.qml
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3


Window {
    id: root
    
    property var mb_OK      : 0x01 << 2//0x00000400
    property var mb_SAVE    : 0x01 << 3//0x00002000
    property var mb_YES     : 0x01 << 4//0x00004000
    property var mb_NO      : 0x01 << 5//0x00010000
    property var mb_CANCEL  : 0x01 << 6//0x0008000
    property var mb_RELOGIN : 0x01 << 7

    property var message: ""    //消息框的消息文本
    property var btnType: 0x01  //按钮组合类型
    property var retValue: 0x01 //关闭对话框后点击的按钮类型

    modality: Qt.ApplicationModal
    flags: Qt.FramelessWindowHint | Qt.Window

    width: 313
    height: 150
    color: "transparent"
    Rectangle{
        anchors.fill: parent
        anchors.margins: 4
        color: "#23518b"
        radius: 5
        Item{
            id:id_item_header
            anchors.left:parent.left
            anchors.top:parent.top
            anchors.right: parent.right
            height: 40
            Text {
                id: id_img_icon
                anchors.verticalCenter: parent.verticalCenter
                anchors.left: parent.left
                anchors.leftMargin: 10
                text: qsTr("提示")
                color: "white"
            }
            Button {
                id: img
                text: "x"
                anchors.right: parent.right
                anchors.rightMargin: 5
                anchors.verticalCenter: parent.verticalCenter
                width: 30
                height: 30
                onClicked: checkd(mb_CANCEL)
            }
            //拖动窗口
            MouseArea {
                property point clickPos
                property bool isPressed: false
                anchors.left: parent.left
                anchors.top:parent.top
                anchors.bottom: parent.bottom
                anchors.right: img.left
                onPressed: {
                    isPressed = true
                    clickPos = Qt.point(mouse.x, mouse.y)
                }
                onReleased: isPressed = false
                onPositionChanged: {
                    var delta = Qt.point(mouse.x - clickPos.x,
                                         mouse.y - clickPos.y)

                    var tmpX = root.x + delta.x
                    var tmpY = root.y + delta.y
                    if(tmpX + root.width > 25 && Screen.desktopAvailableWidth - tmpX > 25)
                        root.x = tmpX
                    if(tmpY + root.height > 25 && Screen.desktopAvailableHeight - tmpY > 25)
                        root.y = tmpY

                }
            }
        }
        Rectangle {
            id:id_item_body
            anchors.left: parent.left
            anchors.top: id_item_header.bottom
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            Keys.onPressed: root.close()
            color: "#3568a7"
            radius:parent.radius
            Item{
                id:id_rect_msg
                anchors.fill: parent
                anchors.bottomMargin: 55
                Text {
                    anchors.fill: parent
                    anchors.leftMargin: 30
                    anchors.rightMargin: 30
                    horizontalAlignment:Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                    wrapMode: Text.WordWrap
                    color: "white"
                    text: qsTr(message)
                }
            }
            RowLayout{
                property var objs: []
                id:id_layout
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.top: id_rect_msg.bottom
                anchors.bottom: parent.bottom
            }
        }
    }
    onBtnTypeChanged: create(root.btnType)

    Component
    {
        id:id_btn_comp
        Button{
            property var type: 0x01
            onClicked: checkd(type)
        }
    }

    function clear()
    {
        var len = id_layout.objs.length
        for(var i=0;i<len;i++)
        {
            id_layout.objs[i].destroy()
        }
        id_layout.objs = []
        root.btnType = 0x01
    }

    function checkd(_type)
    {
        root.retValue = _type
        //clear()//可不要,因为对话框关闭后会被销毁释放,单例模式下对话框关闭不会被销毁释放
        root.close()
    }

    function add_one(type,text)
    {
        var obj = id_btn_comp.createObject(id_layout, {"Layout.alignment" : Qt.AlignHCenter, "Layout.preferredWidth" : 60, "Layout.preferredHeight" : 30,"text" : text})
        obj.type = type
        //id_layout.objs.push(obj)//可不要,这句是在单例模式下使用的(对话框只创建一次,后面每次打开都更新按钮)
    }

    function create(type)
    {
        if((type & root.mb_OK) === root.mb_OK)
        {
            add_one(root.mb_OK,"ok")
        }
        if((type & root.mb_SAVE) === root.mb_SAVE)
        {
            add_one(root.mb_SAVE,"save")
        }
        if((type & root.mb_YES) === root.mb_YES)
        {
            add_one(root.mb_YES,"yes")
        }
        if((type & root.mb_NO) === root.mb_NO)
        {
            add_one(root.mb_NO,"no")
        }
        if((type & root.mb_CANCEL) === root.mb_CANCEL)
        {
            add_one(root.mb_CANCEL,"cancel")
        }
        if((type & root.mb_RELOGIN) === root.mb_RELOGIN)
        {
            add_one(root.mb_RELOGIN,"relogin")
        }
    }
}

/*##^##
Designer {
    D{i:0;height:222;width:392}
}
##^##*/



调用方式:

对话框关闭后就

destroy

了,不会占用内存,在接收到消息框的

closing

关闭信号后,我们就在lambda函数

ret

中进行后续处理

import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.0

Window {
    id:window
    visible: true
    width: 16 * 50
    height: 9 * 50

    Button {
        anchors.centerIn: parent
        text: "show"
        onClicked:{
            var dia = Qt.createComponent("CMsgBox.qml")
            var dlg = dia.createObject(window)
            dlg.btnType = dlg.mb_OK | dlg.mb_NO | dlg.mb_CANCEL
            dlg.message = "Are you sure?"
            dlg.closing.connect(function ret(){
                if(dlg.retValue === dlg.mb_YES)
                {
                    //do something
                }
                else if(dlg.retValue === dlg.mb_NO)
                {
                    //do something
                }
                else if(dlg.retValue === dlg.mb_CANCEL)
                {
                    //do something
                }

                dlg.destroy()
            })
            dlg.show()
        }
    }
}



版权声明:本文为qq_26611129原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。