C++全栈聊天项目(20) 聊天列表动态加载

news2024/11/24 17:34:21

聊天列表动态加载

如果要动态加载聊天列表内容,我们可以在列表的滚动区域捕获鼠标滑轮事件,并且在滚动到底部的时候我们发送一个加载聊天用户的信号

bool ChatUserList::eventFilter(QObject *watched, QEvent *event)
{
    // 检查事件是否是鼠标悬浮进入或离开
    if (watched == this->viewport()) {
        if (event->type() == QEvent::Enter) {
            // 鼠标悬浮,显示滚动条
            this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
        } else if (event->type() == QEvent::Leave) {
            // 鼠标离开,隐藏滚动条
            this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        }
    }

    // 检查事件是否是鼠标滚轮事件
    if (watched == this->viewport() && event->type() == QEvent::Wheel) {
        QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
        int numDegrees = wheelEvent->angleDelta().y() / 8;
        int numSteps = numDegrees / 15; // 计算滚动步数

        // 设置滚动幅度
        this->verticalScrollBar()->setValue(this->verticalScrollBar()->value() - numSteps);

        // 检查是否滚动到底部
        QScrollBar *scrollBar = this->verticalScrollBar();
        int maxScrollValue = scrollBar->maximum();
        int currentValue = scrollBar->value();
        //int pageSize = 10; // 每页加载的联系人数量

        if (maxScrollValue - currentValue <= 0) {
            // 滚动到底部,加载新的联系人
            qDebug()<<"load more chat user";
            //发送信号通知聊天界面加载更多聊天内容
            emit sig_loading_chat_user();
         }

        return true; // 停止事件传递
    }

    return QListWidget::eventFilter(watched, event);
}

回到ChatDialog类里添加槽函数

void ChatDialog::slot_loading_chat_user()
{
    if(_b_loading){
        return;
    }

    _b_loading = true;
    LoadingDlg *loadingDialog = new LoadingDlg(this);
    loadingDialog->setModal(true);
    loadingDialog->show();
    qDebug() << "add new data to list.....";
    addChatUserList();
    // 加载完成后关闭对话框
    loadingDialog->deleteLater();

    _b_loading = false;
}

槽函数中我们添加了LoadingDlg类,这个类也是个QT 设计师界面类,ui如下

https://cdn.llfc.club/1717637779912.jpg

添加stackwidget管理界面

ChatDialog界面里添加stackedWidget,然后添加两个页面

https://cdn.llfc.club/1717639561119.jpg

回头我们将这两个界面升级为我们自定义的界面

我们先添加一个自定义的QT设计师界面类ChatPage,然后将原来放在ChatDialog.ui中的chat_data_wid这个widget移动到ChatPage中ui布局如下

https://cdn.llfc.club/1717640323397.jpg

布局属性如下

https://cdn.llfc.club/1717640426705.jpg

然后我们将ChatDialog.ui中的chat_page 升级为ChatPage。

接着我们将ChatPage中的一些控件比如emo_lb, file_lb升级为ClickedLabel, receive_btn, send_btn升级为ClickedBtn

如下图:

https://cdn.llfc.club/1717644080174.jpg

然后我们在ChatPage的构造函数中添加按钮样式的编写

ChatPage::ChatPage(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ChatPage)
{
    ui->setupUi(this);
    //设置按钮样式
    ui->receive_btn->SetState("normal","hover","press");
    ui->send_btn->SetState("normal","hover","press");

    //设置图标样式
    ui->emo_lb->SetState("normal","hover","press","normal","hover","press");
    ui->file_lb->SetState("normal","hover","press","normal","hover","press");
}

因为我们继承了QWidget,我们想实现样式更新,需要重写paintEvent

