聊天项目(26) 实现联系人和好友申请列表

简介

今日实现界面效果

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

联系人列表

我们自定义一个ChatUserList类,用来管理聊天列表。其声明如下:

  1. class ContactUserList : public QListWidget
  2. {
  3. Q_OBJECT
  4. public:
  5. ContactUserList(QWidget *parent = nullptr);
  6. void ShowRedPoint(bool bshow = true);
  7. protected:
  8. bool eventFilter(QObject *watched, QEvent *event) override ;
  9. private:
  10. void addContactUserList();
  11. public slots:
  12. void slot_item_clicked(QListWidgetItem *item);
  13. // void slot_add_auth_firend(std::shared_ptr<AuthInfo>);
  14. // void slot_auth_rsp(std::shared_ptr<AuthRsp>);
  15. signals:
  16. void sig_loading_contact_user();
  17. void sig_switch_apply_friend_page();
  18. void sig_switch_friend_info_page();
  19. private:
  20. ConUserItem* _add_friend_item;
  21. QListWidgetItem * _groupitem;
  22. };

具体实现

  1. ContactUserList::ContactUserList(QWidget *parent)
  2. {
  3. Q_UNUSED(parent);
  4. this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  5. this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  6. // 安装事件过滤器
  7. this->viewport()->installEventFilter(this);
  8. //模拟从数据库或者后端传输过来的数据,进行列表加载
  9. addContactUserList();
  10. //连接点击的信号和槽
  11. connect(this, &QListWidget::itemClicked, this, &ContactUserList::slot_item_clicked);
  12. // //链接对端同意认证后通知的信号
  13. // connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_add_auth_friend,this,
  14. // &ContactUserList::slot_add_auth_firend);
  15. // //链接自己点击同意认证后界面刷新
  16. // connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_auth_rsp,this,
  17. // &ContactUserList::slot_auth_rsp);
  18. }
  19. void ContactUserList::ShowRedPoint(bool bshow /*= true*/)
  20. {
  21. _add_friend_item->ShowRedPoint(bshow);
  22. }
  23. void ContactUserList::addContactUserList()
  24. {
  25. auto * groupTip = new GroupTipItem();
  26. QListWidgetItem *item = new QListWidgetItem;
  27. item->setSizeHint(groupTip->sizeHint());
  28. this->addItem(item);
  29. this->setItemWidget(item, groupTip);
  30. item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
  31. _add_friend_item = new ConUserItem();
  32. _add_friend_item->setObjectName("new_friend_item");
  33. _add_friend_item->SetInfo(0,tr("新的朋友"),":/res/add_friend.png");
  34. _add_friend_item->SetItemType(ListItemType::APPLY_FRIEND_ITEM);
  35. QListWidgetItem *add_item = new QListWidgetItem;
  36. //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint();
  37. add_item->setSizeHint(_add_friend_item->sizeHint());
  38. this->addItem(add_item);
  39. this->setItemWidget(add_item, _add_friend_item);
  40. //默认设置新的朋友申请条目被选中
  41. this->setCurrentItem(add_item);
  42. auto * groupCon = new GroupTipItem();
  43. groupCon->SetGroupTip(tr("联系人"));
  44. _groupitem = new QListWidgetItem;
  45. _groupitem->setSizeHint(groupCon->sizeHint());
  46. this->addItem(_groupitem);
  47. this->setItemWidget(_groupitem, groupCon);
  48. _groupitem->setFlags(_groupitem->flags() & ~Qt::ItemIsSelectable);
  49. // 创建QListWidgetItem,并设置自定义的widget
  50. for(int i = 0; i < 13; i++){
  51. int randomValue = QRandomGenerator::global()->bounded(100); // 生成0到99之间的随机整数
  52. int str_i = randomValue%strs.size();
  53. int head_i = randomValue%heads.size();
  54. int name_i = randomValue%names.size();
  55. auto *con_user_wid = new ConUserItem();
  56. con_user_wid->SetInfo(0,names[name_i], heads[head_i]);
  57. QListWidgetItem *item = new QListWidgetItem;
  58. //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint();
  59. item->setSizeHint(con_user_wid->sizeHint());
  60. this->addItem(item);
  61. this->setItemWidget(item, con_user_wid);
  62. }
  63. }
  64. bool ContactUserList::eventFilter(QObject *watched, QEvent *event)
  65. {
  66. // 检查事件是否是鼠标悬浮进入或离开
  67. if (watched == this->viewport()) {
  68. if (event->type() == QEvent::Enter) {
  69. // 鼠标悬浮,显示滚动条
  70. this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  71. } else if (event->type() == QEvent::Leave) {
  72. // 鼠标离开,隐藏滚动条
  73. this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  74. }
  75. }
  76. // 检查事件是否是鼠标滚轮事件
  77. if (watched == this->viewport() && event->type() == QEvent::Wheel) {
  78. QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
  79. int numDegrees = wheelEvent->angleDelta().y() / 8;
  80. int numSteps = numDegrees / 15; // 计算滚动步数
  81. // 设置滚动幅度
  82. this->verticalScrollBar()->setValue(this->verticalScrollBar()->value() - numSteps);
  83. // 检查是否滚动到底部
  84. QScrollBar *scrollBar = this->verticalScrollBar();
  85. int maxScrollValue = scrollBar->maximum();
  86. int currentValue = scrollBar->value();
  87. //int pageSize = 10; // 每页加载的联系人数量
  88. if (maxScrollValue - currentValue <= 0) {
  89. // 滚动到底部,加载新的联系人
  90. qDebug()<<"load more contact user";
  91. //发送信号通知聊天界面加载更多聊天内容
  92. emit sig_loading_contact_user();
  93. }
  94. return true; // 停止事件传递
  95. }
  96. return QListWidget::eventFilter(watched, event);
  97. }
  98. void ContactUserList::slot_item_clicked(QListWidgetItem *item)
  99. {
  100. QWidget *widget = this->itemWidget(item); // 获取自定义widget对象
  101. if(!widget){
  102. qDebug()<< "slot item clicked widget is nullptr";
  103. return;
  104. }
  105. // 对自定义widget进行操作, 将item 转化为基类ListItemBase
  106. ListItemBase *customItem = qobject_cast<ListItemBase*>(widget);
  107. if(!customItem){
  108. qDebug()<< "slot item clicked widget is nullptr";
  109. return;
  110. }
  111. auto itemType = customItem->GetItemType();
  112. if(itemType == ListItemType::INVALID_ITEM
  113. || itemType == ListItemType::GROUP_TIP_ITEM){
  114. qDebug()<< "slot invalid item clicked ";
  115. return;
  116. }
  117. if(itemType == ListItemType::APPLY_FRIEND_ITEM){
  118. // 创建对话框,提示用户
  119. qDebug()<< "apply friend item clicked ";
  120. //跳转到好友申请界面
  121. emit sig_switch_apply_friend_page();
  122. return;
  123. }
  124. if(itemType == ListItemType::CONTACT_USER_ITEM){
  125. // 创建对话框,提示用户
  126. qDebug()<< "contact user item clicked ";
  127. //跳转到好友申请界面
  128. emit sig_switch_friend_info_page();
  129. return;
  130. }
  131. }

