QML做一个聊天框

用QML做聊天界面的思路一般都是用ListView来展示聊天记录。我也做了一个简易的聊天框,效果如下:

虽然思路很简单,但是实现时遇到不少QML的Bug,比如滚动时图片闪烁、拉伸时位置/宽度绑定错误(所以我放弃了Layout)等,可能在别的版本还会有其他QML渲染上的Bug。

代码链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qml/TalkList

不同类型的消息我用了不同的delegate,因为要动态选择delegate又使用了Loader进行加载。为了在Loader的sourceComponent里像一般的ListView delegate那样访问model数据,需要把Component声明到Loader里。

    delegate: Loader{
        sourceComponent: {
            switch(model.type){
            case TalkData.Text:

                return text_comp;
            case TalkData.Audio:
                return audio_comp;
            }
            return none_comp;
        }

        //放到delegate才能attach model
        Component{
            id: text_comp
            TalkItemText{ }
        }
        Component{
            id: audio_comp
            TalkItemAudio{ }
        }
        Component{
            id: none_comp
            Item{ }
        }
    }

Text不能选中文本,所以我用TextEdit来展示消息。不过这样也只能选中一个Label里的文本,不能全选。

下面贴两个主体代码,即文本行delegate的代码(完整代码请在上面的github连接下):

code 1.delegate item 基类

import QtQuick 2.12
import QtQuick.Layouts 1.12

//信息delegate的基类
//龚建波 2021-3-29
Item {
    id: control

    width: parent.ListView.view.width
    height: Math.max(profileHeight,
                     content_item.height)

    //profile picture头像
    property int profileHeight: 48
    property int messageHeight: 48

    property int leftWidth: 110
    property int rightWidth: 110
    property int contentWidth: Math.max(10,control.width-control.leftWidth-control.rightWidth)
    property bool isUser: (model.user===model.sender)
    property color messageBgColor: control.isUser?"#98E892":"#FFFFFF"

    default property alias contentItems: content_item.children

    Item{
        id: left_item
        height: control.height
        width: control.leftWidth
        //目前头像为固定,动态值可以放model
        Image {
            visible: !control.isUser
            width: control.profileHeight
            height: control.profileHeight
            anchors.horizontalCenter: parent.horizontalCenter
            source: "qrc:/Image/profile_48_gray.png"
            //fillMode: Image.PreserveAspectFit
        }
    }

    Column{
        id: content_item
        x: control.leftWidth
        width: control.contentWidth
        spacing: 6
        //layoutDirection: control.isUser?Qt.RightToLeft:Qt.LeftToRight
    }
    Item {
        id: right_item
        height: control.height
        width: control.rightWidth
        anchors.right: parent.right
        //头像没必要放两个,可以动态锚定
        //但是区分开后可以写一些差异化的操作
        Image {
            visible: control.isUser
            width: control.profileHeight
            height: control.profileHeight
            anchors.horizontalCenter: parent.horizontalCenter
            source: "qrc:/Image/profile_48_gray.png"
            //fillMode: Image.PreserveAspectFit
        }
    }

    //Component.onCompleted: {
    //    console.log('init',index);
    //}
    //Component.onDestruction: {
    //    console.log('free',index);
    //}
}

code 2.delegate text

import QtQuick 2.12

//文本信息delegate
//龚建波 2021-3-29
TalkItemBase {
    id: control

    //ColumnLayout在拉伸时计算有问题,暂时用Column+Row
    Row{
        width: control.contentWidth
        layoutDirection: control.isUser?Qt.RightToLeft:Qt.LeftToRight
        Rectangle{
            id: wrap_item
            radius: 4
            width: text_item.width
            height: text_item.height
            color: control.messageBgColor

            //指向发言人小三角
            Rectangle{
                width: 10
                height: 10
                y: control.messageHeight/2-10
                anchors.horizontalCenter: control.isUser?parent.right:parent.left
                rotation: 45
                color: control.messageBgColor
            }

            TalkLabel{
                id: text_item
                text: model.text_text
                width: Math.min(control.contentWidth,textWidth)
            }
        }
    }

    Row{
        width: control.contentWidth
        layoutDirection: control.isUser?Qt.RightToLeft:Qt.LeftToRight
        TalkLabel{
            text: model.datetime
            padding: 0
        }
    }
}

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龚建波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值