[项目:微服务即时通讯系统客户端(基于C++QT)]三,左侧界面搭建

三,左侧界面搭建

一,导入

先把MainWidget类做成“单例类”

采用的是单例模式,让某一个类,在指定进程中只有唯一的实例

先看一下MainWidget的框架

QWidget//这部分是头文件保护宏,确保该头文件只被包含一次,防止因重复包含导致的编译错误。
#ifndef MAINWIDGET_H
#define MAINWIDGET_H//引入 Qt 的 QWidget 类,这个类是所有用户界面对象的基类。
#include <QWidget>//这段代码使用 Qt 的命名空间机制。
//它定义了一个名为 Ui 的命名空间,里面声明了一个名为 mainWidget 的类。
//这个类通常是通过 Qt Designer 生成的,用于管理 UI 元素。
QT_BEGIN_NAMESPACE
namespace Ui {
class mainWidget;
}
QT_END_NAMESPACE//这里定义了一个名为 mainWidget 的类,它继承自 QWidget。Q_OBJECT
class mainWidget : public QWidget
{Q_OBJECTpublic:mainWidget(QWidget *parent = nullptr);~mainWidget();private:Ui::mainWidget *ui;
};
#endif // MAINWIDGET_H
//包含了之前定义的 mainWidget 类的头文件。
#include "mainwidget.h"
//包含了由 Qt Designer 生成的 UI 代码的头文件,通常负责设置 UI 元素。
#include "./ui_mainwidget.h"//这行代码定义了一个静态指针成员变量 instance,初始化为 nullptr。这通常用于实现单例模式,确保 mainWidget 类只有一个实例
mainWidget* mainWidget::instance=nullptr;//构造函数,接受一个可选的父窗口部件指针
mainWidget::mainWidget(QWidget *parent): QWidget(parent)        //调用基类 QWidget 的构造函数,并将父部件传递给它, ui(new Ui::mainWidget) //创建一个新的 Ui::mainWidget 对象,负责设置 UI。
{ui->setupUi(this);       //调用 setupUi 方法,将 UI 组件设置到当前 mainWidget 实例中
}//析构函数
mainWidget::~mainWidget()
{delete ui;
}

二,需求分析

53f9dff501159a97d4c122149e72b38.png

三,代码书写

前置:设置图标,需要把图标图片,导入到项目中,通过qrc文件进行管理

在本章节大致使用了一下素材

素材网站:

https://www.aigei.com/

https://www.iconfont.cn/

userAvatar.jpeglogo.png

apply_active.pngapply_inactive.pngfriend_active.pngfriend_inactive.pngsession_active.pngsession_inactive.png

一,mainWidget.h的编写

#ifndef MAINWIDGET_H
#define MAINWIDGET_H#include <QWidget>
#include <QPushButton>QT_BEGIN_NAMESPACE
namespace Ui {
class mainWidget;
}
QT_END_NAMESPACEclass mainWidget : public QWidget
{Q_OBJECTprivate:static mainWidget* instance;//指针指向当前的类的唯一实例//静态指针,用于指向 mainWidget 类的唯一实例//这是单例模式的核心,确保全局只存在一个 mainWidget 对象//对于单例模式来说,最关键的部分,不是创建实例,而是限制别人创建实例mainWidget(QWidget *parent = nullptr);//他是私有的防止外部代码直接创建mainWidget实例public:static mainWidget*  getInstance();//静态成员函数用于获取当前实例~mainWidget();//析构函数private:Ui::mainWidget *ui;//窗口最左侧部分QWidget* windowLeft;//窗口中间部分QWidget* windowMid;//窗口右侧部分QWidget* windowRight;//用户头像QPushButton* userAvatar;//会话标签页按钮QPushButton* sessionTabBtn;//好友标签页按钮QPushButton* friendTabBtn;//好友申请标签页按钮QPushButton* applyTabBtn;//枚举类型当前的激活的标签页是哪一个enum ActiveTab{SESSION_LIST,FRIEND_LIST,APPLY_LIST};ActiveTab activeTab=SESSION_LIST;//默认为会话列表//初始化主窗口的样式布局void initMainWindow();//初始化左侧窗口布局void initLeftWindow();//初始化中间窗口布局void initMidWindow();//初始化右侧窗口布局void initRightWindow();//信号槽void initSignalSlot();//槽函数void switchTabToSession();void switchTabToFriend();void switchTabToApply();void loadSessionList();void loadFriendList();void loadApplyList();
};
#endif // MAINWIDGET_H

