系统设计
模块设计
好友申请模块
主要组件:ClickedBtn、QScrollArea、CustomizeEdit、ClickedOnceLabel
使用的自定义组件:CustomizeEdit、ClickedBtn、QScrollArea、、ClickedOnceLabel
模块运行逻辑
聊天主界面中将search_edit内容改变时发出信号,绑定若文本不为空执行槽函数ShowSearch,用于显示搜索列表。
connect(ui->search_edit,&QLineEdit::textChanged,this,&ChatDialog::slot_text_changed);
ShowSearch函数功能
void ChatDialog::ShowSearch(bool bsearch) { if(bsearch){ ui->chat_user_list->hide(); ui->con_user_list->hide(); ui->search_list->show(); _mode = ChatUIMode::SearchMode; }else if(_state == ChatUIMode::ChatMode){ ui->chat_user_list->show(); ui->con_user_list->hide(); ui->search_list->hide(); _mode = ChatUIMode::ChatMode; }else if(_state == ChatUIMode::ContactMode){ ui->chat_user_list->hide(); ui->search_list->hide(); ui->con_user_list->show(); _mode = ChatUIMode::ContactMode; }
SearchList的构造函数中,实现了添加搜索的AddUserItem 以 ListItemBase 为父类 ,QListWidgetBase为基类
SearchList查询添加好友的Item
void SearchList::addTipItem() { auto *invalid_item = new QWidget(); QListWidgetItem *item_tmp = new QListWidgetItem; //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint(); item_tmp->setSizeHint(QSize(250,10)); this->addItem(item_tmp); invalid_item->setObjectName("invalid_item"); this->setItemWidget(item_tmp, invalid_item); item_tmp->setFlags(item_tmp->flags() & ~Qt::ItemIsSelectable);
auto *add_user_item = new AddUserItem(); QListWidgetItem *item = new QListWidgetItem; //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint(); item->setSizeHint(add_user_item->sizeHint()); this->addItem(item); this->setItemWidget(item, add_user_item);
}
当点击Searchlist时,出发点击槽函数,并且判断类型。
QListWidgetItem的类型
//自定义QListWidgetItem的几种类型
enum ListItemType{
CHAT_USER_ITEM, //聊天用户
CONTACT_USER_ITEM, //联系人用户
SEARCH_USER_ITEM, //搜索到的用户
ADD_USER_TIP_ITEM, //提示添加用户
INVALID_ITEM, //不可点击条目
GROUP_TIP_ITEM, //分组提示条目
LINE_ITEM, //分割线
APPLY_FRIEND_ITEM, //好友申请
};
用于创建添加好友界面的slot
void SearchList::slot_item_clicked(QListWidgetItem *item) { QWidget *widget = this->itemWidget(item); // 获取自定义widget对象 if(!widget){ qDebug()<< "slot item clicked widget is nullptr"; return; }
// 对自定义widget进行操作, 将item 转化为基类ListItemBase ListItemBase *customItem = qobject_cast<ListItemBase*>(widget); if(!customItem){ qDebug()<< "slot item clicked widget is nullptr"; return; } auto itemType = customItem->GetItemType(); if(itemType == ListItemType::INVALID_ITEM){ qDebug()<< "slot invalid item clicked "; return; } if(itemType == ListItemType::ADD_USER_TIP_ITEM){ //生成对应的查找信息的界面QDialog _find_dlg = std::make_shared<FindSuccessDlg>(this); //该处为自定义,后期改写为服务器获取 auto si = std::make_shared<SearchInfo> (0,"wzq","wzq","wzq",0,":C:/Users/12291/Pictures/icon/add_friend_normal.png"); //使用强制转换 dynamic_pointer_cast<FindSuccessDlg>(_find_dlg)->SetSearchInfo(si); //显示 _find_dlg->show(); // dynamic_pointer_cast<FindSuccessDlg>(_find_dlg)->SetSearchInfo(si); // dynamic_pointer_cast<FindSuccessDlg>(_find_dlg)->SetSearchInfo(si); // if (_send_pending) { // return; // } // if (!_search_edit) { // return; // } // waitPending(true); // auto search_edit = dynamic_cast<CustomizeEdit*>(_search_edit); // auto uid_str = search_edit->text(); // //此处发送请求给server // QJsonObject jsonObj; // jsonObj["uid"] = uid_str; // QJsonDocument doc(jsonObj); // QByteArray jsonData = doc.toJson(QJsonDocument::Compact); // //发送tcp请求给chat server // emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_SEARCH_USER_REQ, jsonData); return; } //清除弹出框 CloseFindDlg();
}
弹出显示对应信息之后,点击FindSuccessDlg的add_friend_btn触发槽函数用于显示添加好友界面。
on_add_friend_btn_clicked函数
void FindSuccessDlg::on_add_friend_btn_clicked() { //隐藏当前界面(添加好友) this->hide(); //弹出加好友界面(详细信息) auto applyFriend = new ApplyFriend(_parent); applyFriend->SetSearchInfo(_si);
//QDialog 类的成员函数。将当前窗口设置为模态窗口,当此窗口显示时,用户不能与其他窗口进行交互,直到这个窗口被关闭或隐藏。 applyFriend->setModal(true); applyFriend->show();
}
组件设计
CustomizeEdit
功能描述
CustomizeEdit 为QLineEdit 的自定义提升类,相对于QlineEdit 添加焦点检测、设置最大长度
customizeedit.h
#ifndef CUSTOMIZEEDIT_H
#define CUSTOMIZEEDIT_H
#include <QLineEdit>
#include <QDebug>
class CustomizeEdit: public QLineEdit
{
Q_OBJECT
public:
CustomizeEdit(QWidget *parent = nullptr);
void SetMaxLength(int maxLen);
protected:
void focusOutEvent(QFocusEvent *event) override
{
// 执行失去焦点时的处理逻辑
//qDebug() << "CustomizeEdit focusout";
// 调用基类的focusOutEvent()方法,保证基类的行为得到执行
QLineEdit::focusOutEvent(event);
//发送失去焦点得信号
emit sig_foucus_out();
}
private:
void limitTextLength(QString text) {
if(_max_len <= 0){
return;
}
QByteArray byteArray = text.toUtf8();
if (byteArray.size() > _max_len) {
byteArray = byteArray.left(_max_len);
this->setText(QString::fromUtf8(byteArray));
}
}
int _max_len;
signals:
void sig_foucus_out();
};
#endif // CUSTOMIZEEDIT_H
customizeedit.cpp
#include "customizeedit.h"
CustomizeEdit::CustomizeEdit(QWidget *parent):QLineEdit (parent),_max_len(0)
{
connect(this, &QLineEdit::textChanged, this, &CustomizeEdit::limitTextLength);
}
void CustomizeEdit::SetMaxLength(int maxLen)
{
_max_len = maxLen;
}
ClickLabel
功能描述
ClickLabel 为 QLabel的自定义提升类,相对于QlineEdit添加鼠标按下、释放、进入、进出的事件处理,鼠标对应状态显示的切换
clicklabel.h
#ifndef CLICKEDLABEL_H
#define CLICKEDLABEL_H
#include <QLabel>
#include "global.h"
class ClickedLabel:public QLabel
{
Q_OBJECT
public:
ClickedLabel(QWidget* parent);
virtual void mousePressEvent(QMouseEvent *ev) override;
virtual void mouseReleaseEvent(QMouseEvent *ev) override;
virtual void enterEvent(QEnterEvent *event) override;
virtual void leaveEvent(QEvent* event) override;
void SetState(QString normal="", QString hover="", QString press="",
QString select="", QString select_hover="", QString select_press="");
ClickLbState GetCurState();
bool SetCurState(ClickLbState state);
void ResetNormalState();
protected:
private:
QString _normal;
QString _normal_hover;
QString _normal_press;
QString _selected;
QString _selected_hover;
QString _selected_press;
ClickLbState _curstate;
signals:
void clicked(QString,ClickLbState);
};
#endif // CLICKEDLABEL_H
clicklabel.cpp
#include "clickedlabel.h"
#include <QMouseEvent>
ClickedLabel::ClickedLabel(QWidget* parent):QLabel (parent),_curstate(ClickLbState::Normal)
{
this->setCursor(Qt::PointingHandCursor);
}
// 处理鼠标点击事件
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_hover);
repolish(this);
update();
}else{
qDebug()<<"clicked , change to normal hover: "<< _normal_hover;
_curstate = ClickLbState::Normal;
setProperty("state",_normal_hover);
repolish(this);
update();
}
// emit clicked();
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",_selected_press);
repolish(this);
update();
}else{
// qDebug()<<"ReleaseEvent , change to select hover: "<< _selected_hover;
setProperty("state",_normal_press);
repolish(this);
update();
}
emit clicked(this->text(),_curstate);
return;
}
// 调用基类的mousePressEvent以保证正常的事件处理
QLabel::mousePressEvent(event);
}
// 处理鼠标悬停进入事件
void ClickedLabel::enterEvent(QEnterEvent* event) {
// 在这里处理鼠标悬停进入的逻辑
if(_curstate == ClickLbState::Normal){
qDebug()<<"enter , change to normal hover: "<< _normal_hover;
setProperty("state",_normal_hover);
repolish(this);
update();
}else{
qDebug()<<"enter , change to selected hover: "<< _selected_hover;
setProperty("state",_selected_hover);
repolish(this);
update();
}
QLabel::enterEvent(event);
}
// 处理鼠标悬停离开事件
void ClickedLabel::leaveEvent(QEvent* event){
// 在这里处理鼠标悬停离开的逻辑
if(_curstate == ClickLbState::Normal){
qDebug()<<"leave , change to normal : "<< _normal;
setProperty("state",_normal);
repolish(this);
update();
}else{
qDebug()<<"leave , change to normal hover: "<< _selected;
setProperty("state",_selected);
repolish(this);
update();
}
QLabel::leaveEvent(event);
}
void ClickedLabel::SetState(QString normal, QString hover, QString press,
QString select, QString select_hover, QString select_press)
{
_normal = normal;
_normal_hover = hover;
_normal_press = press;
_selected = select;
_selected_hover = select_hover;
_selected_press = select_press;
setProperty("state",normal);
repolish(this);
}
ClickLbState ClickedLabel::GetCurState(){
return _curstate;
}
bool ClickedLabel::SetCurState(ClickLbState state)
{
_curstate = state;
if(_curstate == ClickLbState::Normal)
{
setProperty("state",_normal);
repolish(this);
}
else if(_curstate == ClickLbState::Selected)
{
setProperty("state",_selected);
repolish(this);
}
return true;
}
void ClickedLabel::ResetNormalState()
{
_curstate = ClickLbState::Normal;
setProperty("state",_normal);
repolish(this);
}
评论区