Qt模仿QQ聊天窗口界面(一)

Qt模仿QQ聊天窗口界面(一)

    • Qt模仿QQ聊天窗口界面(一)
      • 简述
      • 效果图
        • QQ的聊天窗口
        • 我做的效果图
      • 代码篇
        • 结尾

简述

最近利用业余时间,模仿QQ做了一个聊天窗口界面,功能还不全,准备分几个部分做出来,还是看空闲时间了,以及广大网友的支持了。

效果图

QQ的聊天窗口

这里写图片描述

我做的效果图

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

代码篇

//TalkWindowShell.cpp
TalkWindowShell::TalkWindowShell(QWidget *parent): BasicWindow(parent)
{ui.setupUi(this);initControl();{TalkWindow* talkwindow1 = new TalkWindow(this);TalkWindowItem* talkwindowItem1 = new TalkWindowItem(talkwindow1);talkwindow1->setWindowName(QStringLiteral("雨田哥-工作号-1号"));talkwindowItem1->setMsgLabelContent(QStringLiteral("雨田哥-1号"));talkwindow1->setWindowSignName(QStringLiteral("欢迎吐槽、雨田哥-工作号-1号"));addTalkWindow(talkwindow1, talkwindowItem1);}{TalkWindow* talkwindow2 = new TalkWindow(this);TalkWindowItem* talkwindowItem2 = new TalkWindowItem(talkwindow2);talkwindow2->setWindowName(QStringLiteral("雨田哥-工作号-2号-2号"));talkwindowItem2->setMsgLabelContent(QStringLiteral("雨田哥-2号"));talkwindow2->setWindowSignName(QStringLiteral("欢迎吐槽、雨田哥-工作号-2号-2号"));addTalkWindow(talkwindow2, talkwindowItem2);}{TalkWindow* talkwindow3 = new TalkWindow(this);TalkWindowItem* talkwindowItem3 = new TalkWindowItem(talkwindow3);talkwindow3->setWindowName(QStringLiteral("雨田哥-工作号-3号-3号-3号"));talkwindowItem3->setMsgLabelContent(QStringLiteral("雨田哥-3号"));talkwindow3->setWindowSignName(QStringLiteral("欢迎吐槽、雨田哥-工作号-3号-3号-3号"));addTalkWindow(talkwindow3, talkwindowItem3);}
}TalkWindowShell::~TalkWindowShell()
{delete m_emotionWindow;m_emotionWindow = nullptr;
}void TalkWindowShell::initControl()
{loadStyleSheet("TalkWindow");m_emotionWindow = new EmotionWindow;m_emotionWindow->hide();QList<int> leftWidgetSize;leftWidgetSize << 154 << width() - 154;ui.splitter->setSizes(leftWidgetSize);ui.listWidget->setStyle(new CustomProxyStyle(this));connect(ui.listWidget, &QListWidget::itemClicked, this, &TalkWindowShell::onTalkWindowItemClicked);connect(m_emotionWindow, SIGNAL(signalEmotionItemClicked(int)), this, SLOT(onEmotionItemClicked(int)));
}void TalkWindowShell::onEmotionBtnClicked(bool)
{m_emotionWindow->setVisible(!m_emotionWindow->isVisible());QPoint emotionPoint = this->mapToGlobal(QPoint(0, 0));emotionPoint.setX(emotionPoint.x() + 170);emotionPoint.setY(emotionPoint.y() + 220);m_emotionWindow->move(emotionPoint);
}void TalkWindowShell::onTalkWindowItemClicked(QListWidgetItem *item)
{QWidget* talkwindowWidget = m_talkwindowItemMap.find(item).value();ui.rightStackedWidget->setCurrentWidget(talkwindowWidget);
}void TalkWindowShell::addTalkWindow(TalkWindow* talkwindow, TalkWindowItem* talkwindowitem)
{ui.rightStackedWidget->addWidget(talkwindow);connect(m_emotionWindow, SIGNAL(signalEmotionWindowHide()), talkwindow, SLOT(onSetEmotionBtnStatus()));QListWidgetItem *aItem = new QListWidgetItem(ui.listWidget);m_talkwindowItemMap.insert(aItem, talkwindow);aItem->setSelected(true);talkwindowitem->setHeadPixmap("");ui.listWidget->addItem(aItem);ui.listWidget->setItemWidget(aItem, talkwindowitem);onTalkWindowItemClicked(aItem);connect(talkwindowitem, &TalkWindowItem::signalCloseClicked, [talkwindowitem, talkwindow, aItem, this](){m_talkwindowItemMap.remove(aItem);talkwindow->close();ui.listWidget->takeItem(ui.listWidget->row(aItem));delete talkwindowitem;ui.rightStackedWidget->removeWidget(talkwindow);if (ui.rightStackedWidget->count() < 1)close();});
}void TalkWindowShell::onEmotionItemClicked(int emotionNum)
{TalkWindow* curTalkWindow = dynamic_cast<TalkWindow*>(ui.rightStackedWidget->currentWidget());if (curTalkWindow){curTalkWindow->addEmotionImage(emotionNum);}
}
TalkWindow.cpp
TalkWindow::TalkWindow(QWidget *parent): QWidget(parent)
{setAttribute(Qt::WA_DeleteOnClose);ui.setupUi(this);initControl();
}TalkWindow::~TalkWindow()
{}void TalkWindow::initControl()
{setSendBtnMenu();QList<int> rightWidgetSize;rightWidgetSize << 600 << 138;ui.bodySpliter->setSizes(rightWidgetSize);connect(ui.sysmin, SIGNAL(clicked(bool)), parent(), SLOT(onShowMin(bool)));connect(ui.sysclose, SIGNAL(clicked(bool)), parent(), SLOT(onShowClose(bool)));connect(ui.closeBtn, SIGNAL(clicked(bool)), parent(), SLOT(onShowClose(bool)));connect(ui.faceBtn, SIGNAL(clicked(bool)), parent(), SLOT(onEmotionBtnClicked(bool)));connect(ui.sendBtn, SIGNAL(clicked(bool)), this, SLOT(onSendBtnClicked(bool)));ui.msgWidget->setShowSkinControl(ui.skinLabel);
}void TalkWindow::onSetEmotionBtnStatus()
{ui.faceBtn->setChecked(false);
}void TalkWindow::setWindowName(const QString& name)
{ui.nameLabel->setText(name);
}void TalkWindow::setWindowSignName(const QString& name)
{ui.signLabel->setText(name);
}void TalkWindow::onSignalWindowclosed()
{close();
}void TalkWindow::onSendBtnClicked(bool)
{ui.textEdit->clear();ui.textEdit->delteAllEmotionImage();MsgWidgetItem* msgItem = new MsgWidgetItem(this);int count = ui.msgLayout->count();ui.msgLayout->insertWidget(count - 1, msgItem);
}void TalkWindow::addEmotionImage(int emotionNum)
{ui.textEdit->setFocus();ui.textEdit->addEmotionUrl(emotionNum);
}void TalkWindow::setSendBtnMenu()
{QMenu* menu = new QMenu(this);menu->setWindowFlags(menu->windowFlags() | Qt::FramelessWindowHint);menu->setAttribute(Qt::WA_TranslucentBackground);menu->setObjectName("senMenu");m_sendAction = menu->addAction(QStringLiteral("按Enter键,发送消息"), this, SLOT(onEnterAction()));m_ctrlSendAction = menu->addAction(QStringLiteral("按Enter+Ctrl键,发送消息"), this, SLOT(onEnterCtrlAction()));QActionGroup* actiongroup = new QActionGroup(this);m_sendAction->setCheckable(true);m_ctrlSendAction->setCheckable(true);m_sendAction->setChecked(true);actiongroup->addAction(m_sendAction);actiongroup->addAction(m_ctrlSendAction);ui.sendBtn->setMenu(menu);
}void TalkWindow::onEnterAction()
{m_sendAction->setChecked(true);}void TalkWindow::onEnterCtrlAction()
{m_ctrlSendAction->setChecked(true);
}
EmotionWindow.cpp
const int emotionColumn = 14;
const int emotionRow = std::ceil(170 / 14);EmotionWindow::EmotionWindow(QWidget *parent): QWidget(parent)
{setWindowFlags(Qt::FramelessWindowHint | Qt::SubWindow);setAttribute(Qt::WA_TranslucentBackground);setAttribute(Qt::WA_DeleteOnClose);ui.setupUi(this);initControl();
}EmotionWindow::~EmotionWindow()
{}void EmotionWindow::initControl()
{CommonUtils::loadStyleSheet(this, "EmotionWindow");for (int row = 0; row < emotionRow; row++){for (int column = 0; column < emotionColumn; column++){EmotionLabelItem* label = new EmotionLabelItem(this);label->setEmotionName(row * emotionColumn + column);connect(label, &EmotionLabelItem::emotionClicked, this, &EmotionWindow::addEmotion);ui.gridLayout->addWidget(label, row, column);}}
}void EmotionWindow::addEmotion(int emotionNum)
{hide();emit signalEmotionWindowHide();emit signalEmotionItemClicked(emotionNum);
}void EmotionWindow::paintEvent(QPaintEvent *event)
{QStyleOption opt;opt.init(this);QPainter p(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);__super::paintEvent(event);
}void EmotionWindow::showEvent(QShowEvent *event)
{setFocus();__super::showEvent(event);
}void EmotionWindow::focusOutEvent(QFocusEvent *event)
{QWidget* widget = qApp->widgetAt(QCursor::pos());if (widget != this && widget != ui.emotionWidget && widget != ui.topWidget){hide();emit signalEmotionWindowHide();}__super::focusOutEvent(event);
}
//QMsgTextEdit.cpp
QMsgTextEdit::QMsgTextEdit(QWidget *parent): QTextEdit(parent)
{}QMsgTextEdit::~QMsgTextEdit()
{delteAllEmotionImage();
}void QMsgTextEdit::delteAllEmotionImage()
{for (auto itor = m_emotionMap.constBegin(); itor != m_emotionMap.constEnd(); ++itor){delete itor.key();}m_emotionMap.clear();
}void QMsgTextEdit::addEmotionUrl(int emotionNum)
{const QString&& imageName = QString(":/TalkWindowShell/Resources/emotion/%1.png").arg(emotionNum);const QString&& flagName = QString("apng-%1-apng").arg(imageName);insertHtml(QString("<img src='%1'/>").arg(flagName));if (m_listEmotionUrl.contains(imageName))return;elsem_listEmotionUrl.append(imageName);QMovie* apngMovie = new QMovie(imageName, "apng", this);apngMovie->setCacheMode(QMovie::CacheNone);m_emotionMap.insert(apngMovie, flagName);connect(apngMovie, SIGNAL(frameChanged(int)), this, SLOT(onEmotionImageFrameChange(int)));apngMovie->start();
}void QMsgTextEdit::onEmotionImageFrameChange(int frame)
{QMovie* movie = qobject_cast<QMovie*>(sender());document()->addResource(QTextDocument::ImageResource, QUrl(m_emotionMap.value(movie)), movie->currentPixmap());setLineWrapColumnOrWidth(lineWrapColumnOrWidth());
}

