聊天项目(24) EventFilter实现搜索隐藏

事件过滤器

我们为了实现点击界面某个位置判断是否隐藏搜索框的功能。我们期待当鼠标点击搜索列表之外的区域时显示隐藏搜索框恢复聊天界面。
点击搜索列表则不隐藏搜索框。可以通过重载ChatDialog的EventFilter函数实现点击功能

  1. bool ChatDialog::eventFilter(QObject *watched, QEvent *event)
  2. {
  3. if (event->type() == QEvent::MouseButtonPress) {
  4. QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
  5. handleGlobalMousePress(mouseEvent);
  6. }
  7. return QDialog::eventFilter(watched, event);
  8. }

具体判断全局鼠标按下位置和功能

  1. void ChatDialog::handleGlobalMousePress(QMouseEvent *event)
  2. {
  3. // 实现点击位置的判断和处理逻辑
  4. // 先判断是否处于搜索模式,如果不处于搜索模式则直接返回
  5. if( _mode != ChatUIMode::SearchMode){
  6. return;
  7. }
  8. // 将鼠标点击位置转换为搜索列表坐标系中的位置
  9. QPoint posInSearchList = ui->search_list->mapFromGlobal(event->globalPos());
  10. // 判断点击位置是否在聊天列表的范围内
  11. if (!ui->search_list->rect().contains(posInSearchList)) {
  12. // 如果不在聊天列表内,清空输入框
  13. ui->search_edit->clear();
  14. ShowSearch(false);
  15. }
  16. }

在ChatDialog构造函数中添加事件过滤器

  1. //检测鼠标点击位置判断是否要清空搜索框
  2. this->installEventFilter(this); // 安装事件过滤器
  3. //设置聊天label选中状态
  4. ui->side_chat_lb->SetSelected(true);

这样就可以实现在ChatDialog中点击其他位置隐藏SearchList列表了。

查找结果

在项目中添加FindSuccessDlg设计师界面类,其布局如下

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

属性管理界面如下

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

FindSuccessDlg声明如下

  1. class FindSuccessDlg : public QDialog
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit FindSuccessDlg(QWidget *parent = nullptr);
  6. ~FindSuccessDlg();
  7. void SetSearchInfo(std::shared_ptr<SearchInfo> si);
  8. private slots:
  9. void on_add_friend_btn_clicked();
  10. private:
  11. Ui::FindSuccessDlg *ui;
  12. QWidget * _parent;
  13. std::shared_ptr<SearchInfo> _si;
  14. };

FindSuccessDlg实现如下

  1. FindSuccessDlg::FindSuccessDlg(QWidget *parent) :
  2. QDialog(parent),
  3. ui(new Ui::FindSuccessDlg)
  4. {
  5. ui->setupUi(this);
  6. // 设置对话框标题
  7. setWindowTitle("添加");
  8. // 隐藏对话框标题栏
  9. setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
  10. // 获取当前应用程序的路径
  11. QString app_path = QCoreApplication::applicationDirPath();
  12. QString pix_path = QDir::toNativeSeparators(app_path +
  13. QDir::separator() + "static"+QDir::separator()+"head_1.jpg");
  14. QPixmap head_pix(pix_path);
  15. head_pix = head_pix.scaled(ui->head_lb->size(),
  16. Qt::KeepAspectRatio, Qt::SmoothTransformation);
  17. ui->head_lb->setPixmap(head_pix);
  18. ui->add_friend_btn->SetState("normal","hover","press");
  19. this->setModal(true);
  20. }
  21. FindSuccessDlg::~FindSuccessDlg()
  22. {
  23. qDebug()<<"FindSuccessDlg destruct";
  24. delete ui;
  25. }
  26. void FindSuccessDlg::SetSearchInfo(std::shared_ptr<SearchInfo> si)
  27. {
  28. ui->name_lb->setText(si->_name);
  29. _si = si;
  30. }
  31. void FindSuccessDlg::on_add_friend_btn_clicked()
  32. {
  33. //todo... 添加好友界面弹出
  34. }