构造函数中关闭了滚动条的显示,重写了事件过滤器,实现了根据鼠标区域判断是否显示滚动条的功能。

并且实现了点击其中某个item响应对应的功能。并根据不同的item类型跳转不同的页面。

联系人item

因为每一个item都是我们自己定义的,所以我们添加设计师界面类,界面布局如下所示

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

类的声明如下

  1. class ConUserItem : public ListItemBase
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit ConUserItem(QWidget *parent = nullptr);
  6. ~ConUserItem();
  7. QSize sizeHint() const override;
  8. void SetInfo(std::shared_ptr<AuthInfo> auth_info);
  9. void SetInfo(std::shared_ptr<AuthRsp> auth_rsp);
  10. void SetInfo(int uid, QString name, QString icon);
  11. void ShowRedPoint(bool show = false);
  12. private:
  13. Ui::ConUserItem *ui;
  14. std::shared_ptr<UserInfo> _info;
  15. };

具体实现

  1. ConUserItem::ConUserItem(QWidget *parent) :
  2. ListItemBase(parent),
  3. ui(new Ui::ConUserItem)
  4. {
  5. ui->setupUi(this);
  6. SetItemType(ListItemType::CONTACT_USER_ITEM);
  7. ui->red_point->raise();
  8. ShowRedPoint(true);
  9. }
  10. ConUserItem::~ConUserItem()
  11. {
  12. delete ui;
  13. }
  14. QSize ConUserItem::sizeHint() const
  15. {
  16. return QSize(250, 70); // 返回自定义的尺寸
  17. }
  18. void ConUserItem::SetInfo(std::shared_ptr<AuthInfo> auth_info)
  19. {
  20. _info = std::make_shared<UserInfo>(auth_info);
  21. // 加载图片
  22. QPixmap pixmap(_info->_icon);
  23. // 设置图片自动缩放
  24. ui->icon_lb->setPixmap(pixmap.scaled(ui->icon_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
  25. ui->icon_lb->setScaledContents(true);
  26. ui->user_name_lb->setText(_info->_name);
  27. }
  28. void ConUserItem::SetInfo(int uid, QString name, QString icon)
  29. {
  30. _info = std::make_shared<UserInfo>(uid,name, icon);
  31. // 加载图片
  32. QPixmap pixmap(_info->_icon);
  33. // 设置图片自动缩放
  34. ui->icon_lb->setPixmap(pixmap.scaled(ui->icon_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
  35. ui->icon_lb->setScaledContents(true);
  36. ui->user_name_lb->setText(_info->_name);
  37. }
  38. void ConUserItem::SetInfo(std::shared_ptr<AuthRsp> auth_rsp){
  39. _info = std::make_shared<UserInfo>(auth_rsp);
  40. // 加载图片
  41. QPixmap pixmap(_info->_icon);
  42. // 设置图片自动缩放
  43. ui->icon_lb->setPixmap(pixmap.scaled(ui->icon_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
  44. ui->icon_lb->setScaledContents(true);
  45. ui->user_name_lb->setText(_info->_name);
  46. }
  47. void ConUserItem::ShowRedPoint(bool show)
  48. {
  49. if(show){
  50. ui->red_point->show();
  51. }else{
  52. ui->red_point->hide();
  53. }
  54. }

这样我们启动程序就能看到模拟的联系人列表被加载进来了。

申请列表

申请页面ui布局如下

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

我们新增ApplyFriendPage类,用来显示申请列表

  1. class ApplyFriendPage : public QWidget
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit ApplyFriendPage(QWidget *parent = nullptr);
  6. ~ApplyFriendPage();
  7. void AddNewApply(std::shared_ptr<AddFriendApply> apply);
  8. protected:
  9. void paintEvent(QPaintEvent *event);
  10. private:
  11. void loadApplyList();
  12. Ui::ApplyFriendPage *ui;
  13. std::unordered_map<int, ApplyFriendItem*> _unauth_items;
  14. public slots:
  15. void slot_auth_rsp(std::shared_ptr<AuthRsp> );
  16. signals:
  17. void sig_show_search(bool);
  18. };

具体实现

  1. ApplyFriendPage::ApplyFriendPage(QWidget *parent) :
  2. QWidget(parent),
  3. ui(new Ui::ApplyFriendPage)
  4. {
  5. ui->setupUi(this);
  6. connect(ui->apply_friend_list, &ApplyFriendList::sig_show_search, this, &ApplyFriendPage::sig_show_search);
  7. loadApplyList();
  8. //接受tcp传递的authrsp信号处理
  9. connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_auth_rsp, this, &ApplyFriendPage::slot_auth_rsp);
  10. }
  11. ApplyFriendPage::~ApplyFriendPage()
  12. {
  13. delete ui;
  14. }
  15. void ApplyFriendPage::AddNewApply(std::shared_ptr<AddFriendApply> apply)
  16. {
  17. //先模拟头像随机,以后头像资源增加资源服务器后再显示
  18. int randomValue = QRandomGenerator::global()->bounded(100); // 生成0到99之间的随机整数
  19. int head_i = randomValue % heads.size();
  20. auto* apply_item = new ApplyFriendItem();
  21. auto apply_info = std::make_shared<ApplyInfo>(apply->_from_uid,
  22. apply->_name, apply->_desc,heads[head_i], apply->_name, 0, 0);
  23. apply_item->SetInfo( apply_info);
  24. QListWidgetItem* item = new QListWidgetItem;
  25. //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint();
  26. item->setSizeHint(apply_item->sizeHint());
  27. item->setFlags(item->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable);
  28. ui->apply_friend_list->insertItem(0,item);
  29. ui->apply_friend_list->setItemWidget(item, apply_item);
  30. apply_item->ShowAddBtn(true);
  31. //收到审核好友信号
  32. connect(apply_item, &ApplyFriendItem::sig_auth_friend, [this](std::shared_ptr<ApplyInfo> apply_info) {
  33. // auto* authFriend = new AuthenFriend(this);
  34. // authFriend->setModal(true);
  35. // authFriend->SetApplyInfo(apply_info);
  36. // authFriend->show();
  37. });
  38. }
  39. void ApplyFriendPage::paintEvent(QPaintEvent *event)
  40. {
  41. QStyleOption opt;
  42. opt.init(this);
  43. QPainter p(this);
  44. style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
  45. }
  46. void ApplyFriendPage::loadApplyList()
  47. {
  48. //添加好友申请
  49. auto apply_list = UserMgr::GetInstance()->GetApplyList();
  50. for(auto &apply: apply_list){
  51. int randomValue = QRandomGenerator::global()->bounded(100); // 生成0到99之间的随机整数
  52. int head_i = randomValue % heads.size();
  53. auto* apply_item = new ApplyFriendItem();
  54. apply->SetIcon(heads[head_i]);
  55. apply_item->SetInfo(apply);
  56. QListWidgetItem* item = new QListWidgetItem;
  57. //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint();
  58. item->setSizeHint(apply_item->sizeHint());
  59. item->setFlags(item->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable);
  60. ui->apply_friend_list->insertItem(0,item);
  61. ui->apply_friend_list->setItemWidget(item, apply_item);
  62. if(apply->_status){
  63. apply_item->ShowAddBtn(false);
  64. }else{
  65. apply_item->ShowAddBtn(true);
  66. auto uid = apply_item->GetUid();
  67. _unauth_items[uid] = apply_item;
  68. }
  69. //收到审核好友信号
  70. connect(apply_item, &ApplyFriendItem::sig_auth_friend, [this](std::shared_ptr<ApplyInfo> apply_info) {
  71. // auto* authFriend = new AuthenFriend(this);
  72. // authFriend->setModal(true);
  73. // authFriend->SetApplyInfo(apply_info);
  74. // authFriend->show();
  75. });
  76. }
  77. // 模拟假数据,创建QListWidgetItem,并设置自定义的widget
  78. for(int i = 0; i < 13; i++){
  79. int randomValue = QRandomGenerator::global()->bounded(100); // 生成0到99之间的随机整数
  80. int str_i = randomValue%strs.size();
  81. int head_i = randomValue%heads.size();
  82. int name_i = randomValue%names.size();
  83. auto *apply_item = new ApplyFriendItem();
  84. auto apply = std::make_shared<ApplyInfo>(0, names[name_i], strs[str_i],
  85. heads[head_i], names[name_i], 0, 1);
  86. apply_item->SetInfo(apply);
  87. QListWidgetItem *item = new QListWidgetItem;
  88. //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint();
  89. item->setSizeHint(apply_item->sizeHint());
  90. item->setFlags(item->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable);
  91. ui->apply_friend_list->addItem(item);
  92. ui->apply_friend_list->setItemWidget(item, apply_item);
  93. //收到审核好友信号
  94. connect(apply_item, &ApplyFriendItem::sig_auth_friend, [this](std::shared_ptr<ApplyInfo> apply_info){
  95. // auto *authFriend = new AuthenFriend(this);
  96. // authFriend->setModal(true);
  97. // authFriend->SetApplyInfo(apply_info);
  98. // authFriend->show();
  99. });
  100. }
  101. }
  102. void ApplyFriendPage::slot_auth_rsp(std::shared_ptr<AuthRsp> auth_rsp)
  103. {
  104. auto uid = auth_rsp->_uid;
  105. auto find_iter = _unauth_items.find(uid);
  106. if (find_iter == _unauth_items.end()) {
  107. return;
  108. }
  109. find_iter->second->ShowAddBtn(false);
  110. }

因为每个item自定义,所以我们新增设计师界面类ApplyFriendItem

界面布局

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

类的声明如下:

  1. class ApplyFriendItem : public ListItemBase
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit ApplyFriendItem(QWidget *parent = nullptr);
  6. ~ApplyFriendItem();
  7. void SetInfo(std::shared_ptr<ApplyInfo> apply_info);
  8. void ShowAddBtn(bool bshow);
  9. QSize sizeHint() const override {
  10. return QSize(250, 80); // 返回自定义的尺寸
  11. }
  12. int GetUid();
  13. private:
  14. Ui::ApplyFriendItem *ui;
  15. std::shared_ptr<ApplyInfo> _apply_info;
  16. bool _added;
  17. signals:
  18. void sig_auth_friend(std::shared_ptr<ApplyInfo> apply_info);
  19. };

以下为具体实现

  1. ApplyFriendItem::ApplyFriendItem(QWidget *parent) :
  2. ListItemBase(parent), _added(false),
  3. ui(new Ui::ApplyFriendItem)
  4. {
  5. ui->setupUi(this);
  6. SetItemType(ListItemType::APPLY_FRIEND_ITEM);
  7. ui->addBtn->SetState("normal","hover", "press");
  8. ui->addBtn->hide();
  9. connect(ui->addBtn, &ClickedBtn::clicked, [this](){
  10. emit this->sig_auth_friend(_apply_info);
  11. });
  12. }
  13. ApplyFriendItem::~ApplyFriendItem()
  14. {
  15. delete ui;
  16. }
  17. void ApplyFriendItem::SetInfo(std::shared_ptr<ApplyInfo> apply_info)
  18. {
  19. _apply_info = apply_info;
  20. // 加载图片
  21. QPixmap pixmap(_apply_info->_icon);
  22. // 设置图片自动缩放
  23. ui->icon_lb->setPixmap(pixmap.scaled(ui->icon_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
  24. ui->icon_lb->setScaledContents(true);
  25. ui->user_name_lb->setText(_apply_info->_name);
  26. ui->user_chat_lb->setText(_apply_info->_desc);
  27. }
  28. void ApplyFriendItem::ShowAddBtn(bool bshow)
  29. {
  30. if (bshow) {
  31. ui->addBtn->show();
  32. ui->already_add_lb->hide();
  33. _added = false;
  34. }
  35. else {
  36. ui->addBtn->hide();
  37. ui->already_add_lb->show();
  38. _added = true;
  39. }
  40. }
  41. int ApplyFriendItem::GetUid() {
  42. return _apply_info->_uid;
  43. }

申请列表类ApplyFriendList的声明如下

  1. class ApplyFriendList: public QListWidget
  2. {
  3. Q_OBJECT
  4. public:
  5. ApplyFriendList(QWidget *parent = nullptr);
  6. protected:
  7. bool eventFilter(QObject *watched, QEvent *event) override;
  8. private slots:
  9. signals:
  10. void sig_show_search(bool);
  11. };

具体实现

  1. ApplyFriendList::ApplyFriendList(QWidget *parent)
  2. {
  3. Q_UNUSED(parent);
  4. this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  5. this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  6. // 安装事件过滤器
  7. this->viewport()->installEventFilter(this);
  8. }
  9. bool ApplyFriendList::eventFilter(QObject *watched, QEvent *event)
  10. {
  11. // 检查事件是否是鼠标悬浮进入或离开
  12. if (watched == this->viewport()) {
  13. if (event->type() == QEvent::Enter) {
  14. // 鼠标悬浮,显示滚动条
  15. this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  16. } else if (event->type() == QEvent::Leave) {
  17. // 鼠标离开,隐藏滚动条
  18. this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  19. }
  20. }
  21. if (watched == this->viewport()) {
  22. if (event->type() == QEvent::MouseButtonPress) {
  23. emit sig_show_search(false);
  24. }
  25. }
  26. // 检查事件是否是鼠标滚轮事件
  27. if (watched == this->viewport() && event->type() == QEvent::Wheel) {
  28. QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
  29. int numDegrees = wheelEvent->angleDelta().y() / 8;
  30. int numSteps = numDegrees / 15; // 计算滚动步数
  31. // 设置滚动幅度
  32. this->verticalScrollBar()->setValue(this->verticalScrollBar()->value() - numSteps);
  33. return true; // 停止事件传递
  34. }
  35. return QListWidget::eventFilter(watched, event);
  36. }

然后在ChatDialog的stackedWidget中将friend_apply_page升级为ApplyFriendPage.

这样我们启动程序就能看到联系人列表和申请列表了。

下一步还需要写QSS美化以下

  1. #con_user_list {
  2. background-color: rgb(247,247,248);
  3. border: none;
  4. }
  5. #con_user_list::item:selected {
  6. background-color: #d3d7d4;
  7. border: none;
  8. outline: none;
  9. }
  10. #con_user_list::item:hover {
  11. background-color: rgb(206,207,208);
  12. border: none;
  13. outline: none;
  14. }
  15. #con_user_list::focus {
  16. border: none;
  17. outline: none;
  18. }
  19. #GroupTipItem {
  20. background-color: #eaeaea;
  21. border: none;
  22. }
  23. #GroupTipItem QLabel{
  24. color: #2e2f30;
  25. font-size: 12px; /* 设置字体大小 */
  26. font-family: "Microsoft YaHei"; /* 设置字体 */
  27. border: none;
  28. }
  29. #new_friend_item {
  30. border-bottom: 1px solid #eaeaea;
  31. }
  32. #LineItem {
  33. background-color:rgb(247,247,247);
  34. border: none;
  35. }
  36. #friend_apply_lb {
  37. font-family: "Microsoft YaHei";
  38. font-size: 18px;
  39. font-weight: normal;
  40. }
  41. #friend_apply_wid {
  42. background-color: #f1f2f3;
  43. border-bottom: 1px solid #ede9e7;
  44. }
  45. #apply_friend_list {
  46. background-color: #f1f2f3;
  47. border-left: 1px solid #ede9e7;
  48. border-top: none;
  49. border-right: none;
  50. border-bottom: none;
  51. }
  52. ApplyFriendItem {
  53. background-color: #f1f2f3;
  54. border-bottom: 2px solid #dbd9d9;
  55. }
  56. ApplyFriendItem #user_chat_lb{
  57. color: #a2a2a2;
  58. font-size: 14px; /* 设置字体大小 */
  59. font-family: "Microsoft YaHei"; /* 设置字体 */
  60. }
  61. ApplyFriendItem #addBtn[state='normal'] {
  62. background-color: #d3d7d4;
  63. color: #2cb46e;
  64. font-size: 16px; /* 设置字体大小 */
  65. font-family: "Microsoft YaHei"; /* 设置字体 */
  66. border-radius: 20px; /* 设置圆角 */
  67. }
  68. ApplyFriendItem #addBtn[state='hover'] {
  69. background-color: #D3D3D3;
  70. color: #2cb46e;
  71. font-size: 16px; /* 设置字体大小 */
  72. font-family: "Microsoft YaHei"; /* 设置字体 */
  73. border-radius: 20px; /* 设置圆角 */
  74. }
  75. ApplyFriendItem #addBtn[state='press'] {
  76. background-color: #BEBEBE;
  77. color: #2cb46e;
  78. font-size: 16px; /* 设置字体大小 */
  79. font-family: "Microsoft YaHei"; /* 设置字体 */
  80. border-radius: 20px; /* 设置圆角 */
  81. }
  82. #already_add_lb{
  83. color:rgb(153,153,153);
  84. font-size: 12px;
  85. font-family: "Microsoft YaHei";
  86. }
  87. #user_name_lb{
  88. color:rgb(0,0,0);
  89. font-size: 16px;
  90. font-weight: normal;
  91. font-family: "Microsoft YaHei";
  92. }

