首页 > 其他 > 详细

基于QML模拟QQ群聊窗口

时间:2014-04-10 17:19:11      阅读:673      评论:0      收藏:0      [点我收藏+]


   据说最近要开发简单的IM工具,于是兴起,研究了下QQ聊天窗口,大概模拟了一下群聊的聊天显示界面,遂与大家分享之

   画面粗糙还望海涵

   bubuko.com,布布扣bubuko.com,布布扣

    图片有点大,原理基本就是使用listview来显示每一条记录,别人的记录显示在左侧,自己的聊天记录显示在右侧,但是他们公用的一个内容控件

   贴下main.qml的代码吧,main本来应该是比较简洁的,这里未来得及整理,有需要大家可以自己去整理

   

import QtQuick 2.0
import QtQuick.XmlListModel 2.0

Item {
    width: 400
    height: 600
//    color: "gray"
    property XmlListModel tmpModel;
    property string atContents: "@zhuditingyu"
    XmlListModel {
        id: xmlModel
        source:"qrc:/ybemxml_new.xml"
        query: "/ybdb/img/item"
        XmlRole { name: "title"; query: "title/string()" }
        XmlRole { name: "path"; query: "path/string()" }
        XmlRole { name: "title2"; query: "title2/string()" }
        Component.onCompleted: {
            tmpModel = xmlModel;
        }
    }


    Rectangle{
        id:atSomeBody
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top:parent.top
        anchors.leftMargin: 12
        anchors.rightMargin: 12
        anchors.topMargin: 12
        height: 30
        radius: 10
        z:2
        color: "gray"
        opacity: 0.0
        Text {
            id: atName
            text: atContents
//            anchors.centerIn: parent
            horizontalAlignment: Text.AlignLeft
            verticalAlignment: Text.AlignVCenter
            width: parent.width
            height: parent.height
        }

    }
    SequentialAnimation {
            id:animation
            NumberAnimation { target: atSomeBody; property: "opacity"; to: 0.8; duration: 500 }
            PauseAnimation { duration: 2000 }
            NumberAnimation { target: atSomeBody; property: "opacity"; to: 0; duration: 500 }
        }

    ListModel{
        id:chatModel
//        ListElement{
//            //cid:x1
//            chatName1:"yitb"
//            chatHead1:"http://img01.nduoa.com/apk/658/658954/icon_72.png"
//            chatFlag1:0
//            chatContents1:"way同学们 都在干嘛呢?"
//            chatTime1:"1397031550073"
//        }
//        ListElement{
//            //            cid:x2
//            chatName1:"yitb2"
//            chatFlag1:1
//            chatHead1:"http://img01.nduoa.com/apk/662/662455/icon_72.png"
//            chatContents1:"群主有福利啦 what a fuck day"
//            chatTime1:"1397031550088"

//        }
//        ListElement{
//            //            cid:x3
//            chatName1:"yitb3"
//            chatFlag1:1
//            chatHead1:"http://img01.nduoa.com/apk/662/662455/icon_72.png"
//            chatContents1:"呵呵,笑死我拉what a fuck day"
//            chatTime1:"1397031550073"
//        }
        ListElement{
            //            cid:x4
            chatName1:"yitb"
            chatFlag1:0
            chatHead1:"http://img01.nduoa.com/apk/658/658954/icon_72.png"
            chatContents1:"都在干嘛呢?不吭声的都木有JJ daywhat a fuck daywhat a fuck day"
            chatTime1:"1397031550000"
        }

    }

    Rectangle{
        id:viewRect
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top:parent.top
        anchors.leftMargin: 10
        anchors.rightMargin: 10
        anchors.topMargin: 10
        height: parent.height-200
        border.width: 2
        border.color: "green"
        radius: 10
        ListView{
            id:chatView
            width: parent.width-10
            anchors.centerIn: parent
            height: parent.height-10
            spacing:10
            delegate: ChatItem{

                chatName: chatName1
                chatContents: chatContents1
                chatFlag: chatFlag1
                chatHead: chatHead1
                chatTime: chatTime1
                chatIndex: index
            }
            clip:true
            model:chatModel
        }
    }
    ChatBiaoq{
        id:biaoq
        anchors.left: parent.left
        anchors.leftMargin: 10
        anchors.bottom: option.top
        anchors.bottomMargin: 10
        opacity: 0
        visible: false
        onSignalClickCurrentImg: {
            console.log(imgName+" "+strPath);
            edit.text += imgName;
        }
    }
    SequentialAnimation {
        id:animation2
        NumberAnimation { target: biaoq; property: "opacity"; to: 0.8; duration: 500 }
        PauseAnimation { duration: 2000 }
        //NumberAnimation { target: atSomeBody; property: "opacity"; to: 0; duration: 500 }
    }
    SequentialAnimation {
        id:animation3
        NumberAnimation { target: biaoq; property: "opacity"; to: 0.0; duration: 500 }
        PauseAnimation { duration: 2000 }
//        NumberAnimation { target: biaoq; property: "visible"; to: f; duration: 500 }
    }

    ChatOption{
        id:option
        anchors.left: parent.left
        anchors.leftMargin: 10

        anchors.right: parent.right
        anchors.rightMargin: 10
        anchors.top:viewRect.bottom
        anchors.topMargin: 10
        onSignalSendType: {
            switch(iType)
            {
            case 0:
            {
                biaoq.visible =true;
                animation2.stop();
                animation2.start();
            }break;
            case 1:
            {

            }break;
            }
        }

    }

    Rectangle{
        id:editRect
        height: 100;
        anchors.left: parent.left
        anchors.leftMargin: 10

        anchors.right: parent.right
        anchors.rightMargin: 5
        anchors.top:viewRect.bottom
        anchors.topMargin: 50
        border.width: 1
        border.color: "gray"
        radius: 10

        Flickable {
            id: flick
            width: parent.width-20
            height: parent.height-10
            anchors.centerIn: parent
            contentWidth: edit.paintedWidth
            contentHeight: edit.paintedHeight
            clip: true

            function ensureVisible(r)
            {
                if (contentX >= r.x)
                    contentX = r.x;
                else if (contentX+width <= r.x+r.width)
                    contentX = r.x+r.width-width;
                if (contentY >= r.y)
                    contentY = r.y;
                else if (contentY+height <= r.y+r.height)
                    contentY = r.y+r.height-height;
            }

            TextEdit {
                id: edit
                width: flick.width
                height: flick.height
                focus: true
                wrapMode: TextEdit.Wrap
                onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
                Keys.onReturnPressed: {
                    appendData(edit.text,0);
                    edit.text = "";
                    chatView.positionViewAtEnd();
                    animation3.stop();
                    animation3.start();
                    biaoq.visible = false;
                }
            }
        }
    }
    ChatScrollBar{
        id:scBar
        anchors.right: viewRect.right
        anchors.rightMargin: 2
        anchors.top: viewRect.top
        anchors.bottom: viewRect.bottom
        width: 10
        scrollColor: "#dbe1e5"
        opacity: 0
        orientation: Qt.Vertical
        position: chatView.visibleArea.yPosition
        pageSize: chatView.visibleArea.heightRatio
        clip: true
    }
    states: State {
        name: "ShowBars"
        when: chatView.movingVertically || chatView.movingHorizontally
        PropertyChanges { target: scBar; opacity: 1 }
    }

    Rectangle{
        id:btn
        anchors.bottom: parent.bottom
        anchors.right: parent.right
        anchors.rightMargin: 10
        anchors.bottomMargin: 5
        width: 100
        height: 30
        border.width: 1
        border.color: "gray"
        radius: 5
        Text{
            id:cli
            text: "Send"
            anchors.centerIn: parent
        }

        MouseArea{
            id:ma
            anchors.fill: parent
            enabled: edit.text.length?true:false
            onClicked: {
                appendData(edit.text,0);
                edit.text = "";
                chatView.positionViewAtEnd();
                animation3.stop();
                animation3.start();
                biaoq.visible = false;
            }
        }
    }

    Rectangle{
        id:btn1
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.leftMargin: 10
        anchors.bottomMargin: 5
        width: 100
        height: 30
        border.width: 1
        border.color: "gray"
        radius: 5
        Text{
            id:cli1
            text: "Send"
            anchors.centerIn: parent
        }

        MouseArea{
            id:ma1
            anchors.fill: parent
            enabled: edit.text.length?true:false
            onClicked: {
                appendData(edit.text,1);
                edit.text = "";
                chatView.positionViewAtEnd();
                animation3.stop();
                animation3.start();
                biaoq.visible = false;
            }
        }
    }
    function findAtSome(str)
    {
        for(var i=0;i<chatModel.count;i++)
        {
            var tmp = "@";
            tmp += chatModel.get(i).chatName1;
            console.log("tmp "+tmp +" str" +str);
            if(str.indexOf(tmp) >= 0 )
            {
                console.log("in it.................")
                return true;
            }else{
                continue;
            }
        }
        return false;
    }

    function appendData(str,iflag)
    {
       var tmp = str;//.replace(/[\r\n]/g,"");
//       var curTime = new Date().UTC();
        var curTime=new Date().getTime();
//        结果:1280977330748
       console.log(curTime);
       var isRepeat = findSameTime(curTime.toString());
        var tmpTime;
        if(isRepeat)
        {
            tmpTime = "";
        }else{
            tmpTime = curTime.toString();
        }
       if(iflag == 0)
       {
           chatModel.append({"chatName1": "卧栏听雨", "chatHead1":"http://img01.nduoa.com/apk/658/658954/icon_72.png", "chatContents1":tmp, "chatFlag1":0,"chatTime1":tmpTime});
       }else{
           chatModel.append({"chatName1": "寒山居士", "chatHead1":"http://img01.nduoa.com/apk/662/662455/icon_72.png", "chatContents1":tmp, "chatFlag1":1,"chatTime1":tmpTime});


       }
       if(findAtSome(str))
       {
           animation.stop();
           atName.text = str;
           animation.start();
       }
   }
    function findSameTime(str)
    {
        for(var i=0;i<chatModel.count;i++)
        {
            if(isSameTime(chatModel.get(i).chatTime1,str))
            {
                console.log("model time: "+chatModel.get(i).chatTime1)
                return true;
            }else{
                continue;
            }
        }
        return false;
    }

    function getFormatData(msecond,iType)
    {
        var dates = new Date((msecond - 0)+ 8*3600);;
        if(iType == 0)
        {
            return dates.getUTCFullYear().toString();
        }else if(iType == 1)
        {
            return dates.getMonth().toString();
        }else if(iType == 2)
        {
            return dates.getDate().toString();
        }else if(iType == 3)
        {
            return dates.getHours().toString();
        }else if(iType == 4)
        {
            return dates.getMinutes().toString();
        }
    }

    function isSameTime(strModel,str)
    {
        var tmpTime = strModel;
        console.log(tmpTime+" "+str);

        if(getFormatData(tmpTime,0) == getFormatData(str,0))
        {

            if(getFormatData(tmpTime,1) == getFormatData(str,1))
            {
                if(getFormatData(tmpTime,2) == getFormatData(str,2))
                {
                    if(getFormatData(tmpTime,3) == getFormatData(str,3))
                    {
                        if(getFormatData(tmpTime,4) == getFormatData(str,4))
                        {
                            console.log("alsfalkflaslakls is True");
                            return true;
                        }else{
                            return false;
                        }

                    }
                }
            }

            return false;
        }else{
            return false;
        }
    }

    function filterImg(str){
        for(var i=0;i<tmpModel.count;i++)
        {
            var curTitle=tmpModel.get(i).title2;
            var curPath = "<img src="+tmpModel.get(i).path+"/>";
            var reg = new RegExp(curTitle, "ig");
            str = str.replace(reg, curPath);
        }
        var orgStr =str.replace(/<<(.+?)>>/gi,"<<$1>>");
        orgStr.replace(/‘/gi,"‘")
        console.log("orgStrorgStrorgStr "+orgStr);
        return orgStr;
    }
}
其他文件稍后在附件里面附上 代码

基于QML模拟QQ群聊窗口,布布扣,bubuko.com

基于QML模拟QQ群聊窗口

原文:http://blog.csdn.net/esonpo/article/details/23344207

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!