在SearchList 的slot_item_clicked函数中添加点击条目处理逻辑

  1. void SearchList::slot_item_clicked(QListWidgetItem *item)
  2. {
  3. QWidget *widget = this->itemWidget(item); //获取自定义widget对象
  4. if(!widget){
  5. qDebug()<< "slot item clicked widget is nullptr";
  6. return;
  7. }
  8. // 对自定义widget进行操作, 将item 转化为基类ListItemBase
  9. ListItemBase *customItem = qobject_cast<ListItemBase*>(widget);
  10. if(!customItem){
  11. qDebug()<< "slot item clicked widget is nullptr";
  12. return;
  13. }
  14. auto itemType = customItem->GetItemType();
  15. if(itemType == ListItemType::INVALID_ITEM){
  16. qDebug()<< "slot invalid item clicked ";
  17. return;
  18. }
  19. if(itemType == ListItemType::ADD_USER_TIP_ITEM){
  20. //todo ...
  21. _find_dlg = std::make_shared<FindSuccessDlg>(this);
  22. auto si = std::make_shared<SearchInfo>(0,"llfc","llfc","hello , my friend!",0);
  23. (std::dynamic_pointer_cast<FindSuccessDlg>(_find_dlg))->SetSearchInfo(si);
  24. _find_dlg->show();
  25. return;
  26. }
  27. //清楚弹出框
  28. CloseFindDlg();
  29. }

这样我们在输入框输入文字,点击搜索列表中搜索添加好友的item,就能弹出搜索结果对话框了。这里只做界面演示,之后会改为像服务器发送请求获取搜索结果。

pro的改写