结尾

其实,看代码篇,有点繁琐,因权限问题,我不能将工程文件上传,需要的,可以加我QQ。需要的可以加我QQ:3246214072。今天我只是先上传已做好的部分,后面看情况,会不断的完善这个聊天窗口界面。感谢广大网友的多多支持~

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS 类似微信,QQ聊天界面的气泡聊天简单实现Demo

以下是YYKit组件的源码分析&#xff0c;高级性能优化相关都在里面可以找到 YYwebImage超细源码分析YYImage超细源码分析YYModel源码分析YYText源码分析 12.27日更新&#xff1a;分析了一个很牛B的聊天UI框架 进阶版高级UI实现 帅气的我又来了&#xff0c;是不是帅气逼人。。。…

QT 登录界面 主界面 切换 仿TIM

QT 登录界面 主界面 切换 一 环境搭建 平台是vs2012 Qt5.2.1 属于QWidget窗口 在项目里又添加了QMainwindow窗口 二 编写代码 QWidget的窗口名是loginwindow&#xff0c;QMainwindow的窗口名是mainwidow&#xff08;发现window少打一个n 尴尬&#xff09; loginw…

环信聊天列表不刷新数据

还原问题&#xff1a; 如图主Ui是activity&#xff0c;下侧的围观区是Fragment,根据环信的demo&#xff0c;上面聊天区可以正常刷新UI。 但是围观区数据源变化&#xff0c;但是不能刷新UI。 思路&#xff1a; 研究一个下午&#xff0c;理了好久逻辑。发现我的问题是&#x…