void ChatPage::paintEvent(QPaintEvent *event)
{
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

类似的,我们的ListItemBase

void ListItemBase::paintEvent(QPaintEvent *event)
{
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

ClickedLabel完善

我们希望ClickedLabel在按下的时候显示按下状态的资源,在抬起的时候显示抬起的资源,所以修改按下事件和抬起事件

void ClickedLabel::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        if(_curstate == ClickLbState::Normal){
              qDebug()<<"clicked , change to selected hover: "<< _selected_hover;
            _curstate = ClickLbState::Selected;
            setProperty("state",_selected_press);
            repolish(this);
            update();

        }else{
               qDebug()<<"clicked , change to normal hover: "<< _normal_hover;
            _curstate = ClickLbState::Normal;
            setProperty("state",_normal_press);
            repolish(this);
            update();
        }
        return;
    }
    // 调用基类的mousePressEvent以保证正常的事件处理
    QLabel::mousePressEvent(event);
}

抬起事件

void ClickedLabel::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        if(_curstate == ClickLbState::Normal){
             // qDebug()<<"ReleaseEvent , change to normal hover: "<< _normal_hover;
            setProperty("state",_normal_hover);
            repolish(this);
            update();

        }else{
             //  qDebug()<<"ReleaseEvent , change to select hover: "<< _selected_hover;
            setProperty("state",_selected_hover);
            repolish(this);
            update();
        }
        emit clicked();
        return;
    }
    // 调用基类的mousePressEvent以保证正常的事件处理
    QLabel::mousePressEvent(event);
}

qss美化

我们添加qss美化一下

LoadingDlg{
    background: #f2eada;
}

#title_lb{
    font-family: "Microsoft YaHei";
    font-size: 18px;
    font-weight: normal;
}

#chatEdit{
    background: #ffffff;
    border: none; /* 隐藏边框 */
    font-family: "Microsoft YaHei"; /* 设置字体 */
    font-size: 18px; /* 设置字体大小 */
    padding: 5px; /* 设置内边距 */
}

#send_wid{
    background: #ffffff;
    border: none; /* 隐藏边框 */
}

#add_btn[state='normal']{
    border-image: url(:/res/add_friend_normal.png);
}

#add_btn[state='hover']{
    border-image: url(:/res/add_friend_hover.png);

}

#add_btn[state='press']{
    border-image: url(:/res/add_friend_hover.png);
}

#receive_btn[state='normal']{
   background: #f0f0f0;
   color: #2cb46e;
   font-size: 16px; /* 设置字体大小 */
   font-family: "Microsoft YaHei"; /* 设置字体 */
   border-radius: 20px; /* 设置圆角 */
}

#receive_btn[state='hover']{
   background: #d2d2d2;
   color: #2cb46e;
   font-size: 16px; /* 设置字体大小 */
   font-family: "Microsoft YaHei"; /* 设置字体 */
   border-radius: 20px; /* 设置圆角 */
}

#receive_btn[state='press']{
   background: #c6c6c6;
   color: #2cb46e;
   font-size: 16px; /* 设置字体大小 */
   font-family: "Microsoft YaHei"; /* 设置字体 */
   border-radius: 20px; /* 设置圆角 */
}

#send_btn[state='normal']{
    background: #f0f0f0;
    color: #2cb46e;
    font-size: 16px; /* 设置字体大小 */
    font-family: "Microsoft YaHei"; /* 设置字体 */
    border-radius: 20px; /* 设置圆角 */
}

#send_btn[state='hover']{
   background: #d2d2d2;
   color: #2cb46e;
   font-size: 16px; /* 设置字体大小 */
   font-family: "Microsoft YaHei"; /* 设置字体 */
   border-radius: 20px; /* 设置圆角 */
}

#send_btn[state='press']{
   background: #c6c6c6;
   color: #2cb46e;
   font-size: 16px; /* 设置字体大小 */
   font-family: "Microsoft YaHei"; /* 设置字体 */
   border-radius: 20px; /* 设置圆角 */
}

#tool_wid{
    background: #ffffff;
    border-bottom: 0.5px solid #ececec; /* 设置下边框颜色和宽度 */
}

#emo_lb[state='normal']{
    border-image: url(:/res/smile.png);
}

#emo_lb[state='hover']{
    border-image: url(:/res/smile_hover.png);
}