本头文件采用了单例模式

单例模式(Singleton Pattern)是一种设计模式,它确保一个类在程序运行期间只会创建一个实例,并且提供一个全局访问点。

到底此处的代码怎么实现的单例模式呢?

  1. 私有构造函数

  2. 静态实例指针static mainWidget* instance;

  3. 静态访问接口static mainWidget* getInstance();

回顾静态成员的特点
  • 静态成员变量:属于类本身,而不是某个对象。所有类的实例共享同一个静态成员变量,它在程序运行时只会分配一块内存空间。

  • 静态成员函数:同样属于类,而不是对象。它只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数(因为非静态成员是属于具体对象的)。

单例模式ABC详解

A.构造函数是私有的mainWidget(QWidget *parent = nullptr);

防止外部代码直接创建mainWidget实例

B.**static** 修饰的 **instance** 是一个静态成员变量,它属于 **mainWidget** 类本身,而不是某个特定的 mainWidget 对象.

程序整个周期只存在一份,所有访问mainWidget类的都共享一个instance指针,初始值为nullptr的时候说明还没有创建。

静态成员变量 instance 可以在 mainWidget 类的任何成员函数中访问,也可以通过 getInstance() 方法从类的外部访问。

C.提供对单例实例的访问

mainWidget* mainWidget::getInstance()
{//此处不传入参数,以桌面为父窗口//由于此时的窗口是整个程序的主窗口,父窗口就设定为桌面,本身就是常规设定。if(instance==nullptr){instance=new mainWidget();}return instance;
}

第一次调用 getInstance() 时,创建一个新的实例

第二次以后调用,直接返回instance实例;

二,逐步编写mainwidget.cpp

一,构造函数

mainWidget::mainWidget(QWidget *parent): QWidget(parent), ui(new Ui::mainWidget)
{ui->setupUi(this);//this指向被构造的mainWidgetthis->setWindowTitle("Pokemon聊天室");this->setWindowIcon(QIcon(":/resource/image/logo.png"));//初始化主窗口的样式布局initMainWindow();//初始化左侧窗口布局initLeftWindow();//初始化中间窗口布局initMidWindow();//初始化右侧窗口布局initRightWindow();//初始化信号槽initSignalSlot();
}

二,initMainWindow初始化主窗口