环信实现聊天功能

目录 1、即时通信1.1 什么是即时通信&#xff1f;1.2 功能说明 2 技术方案3 环信3.1 开发简介3.2 环信Console 4 用户体系集成4.1 Appkey 数据结构4.2 环信 ID 数据结构4.3 环信 ID 使用规则4.4 获取管理员权限4.4.1 配置4.4.2 获取token4.5 注册环信用户4.6 测试4.7 查询环信用…

Android泡泡聊天界面的实现

昨天写了个界面&#xff0c;实现了Android泡泡聊天界面。运行结果如下&#xff0c;点击发送按钮&#xff0c;屏幕就显示Text的内容。 我也是在网上的一份源码的基础上更改的&#xff0c;整个泡泡界面的实现要点&#xff1a; &#xff08;1&#xff09;主界面其实就是一个List V…

【开源免费】使用Spring Boot和Html实现ChatGPT,1:亿还原,将就看。

简介 关注我&#xff1a;GPT4.0 JAVA SDK近期更新 前段时间写了一个Chatgpt的Java版SDK开源地址&#xff1a;chatgpt-java欢迎使用。但由于原来OpenAI 并没有支持官网的chatgpt模型&#xff0c;所以使用起来相对没有官网那么智能完善&#xff0c;所以就没有写出一个demo项目&a…