#emo_lb[state='press']{
    border-image: url(:/res/smile_press.png);
}

#file_lb[state='normal']{
    border-image: url(:/res/filedir.png);
}

#file_lb[state='hover']{
    border-image: url(:/res/filedir_hover.png);
}

#file_lb[state='press']{
    border-image: url(:/res/filedir_press.png);
}

效果

最后整体运行一下看看效果, 下一节我们实现红框内的内容

https://cdn.llfc.club/1717645209118.jpg

视频链接

https://www.bilibili.com/video/BV13Z421W7WA/?spm_id_from=333.788&vd_source=8be9e83424c2ed2c9b2a3ed1d01385e9

源码链接

https://gitee.com/secondtonone1/llfcchat

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1807071.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

dockerhub不可用临时解决方案

近日&#xff0c;在拉取一些docker hub的镜像的时候死活拉不下来&#xff0c;要么超时&#xff0c;要么无法接站点地址&#xff0c;不管是docker hub,还是国内镜像站&#xff0c;统统都不行了。 经过各大媒体报道&#xff0c;以及自己的亲身验证&#xff0c;才知道&#xff0c…

[imx6ull]Linux下的SocketCAN通信

文章目录 一、CAN总线协议1.简介2.电气属性3.通信原理①数据帧的帧格式&#xff1a;②总线同步③总线竞争④数据保护 二、Linux下CAN的操作1.硬件连接①CAN电平转换器②扩展板使用CAN 2.查询 can 信息3.开启/关闭 can4.发送/接收 can 数据5.设置 can 参数 三、CAN的回环测试四、…

Spring之SpringMVC源码

SpringMVC源码 一、SpringMVC的基本结构 1.MVC简介 以前的纯Servlet的处理方式&#xff1a; Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String type req.getParameter(Constant.REQUEST_PA…

Autodesk 3ds Max软件下载安装;3ds Max功能强大的三维建模、渲染软件安装包获取

3ds Max&#xff0c;无论是初学者还是资深设计师&#xff0c;都能通过3ds Max在数字世界中实现自己的创意&#xff0c;打造出令人惊叹的三维作品。 在3ds Max中&#xff0c;灯光系统是至关重要的一环。它提供了光度学灯光和标准灯光两种主要类型&#xff0c;用于照亮和增强场景…

预备知识----技术架构演进之路

单机架构 简介&#xff1a;应用服务和数据库服务共用一台服务器。 出现原因&#xff1a;出现在互联网早期&#xff0c;访问量较小&#xff0c;单机足以满足需求。 架构工作原理&#xff1a;通过应用&#xff08;划分了多个模块&#xff09;和数据库在单个服务器上写作完成业务…

Liunx环境下redis主从集群搭建(保姆级教学)01

Linux 环境安装redis 准备一台linux虚拟机 我使用基于Linux的开源类服务器操作系统CentOS7。 打开虚拟机&#xff0c;输入密码登录 下载linux版本的redis安装包 已经下载redis-5.0.10.tar.gz 创建一个文件夹用来安装redis,我在/opt目录下创建redis文件夹 将下载好的redis…

前端_调试工具_Chrome Devtools

目录 一、上左侧菜单功能 1.选择功能 2.手机/电脑 显示切换功能 3.内存 4.元素 5.控制台 6.源代码/来源 7.网络 8.应用 9.性能 10.安全 11.Lighthouse 12.记录器 13.性能数据分析 二、上右侧菜单功能 1.警告 2.设置 3....更多功能 谷歌浏览器自带了调试工具C…

AE电源pinnacle软件新款老款二款软件

AE电源pinnacle软件新款老款二款软件

数据中心运维管理方案

数据中心运维管理方案 随着数据中心在现代信息社会中的重要性日益增加&#xff0c;高效、可靠的运维管理方案成为保障其稳定运行的关键。本文将探讨数据中心运维管理的策略和实践&#xff0c;旨在为运维团队提供全面、系统的管理方法&#xff0c;确保数据中心在任何情况下都能…

(文章复现)低温环境下考虑电池寿命的微电网优化调度