void mainWidget::initMainWindow()
{//创建一个水平布局管理器QHBoxLayout* layout=new QHBoxLayout();//处理间隔Spacing就是layout内部元素之间的间隔距离,设置为0就是紧紧挨着水平的紧紧挨着layout->setSpacing(0);this->setLayout(layout);//将 layout 设置为 mainWidget 窗口的布局管理器//创建三个QWidget子部件windowLeft=new QWidget();windowMid=new QWidget();windowRight=new QWidget();//这三个部分马上添加到布局管理器中//在设计界面的时候,会涉及到很多尺寸,间距,边框,字体相关细节。windowLeft->setFixedWidth(60);//左侧导航栏为固定的70像素windowMid->setFixedWidth(230);//中间windowRight->setMinimumWidth(500);//右边聊天框 根据窗口自动化改变//可以使用qq的截图来进行判定大小//设计颜色qsswindowLeft->setStyleSheet("QWidget {background-color:rgb(23,23,23)}");//左侧导航栏为固定的70像素windowMid->setStyleSheet("QWidget {background-color:rgb(46,46,46)}");windowRight->setStyleSheet("QWidget {background-color:rgb(255,255,255)}");//子窗口添加到布局管理器中layout->addWidget(windowLeft);layout->addWidget(windowMid);layout->addWidget(windowRight);}

image.png

三,initLeftWindow()

//H 代表 Horizontal(水平),V 代表 Vertical(垂直)
void mainWidget::initLeftWindow()
{QVBoxLayout* layout =new QVBoxLayout();layout->setSpacing(20);//设置按钮的间距layout->setContentsMargins(0,70,0,0);//设置左上右下的间距windowLeft->setLayout(layout);//添加用户头像userAvatar =new QPushButton();userAvatar->setFixedSize(45,45);//按钮本身的尺寸userAvatar->setIconSize(QSize(45,45));//按钮自身的尺寸userAvatar->setIcon(QIcon(":/resource/image/userAvatar.jpg"));userAvatar->setStyleSheet("QPushButton{ background-color:transparent;}");layout->addWidget(userAvatar,1,Qt::AlignTop |   Qt::AlignCenter);//1是占据空间的权重,靠上对齐,水平居中layout->addStretch(5);//添加空白处//添加会话标签按钮sessionTabBtn=new QPushButton();sessionTabBtn->setFixedSize(45,45);//按钮本身的尺寸sessionTabBtn->setIconSize(QSize(45,45));//按钮自身的尺寸sessionTabBtn->setIcon(QIcon(":/resource/image/session_active.png"));sessionTabBtn->setStyleSheet("QPushButton{ background-color:transparent;}");layout->addWidget(sessionTabBtn,1,Qt::AlignTop |   Qt::AlignCenter);//添加好友标签页按钮friendTabBtn=new QPushButton();friendTabBtn->setFixedSize(45,45);//按钮本身的尺寸friendTabBtn->setIconSize(QSize(45,45));//按钮自身的尺寸friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));friendTabBtn->setStyleSheet("QPushButton{ background-color:transparent;}");layout->addWidget(friendTabBtn,1,Qt::AlignTop |   Qt::AlignCenter);//添加好友申请标签页按钮applyTabBtn=new QPushButton();applyTabBtn->setFixedSize(45,45);//按钮本身的尺寸applyTabBtn->setIconSize(QSize(45,45));//按钮自身的尺寸applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));applyTabBtn->setStyleSheet("QPushButton{ background-color:transparent;}");layout->addWidget(applyTabBtn,1,Qt::AlignTop |   Qt::AlignCenter);;layout->addStretch(20);//添加下面的空白处//连接信号槽,处理标签页按钮切换的问题
}

四,initSignalSlot()

void mainWidget::initSignalSlot()
{////连接信号槽,处理标签页按钮切换的问题/connect(sessionTabBtn,&QPushButton::clicked,this,&mainWidget::switchTabToSession);//连接的信号来自sessionTabBtn这个指向 QPushButton 对象的指针//&QPushButton::clicked 表示 QPushButton 类中的 clicked 信号,clicked 信号在 QPushButton 被点击时触发//槽(slot)函数所属对象的指针,指的是 mainWidget 类的一个实例对象,槽函数是在当前对象(即 mainWidget 类的实例)中定义的//最后一个位置是槽函数:每当 sessionTabBtn 发出 clicked 信号时,这个槽函数就会被调用connect(friendTabBtn,&QPushButton::clicked,this,&mainWidget::switchTabToFriend);connect(applyTabBtn,&QPushButton::clicked,this,&mainWidget::switchTabToApply);}

addWidget的参数中1的作用

拉伸系数的作用:它决定了当布局空间发生变化(如窗口大小改变时),该部件在布局中占据的比例。如果拉伸系数为 1,那么它在布局中将获得与其他拉伸系数为 1 的部件相同的空间份额。如果拉伸系数为 0,则该部件的大小不会随布局的空间变化而变化(即固定大小)

五,槽函数

void mainWidget::switchTabToSession()
{//1.记录当前切换到了哪一个标签页activeTab=SESSION_LIST;//2.调整当前图片显示情况,把会话的按钮图标设为active,另两个图标设为inactivesessionTabBtn->setIcon(QIcon(":/resource/image/session_active.png"));friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));//3.在主窗口中间部分,加载会话列表数据this->loadSessionList();
}
void mainWidget::switchTabToFriend()
{//1.记录当前切换到了哪一个标签页activeTab=FRIEND_LIST;//2.调整当前图片显示情况,把会话的按钮图标设为active,另两个图标设为inactivesessionTabBtn->setIcon(QIcon(":/resource/image/session_inactive.png"));friendTabBtn->setIcon(QIcon(":/resource/image/friend_active.png"));applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));//3.在主窗口中间部分,加载会话列表数据this->loadFriendList();
}
void mainWidget::switchTabToApply()
{//1.记录当前切换到了哪一个标签页activeTab=APPLY_LIST;//2.调整当前图片显示情况,把会话的按钮图标设为active,另两个图标设为inactivesessionTabBtn->setIcon(QIcon(":/resource/image/session_inactive.png"));friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));applyTabBtn->setIcon(QIcon(":/resource/image/apply_active.png"));//3.在主窗口中间部分,加载会话列表数据this->loadApplyList();
}

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

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

相关文章

NSSCTF刷题篇1

js类型 [SWPUCTF 2022 新生赛]js_sign 这是一道js信息泄露的题目直接查看源码&#xff0c;有一个main.js文件点击之后&#xff0c;有一串数字和一段base64编码&#xff0c;解开base64编码得到这个编码为敲击码 解码在线网站&#xff1a;Tap Code - 许愿星 (wishingstarmoye.…

Fyne ( go跨平台GUI )中文文档- 扩展Fyne (七)

本文档注意参考官网(developer.fyne.io/) 编写, 只保留基本用法 go代码展示为Go 1.16 及更高版本, ide为goland2021.2 这是一个系列文章&#xff1a; Fyne ( go跨平台GUI )中文文档-入门(一)-CSDN博客 Fyne ( go跨平台GUI )中文文档-Fyne总览(二)-CSDN博客 Fyne ( go跨平台GUI…

百度amis框架经验分享

百度amis框架经验分享 官方文档 amis - 低代码前端框架 这篇文章讲了amis的设计 为什么说百度AMIS框架是一个优秀的设计_百度前端框架-CSDN博客 学习方法&#xff1a; 最好的学习方法就是GPT官方文档 不要去很大力气通读官方文档&#xff0c;大概浏览一遍就行&#xff0c; 以你…

VisionPro - 基础 - 模板匹配技术-Search/PMAlign/PatMax(6)-纹理屏蔽和重叠匹配

前言&#xff1a; 1 特征掩膜屏蔽&#xff1a; 模板匹配的应用中&#xff0c;去除非感兴趣的区域&#xff0c;或者去除一些枝端末节的特征&#xff0c;突出需要的主特征的匹配是一个基本原则。这一节&#xff0c;介绍了PatMax的一些处理方法&#xff1a; 2 重叠匹配 1 Ignor…

【HTTPS】中间人攻击和证书的验证

中间人攻击 服务器可以创建出一堆公钥和私钥&#xff0c;黑客也可以按照同样的方式&#xff0c;创建一对公钥和私钥&#xff0c;冒充自己是服务器&#xff08;搅屎棍&#xff09; 黑客自己也能生成一对公钥和私钥。生成公钥和私钥的算法是开放的&#xff0c;服务器能生产&…

工程车辆目标检测、程车检测算法、工程车辆类型检测算法

工程车检测算法主要用于智能交通系统、建筑工地管理、矿山开采、物流运输等领域&#xff0c;通过图像识别技术来检测和识别工程车&#xff0c;以提高安全管理、交通流量管理和资源调度的效率。以下是关于工程车检测算法的技术实现、应用场景及优势的详细介绍。 一、技术实现 工…

nuget包管理

1、下载 下载nuget 下载nuget.exe&#xff0c;配置系统环境变量&#xff0c;打开电脑属性一高级系统设置一环境变量一系统变量&#xff0c;选择Path&#xff0c;添加nuget.exe目录 2、常用命令 nuget install System.Data.SQLITE -SolutionDirectory D:\NugetPackages\ -Packa…

生信服务器 | 组蛋白甲基化修饰、DNA亲和纯化测序、优青博导团队指导设计、解读实验结果。

查看原文>>>生信服务器 | 组蛋白甲基化修饰、DNA亲和纯化测序、优青博导团队免费指导设计、解读实验结果、一台服务器解决您所有的分析困扰!

CUDA-纹理内存

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 纹理内存是什么&#xff1f; 在 GPU 编程中&#xff0c;纹理内存是一种专门用于二维和三维数据读取的存储方式&#xff0c;特别适…

[SAP ABAP] 数据字典外键关联

SE11创建自定义数据库表 学校表(ZDBT_SCH_437) 表有3个组成字段&#xff1a; ① MANDT (参考数据元素为MANDT&#xff0c;主键) ② SCHID 学校ID (参考新建数据元素ZDE_SCHID_437&#xff0c;主键&#xff0c;NUMC4) ③ SCHNAME 学校名称 (CHAR20) 学生表(ZDBT_STU_437) 表有7个…

基于微信小程序校园订餐的设计与开发+ssm(lw+演示+源码+运行)

摘 要 人民生活水平的提高就会造成生活节奏越来越快&#xff0c;很多人吃饭都采用点外卖的方式。现在点外卖的平台已有很多&#xff0c;大多都需要安装它们的APP才可以使用&#xff0c;并且没有针对校园。如果一味的使用外卖平台不仅会造成商家成本的增加&#xff0c;还不利于…

基于微信小程序的智慧物业管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

C++容器list底层迭代器的实现逻辑~list相关函数模拟实现

目录 1.两个基本的结构体搭建 2.实现push_back函数 3.关于list现状的分析&#xff08;对于我们如何实现这个迭代器很重要&#xff09; 3.1和string,vector的比较 3.2对于list的分析 3.3总结 4.迭代器类的封装 5.list容器里面其他函数的实现 6.个人总结 7.代码附录 1.两…

easylogger移植

1.源码 GitHub - armink/EasyLogger: An ultra-lightweight(ROM<1.6K, RAM<0.3k), high-performance C/C log library. | 一款超轻量级(ROM<1.6K, RAM<0.3k)、高性能的 C/C 日志库 2.介绍 easylogger就是用来打印日志的,我们可以将日志输出到sscom, led屏幕, 或者…

多模态交互才是人机交互的未来

交互方式 在探讨文字交流、语音交流和界面交流的效率时&#xff0c;我们可以看到每种方式都有其独特的优势和局限性。文字交流便于记录和回溯&#xff0c;语音交流则在表达情绪和非语言信息方面更为高效&#xff0c;而界面交流则依赖于图形用户界面&#xff08;GUI&#xff09…

[大语言模型-论文精读] 以《黑神话:悟空》为研究案例探讨VLMs能否玩动作角色扮演游戏?

1. 论文简介 论文《Can VLMs Play Action Role-Playing Games? Take Black Myth Wukong as a Study Case》是阿里巴巴集团的Peng Chen、Pi Bu、Jun Song和Yuan Gao&#xff0c;在2024.09.19提交到arXiv上的研究论文。 论文: https://arxiv.org/abs/2409.12889代码和数据: h…

Mixamo动画使用技巧

1、登录Mixiamo网站 2、下载人物模型 3、找到FBX文件 选中人形骨骼 3、下载动画 4、拖拽FBX 5、注意事项 生成的FBX文件中会包含一个骨骼一个动画 如果人物有骨骼&#xff0c;则不需要&#xff0c;没有需要对应此包中的骨骼&#xff0c;骨骼不可以通用&#xff0c;动画通用 …

某集群管理系统存在任意文件读取漏洞

你为什么要拼命努力&#xff1f;父母的白发&#xff0c;想去的地方很远&#xff0c;想要的东西很贵&#xff0c;喜欢的人很优秀&#xff0c;周围人的嘲笑&#xff0c;以及&#xff0c;天生傲骨。 漏洞描述 利用漏洞&#xff0c;攻击者可以读取 Windows 或 Linux 服务器上的任…