Fdog系列(五):使用Qt模仿QQ实现登录界面到主界面,功能篇。

文章目录 一. 前言同时完整项目代码已上传github&#xff1a;[Fdog即时通讯软件](https://github.com/HuaGouFdog/FdogInstantMessaging) 求星星&#xff01;二. 正文1. 如何保存第一次登录数据2. 如何获取已经登录过的账号信息,并完成自定义下列框3. 从下拉列表框删除账号4. 文…

可换皮肤的Qt登录界面

⭐️我叫忆_恒心,一名喜欢书写博客的在读研究生👨‍🎓。 如果觉得本文能帮到您,麻烦点个赞👍呗! 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧,喜欢的小伙伴给个三连支持一下呗。👍⭐️❤️ 可换皮肤的Qt登录界面 QSS的学习笔记 快…

chatgpt赋能python:Python如何去除停用词

Python 如何去除停用词 介绍 在进行自然语言处理时&#xff0c;停用词是常见的障碍。停用词是指在文本中频繁出现但没有实际意义的词语。例如&#xff0c;“the”、“is”、“a” 等单词通常被认为是停用词&#xff0c;因为它们在具有意义的文本中出现得非常频繁&#xff0c;…

使用关联规则分析股票数据--数据来自tushare大数据社区

使用关联规则分析股票数据--数据来自tushare大数据社区 一、开发环境二、目标三、关联规则&#xff08;之前了解过直接跳到第四步&#xff09;1.关联规则的定义2.啤酒尿布的例子2.1 支持度2.2置信度2.3 提升度2.4 关联规则2.5 啤酒和尿布 四、股票关联规则分析1.使用的库2.获取…

Twitter部分源代码泄漏、疑遭离职员工报复:马斯克要求GitHub交出所有上传、下载人员名单...