我们对项目的pro做了调整,更新了static文件夹的拷贝以及编码utf-8的设定

  1. QT += core gui network
  2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
  3. TARGET = llfcchat
  4. TEMPLATE = app
  5. RC_ICONS = icon.ico
  6. DESTDIR = ./bin
  7. DEFINES += QT_DEPRECATED_WARNINGS
  8. CONFIG += c++11
  9. SOURCES += \
  10. adduseritem.cpp \
  11. bubbleframe.cpp \
  12. chatdialog.cpp \
  13. chatitembase.cpp \
  14. chatpage.cpp \
  15. chatuserlist.cpp \
  16. chatuserwid.cpp \
  17. chatview.cpp \
  18. clickedbtn.cpp \
  19. clickedlabel.cpp \
  20. customizeedit.cpp \
  21. findsuccessdlg.cpp \
  22. global.cpp \
  23. httpmgr.cpp \
  24. listitembase.cpp \
  25. loadingdlg.cpp \
  26. logindialog.cpp \
  27. main.cpp \
  28. mainwindow.cpp \
  29. messagetextedit.cpp \
  30. picturebubble.cpp \
  31. registerdialog.cpp \
  32. resetdialog.cpp \
  33. searchlist.cpp \
  34. statewidget.cpp \
  35. tcpmgr.cpp \
  36. textbubble.cpp \
  37. timerbtn.cpp \
  38. userdata.cpp \
  39. usermgr.cpp
  40. HEADERS += \
  41. adduseritem.h \
  42. bubbleframe.h \
  43. chatdialog.h \
  44. chatitembase.h \
  45. chatpage.h \
  46. chatuserlist.h \
  47. chatuserwid.h \
  48. chatview.h \
  49. clickedbtn.h \
  50. clickedlabel.h \
  51. customizeedit.h \
  52. findsuccessdlg.h \
  53. global.h \
  54. httpmgr.h \
  55. listitembase.h \
  56. loadingdlg.h \
  57. logindialog.h \
  58. mainwindow.h \
  59. messagetextedit.h \
  60. picturebubble.h \
  61. registerdialog.h \
  62. resetdialog.h \
  63. searchlist.h \
  64. singleton.h \
  65. statewidget.h \
  66. tcpmgr.h \
  67. textbubble.h \
  68. timerbtn.h \
  69. userdata.h \
  70. usermgr.h
  71. FORMS += \
  72. adduseritem.ui \
  73. chatdialog.ui \
  74. chatpage.ui \
  75. chatuserwid.ui \
  76. findsuccessdlg.ui \
  77. loadingdlg.ui \
  78. logindialog.ui \
  79. mainwindow.ui \
  80. registerdialog.ui \
  81. resetdialog.ui
  82. # Default rules for deployment.
  83. qnx: target.path = /tmp/$${TARGET}/bin
  84. else: unix:!android: target.path = /opt/$${TARGET}/bin
  85. !isEmpty(target.path): INSTALLS += target
  86. RESOURCES += \
  87. rc.qrc
  88. DISTFILES += \
  89. config.ini
  90. CONFIG(debug, debug | release) {
  91. #指定要拷贝的文件目录为工程目录下release目录下的所有dll、lib文件,例如工程目录在D:\QT\Test
  92. #PWD就为D:/QT/Test,DllFile = D:/QT/Test/release/*.dll
  93. TargetConfig = $${PWD}/config.ini
  94. #将输入目录中的"/"替换为"\"
  95. TargetConfig = $$replace(TargetConfig, /, \\)
  96. #将输出目录中的"/"替换为"\"
  97. OutputDir = $${OUT_PWD}/$${DESTDIR}
  98. OutputDir = $$replace(OutputDir, /, \\)
  99. //执行copy命令
  100. QMAKE_POST_LINK += copy /Y \"$$TargetConfig\" \"$$OutputDir\" &
  101. # 首先,定义static文件夹的路径
  102. StaticDir = $${PWD}/static
  103. # 将路径中的"/"替换为"\"
  104. StaticDir = $$replace(StaticDir, /, \\)
  105. #message($${StaticDir})
  106. # 使用xcopy命令拷贝文件夹,/E表示拷贝子目录及其内容,包括空目录。/I表示如果目标不存在则创建目录。/Y表示覆盖现有文件而不提示。
  107. QMAKE_POST_LINK += xcopy /Y /E /I \"$$StaticDir\" \"$$OutputDir\\static\\\"
  108. }else{
  109. #release
  110. message("release mode")
  111. #指定要拷贝的文件目录为工程目录下release目录下的所有dll、lib文件,例如工程目录在D:\QT\Test
  112. #PWD就为D:/QT/Test,DllFile = D:/QT/Test/release/*.dll
  113. TargetConfig = $${PWD}/config.ini
  114. #将输入目录中的"/"替换为"\"
  115. TargetConfig = $$replace(TargetConfig, /, \\)
  116. #将输出目录中的"/"替换为"\"
  117. OutputDir = $${OUT_PWD}/$${DESTDIR}
  118. OutputDir = $$replace(OutputDir, /, \\)
  119. //执行copy命令
  120. QMAKE_POST_LINK += copy /Y \"$$TargetConfig\" \"$$OutputDir\"
  121. # 首先,定义static文件夹的路径
  122. StaticDir = $${PWD}/static
  123. # 将路径中的"/"替换为"\"
  124. StaticDir = $$replace(StaticDir, /, \\)
  125. #message($${StaticDir})
  126. # 使用xcopy命令拷贝文件夹,/E表示拷贝子目录及其内容,包括空目录。/I表示如果目标不存在则创建目录。/Y表示覆盖现有文件而不提示。
  127. QMAKE_POST_LINK += xcopy /Y /E /I \"$$StaticDir\" \"$$OutputDir\\static\\\"
  128. }
  129. win32-msvc*:QMAKE_CXXFLAGS += /wd"4819" /utf-8

视频

https://www.bilibili.com/video/BV1ww4m1e72G/

源码链接

https://gitee.com/secondtonone1/llfcchat

热门评论

热门文章

  1. C++ 类的继承封装和多态

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

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

    喜欢(587) 浏览(1953)
  4. slice介绍和使用

    喜欢(521) 浏览(2024)
  5. 解密定时器的实现细节

    喜欢(566) 浏览(2551)

最新评论

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

个人公众号

个人微信