参考文献&#xff1a; [1]丁佳昀,胡秦然,吴在军,等.低温环境下考虑电池寿命的微电网优化调度[J].中国电机工程学报,2024,44(10):3815-3824. 1.摘要 储能系统作为微电网重要组成部分&#xff0c;为微电网协调能量供需提供了解决方案。然而&#xff0c;在低温环境下&#xff0c…

抽象类接口(超详细)

抽象类&接口(超详细) 一:抽象类和抽象方法 封装:对象代表什么,就得封装对应的数据,并提供数据对应的行为 如果老师的work是教书,学生的work是学习。以前我们是在父类里面写一个work随便写一个方法体,然后子类重写。但是有一个弊端,如果子类不是你写的,是别人写…

嵌入式仪器模块:波形发生器模块(嵌入式)

• 16 位分辨率 • 125 MHz 刷新率 • 支持生成 FSK/ASK 信号 应用场景 • 生成任意标准波形或用户自定义波形 • 在特殊协议通信中模拟某个波形 • 无线充电&#xff08;信号调制&#xff09; 道114输出阻抗Low-ZLow-ZLow-Z输出范围 5 V 5 V 6 V耦合DCDCDC带宽4 MHz10 M…

第一个SpringBoot项目

目录 &#x1f4ad;1、新建New Project IDEA2023版本创建Sping项目只能勾选17和21&#xff0c;却无法使用Java8&#xff1f;&#x1f31f; 2、下载JDK 17&#x1f31f; &#x1f4ad;2、项目创建成功界面 1、目录 &#x1f31f; 2、pom文件&#x1f31f; &#x1f4ad;3、…

C#操作MySQL从入门到精通(20)——更新数据

前言: 谈到数据库,大家最容易脱口而出的就是增删改查,本文所说的更新数据就是增删改查的改,改变数据的意思。 本文测试使用的数据库如下: 1、更新一列 所谓更新一列的意思就是只更改一列数据,并且通常要使用where条件,因为不加这个条件的话会导致将所有行的数据进行…

LeetCode:环形链表II

文章收录于LeetCode专栏 LeetCode地址 环形链表II 题目 给定一个链表&#xff0c;返回链表开始入环的第一个节点。如果链表无环&#xff0c;则返回null。   为了表示给定链表中的环&#xff0c;我们使用整数pos来表示链表尾连接到链表中的位置&#xff08;索引从0开始&#…

vue3中进度条上加高亮圆点

实现效果 小圆点基于进度条定位&#xff08;left&#xff09;。 实现代码 <template><!-- 这块代码实现的功能&#xff1a;progressData遍历的年份进度数组&#xff0c;展示每年完成的进度--><ul><li v-for"(item, index) in progressData" :k…

LabVIEW 反向工程的实现与法律地位

什么是LabVIEW反向工程&#xff1f; 反向工程是指从现有的应用程序或软件中推导出其设计、架构、代码等信息的过程。对于LabVIEW而言&#xff0c;反向工程涉及从现有的VI&#xff08;虚拟仪器&#xff09;文件、项目或应用程序中提取出设计思路、功能模块、算法实现等。 LabV…

轻松上手MYSQL:SQL优化之Explain详解

​​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL应用》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 文章目录 一、Explain1.1 explain作用1.2 explain列说明idselect_typetableparti…

Linux|如何安装 Java

引言 Java是最受欢迎的编程语言之一&#xff0c;JVM&#xff08;Java的虚拟机&#xff09;是运行Java应用程序的运行时环境。这两个平台是许多流行软件所需的&#xff0c;包括Tomcat&#xff0c;Jetty&#xff0c;Cassandra&#xff0c;Glassfish和Jenkins。 本教程[1]将指导您…

关闭Cloudflare Pages的访问策略

curl API 获取相应的 uid curl -X GET "https://api.cloudflare.com/client/v4/accounts/账户标识符/access/apps" \-H "X-Auth-Email: 邮箱" \-H "X-Auth-Key: Global API KEY" \-H "Content-Type: application/json"账户标识符是登…