点击“开发者技术前线”&#xff0c;选择“星标” 让一部分开发者看到未来 作者 &#xff5c; Tina 来自&#xff1a;AI前线 最近的法律文件显示&#xff0c;Twitter 的部分源代码已经在网上泄露。这是一次罕见的、严重的知识产权泄露事件。为防止该事件对其服务产生潜在的破坏…

马斯克刚说要开源,没几天Twitter源代码就泄漏了...

出品 | OSC开源社区&#xff08;ID&#xff1a;oschina2013) 根据《纽约时报》的报道&#xff0c;一份法律文件显示&#xff0c;Twitter 称其部分源代码在网上被泄露&#xff0c;该公司已于上周五采取行动&#xff0c;它通过向托管代码的 GitHub 发送版权侵权通知&#xff0c;删…

文心一言员工跳槽工资翻倍, AI 人才备受追捧;推特称其部分源代码遭泄露;Docker 撤回受争议的收费方案|极客头条...

「极客头条」—— 技术人员的新闻圈&#xff01; CSDN 的读者朋友们早上好哇&#xff0c;「极客头条」来啦&#xff0c;快来看今天都有哪些值得我们技术人关注的重要新闻吧。 整理 | 梦依丹 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 一分钟速览新闻点&#…

有道智云翻译API + retrofit实现在线翻译Android app

目录 1.进入有道智云主页&#xff0c;注册自己的账号(手机号验证码)&#xff0c;完善信息随意填 2.登录进来后&#xff0c;创建应用。根据需要选择语言翻译服务。 3. 打开Android Studio&#xff0c;新建空的Activity项目 1. 新建项目&#xff0c;在build.gradle(app)添加re…

STRAIGHT声码器详解

转载请注明出处。 STRAIGHT自适应加权谱内插的语音转换与重构 STRAIGHT&#xff08; Speech Transformation and Representation using Adaptive Interpolation of weighted spectrum)算法&#xff08;Kawahara,1998&#xff09;&#xff0c;是一种语音信号分析、合成、修改的…

chatgpt赋能python:如何用Python挣钱:从小白到大佬的必备指南

如何用Python挣钱&#xff1a;从小白到大佬的必备指南 作为一名有10年Python编程经验的工程师&#xff0c;我深知Python的应用范围非常广泛&#xff0c;它可以为各种行业带来巨大的价值。当然&#xff0c;对于许多人来说&#xff0c;如果你是一名SEO从业者&#xff0c;也完全可…

chatgpt赋能python:如何利用Python在网上赚钱:一份SEO指南

如何利用Python在网上赚钱&#xff1a;一份SEO指南 随着互联网的快速发展和Python成为一种越来越受欢迎的编程语言&#xff0c;越来越多的人开始利用Python在网上赚取额外的收入。本篇文章将介绍一些Python工具和技术&#xff0c;以及SEO最佳实践&#xff0c;帮助你利用Python…

PHP短信验证功能

PHP阿里大鱼短信验证 第一步 登陆阿里大于注册账号&#xff0c;在用户管理中心创建应用&#xff0c;确定AppKEY和App Secret还有配置签名 第二步 在应用管理中选择SDK下载&#xff0c;或者直接点击http://download.csdn.net/detail/s371795639/9695983下载&#xff0c;免费的…

发送短信验证码 API数据接口

1.前言 此接口发送短信验证码 短信模板 参数说明: 1449978 验证码为&#xff1a;{1}为您的登录验证码&#xff0c;请于{2}分钟内填写&#xff0c;如非本人操作&#xff0c;请忽略本短信。 1449979 验证码为&#xff1a;{1}&#xff0c;您正在登录&#xff0c;若非本人操作&…

为何语言学家乔姆斯基对ChatGPT持否定态度?

本文比较了乔姆斯基关于语言知识的本质、来源和使用的理论与 GPT 的不同&#xff0c; 说明了GPT没有可解释性。 2023年3月8日著名语言学家乔姆斯基与罗伯茨&#xff08;Ian Roberts&#xff09;、瓦图穆尔&#xff08;Jeffrey Watmull&#xff09;共同在《纽约时报》发表了题为…