IM项目-----客户端部分选择好友窗口
前言
介绍选择好友窗口的实现
选择好友类
这个类中有两个Widget,代表左右部分。
在构造函数中使用水平布局管理进行布局。
左边部分使用垂直布局管理,右边部分使用网格布局。
class ChooseFriendDialog : public QDialog
{
Q_OBJECT
public:
ChooseFriendDialog(const QString& userId,QWidget* parent = nullptr);
void initLeft(QHBoxLayout* layout);
void addFriend(const QString& userId,const QIcon& avatar, const QString& name, bool checked);
void addSelectedFriend(const QString& userId,const QIcon& avatar, const QString& name, bool checked);
void deleteSelectedFriend(const QString& userId);
void initRight(QHBoxLayout* layout);
//加载好友列表
void initData();
void clickOkBtn();
//获取已选中的好友userId
QList<QString> generateMemberList();
private:
// 保存左侧全部好友列表的 QWidget
QWidget* totalContainer;
// 保存右侧选中好友列表的 QWidget
QWidget* selectedContainer;
QPushButton* okBtn;
QPushButton* cancelBtn;
QString userId;//该会话的用户Id
};
其中滑动区域中的一个一个item的实现是自定义控件。
class ChooseFriendItem : public QWidget
{
Q_OBJECT
public:
//checked代表当前item的复选框是否被选中
ChooseFriendItem(ChooseFriendDialog* owner,const QString &userId,const QIcon& avatar, const QString& name, bool checked);
//重写绘制事件来绘制鼠标放到item上的颜色效果
void paintEvent(QPaintEvent* event) override;
void enterEvent(QEnterEvent* event) override;
void leaveEvent(QEvent* event) override;
QString getUserId();
QCheckBox* getCheckBox();
private:
QCheckBox* checkBox;
QPushButton* avatarBtn;
QLabel* nameLabel;
//鼠标是否选中
bool isHover = false;
//这个item是属于哪个控件的,这里是属于ChooseFriendDialog
ChooseFriendDialog* owner;
//这个好友的userId,用来作为item唯一标识,方便复选框取消选择进行删除
QString userId;
};
重写了鼠标移动和离开的事件来进行颜色的改变。通过QPainter来实现,和前面qss实现不同。
void ChooseFriendItem::paintEvent(QPaintEvent *event)
{
(void) event;
QPainter painter(this);
if (isHover) {
// 绘制成深色
painter.fillRect(this->rect(), QColor(230, 230, 230));
} else {
// 绘制成浅色
painter.fillRect(this->rect(), QColor(255, 255, 255));
}
}
在构造函数中连接了信号槽,用于处理复选框选中和取消选中。
在这个对象中保存了一个选择好友类的指针,用于完成UI的更新。
//连接槽函数,选中复选框执行对应操作
connect(checkBox,&QCheckBox::toggled,this,[=](bool checked){
if(checked){
//复选框为勾选状态
owner->addSelectedFriend(userId,avatarBtn->icon(),nameLabel->text(),true);
}else{
//复选框取消勾选
owner->deleteSelectedFriend(userId);
}
});
在好友窗口构造时,就会调用addFriend函数,将好友列表中的好友添加进来。
当我们勾选复选框后,就会调用第二个函数,构造一个item添加到右侧滑动窗口中。
void ChooseFriendDialog::addFriend(const QString& userId,const QIcon &avatar, const QString &name, bool checked)
{
ChooseFriendItem* chooseFriendItem = new ChooseFriendItem(this,userId,avatar,name,checked);
totalContainer->layout()->addWidget(chooseFriendItem);
}
void ChooseFriendDialog::addSelectedFriend(const QString& userId,const QIcon &avatar, const QString &name, bool checked = true)
{
ChooseFriendItem* chooseFriendItem = new ChooseFriendItem(this,userId,avatar,name,checked);
selectedContainer->layout()->addWidget(chooseFriendItem);
}
当取消勾选复选框,就需要清除右侧已选择的item,这个的实现逻辑就是遍历右侧滑动区域的item,比较点击的item中的userID和右侧滑动区域的item是否一致,删除一致的item。
另外需要遍历左侧的滑动区域,将勾选状态设置为false。
void ChooseFriendDialog::deleteSelectedFriend(const QString &userId)
{
//获取已选择好友窗口的layout
QVBoxLayout* vlayout = dynamic_cast<QVBoxLayout*>(selectedContainer->layout());
//遍历这个layout的所有item
for(int i = vlayout->count() - 1;i >= 0; i--)
{
auto* item = vlayout->itemAt(i);
if (item == nullptr || item->widget() == nullptr) {
continue;
}
ChooseFriendItem* chooseFriendItem = dynamic_cast<ChooseFriendItem*>(item->widget());
// 判定当前的 Item 的 userId 是否是要删除的 userId
if (chooseFriendItem->getUserId() != userId) {
continue;
}
vlayout->removeWidget(chooseFriendItem);
// 此处直接使用 delete 可能导致程序直接崩溃. 因为 delete 该对象的时候, 该对象内部的 QCheckBox 还在使用中 (触发着信号槽呢)
// 改成 deleteLater, 就相当于把 delete 操作委托给 Qt 自身来完成了. 告诉 Qt 框架说, 你要删除这个对象. 至于啥时候删除 Qt
// 会确保在 Qt 自身用完了之后, 去真正删除.
// delete chooseFriendItem;
chooseFriendItem->deleteLater();
}
// 再遍历一下左侧列表, 把左侧列表中对应 item 的 checkBox 勾选状态取消掉.
QVBoxLayout* vlayoutLeft = dynamic_cast<QVBoxLayout*>(totalContainer->layout());
for (int i = 0; i < vlayoutLeft->count(); ++i) {
auto* item = vlayoutLeft->itemAt(i);
if (item == nullptr || item->widget() == nullptr) {
continue;
}
ChooseFriendItem* chooseFriendItem = dynamic_cast<ChooseFriendItem*>(item->widget());
if (chooseFriendItem->getUserId() != userId) {
continue;
}
// 取消 checkBox 选中状态
chooseFriendItem->getCheckBox()->setChecked(false);
}
}
原文地址:https://blog.csdn.net/2301_77412625/article/details/143923100
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!