源码连接

https://gitee.com/secondtonone1/llfcchat

视频连接

https://www.bilibili.com/video/BV1SS42197Yo/?vd_source=8be9e83424c2ed2c9b2a3ed1d01385e9

热门评论

热门文章

  1. slice介绍和使用

    喜欢(521) 浏览(2173)
  2. Linux环境搭建和编码

    喜欢(594) 浏览(9320)
  3. windows环境搭建和vscode配置

    喜欢(587) 浏览(2232)
  4. 解密定时器的实现细节

    喜欢(566) 浏览(2929)
  5. C++ 类的继承封装和多态

    喜欢(588) 浏览(4105)

最新评论

  1. 解决博客回复区被脚本注入的问题 secondtonone1:走到现在我忽然明白一个道理,无论工作也好生活也罢,最重要的是开心,即使一份安稳的工作不能给我带来事业上的积累也要合理的舍弃,所以我还是想去做喜欢的方向。
  2. asio多线程模型IOServicePool Lion:线程池一定要继承单例模式吗
  3. 泛型算法的定制操作 secondtonone1:lambda和bind是C11新增的利器,善于利用这两个机制可以极大地提升编程安全性和效率。
  4. 类和对象 陈宇航:支持!!!!
  5. C++ 虚函数表原理和类成员内存分布 WangQi888888:class Test{ int m; int b; }中b成员是int,为什么在内存中只占了1个字节。不应该是4个字节吗?是不是int应该改为char。这样的话就会符合图上说明的情况

个人公众号

个人微信