设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间20 现在时间20 缓存数据 和聪明人交流,和靠谱的人恋爱,和进取的人共事,和幽默的人随行。晚安!

和聪明人交流,和靠谱的人恋爱,和进取的人共事,和幽默的人随行。晚安!

查看: 687|回复: 3

详解QListWidget如何实现自定义Item效果

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:204
  • 打卡月天数:0
  • 打卡总奖励:3189
  • 最近打卡:2023-08-27 09:08:14
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
412
主题
384
精华
0
金钱
4389
积分
823
注册时间
2022-12-20
最后登录
2025-8-30

发表于 2023-2-13 12:21:14 | 显示全部楼层 |阅读模式
首先,我们来看以下实现的最终效果吧!
132135nlzeiv7lotgkddvi.png

我觉得这并不是一个很难得问题,最近新招了一个应届生,发现在实现上述效果时,被困扰住了,是不是刚刚接触Qt的这种稍微有难度的界面时,都会有些无头绪呢?
所以,我打算分享给大家实现的思路,以及会出现的问题,就我一个开发5年C++的员工而言,针对新手会遇到哪些不懂的问题。
当前的开发环境:win10 VS2017 + Qt5.14.2 x64
在实现过程中新手会出现的难点,如下
1:如何在QListWidget中添加带有按钮、文本等其它控件的一条数据?
2:选中每一条之后如何响应?QListWidget自带的item响应为什么不生效?
3:如何选中删除按钮并通知QListWidget做出具体的响应?
就根据上述三个问题,边讲述问题边实现带有自定义控件的Item内容吧!
在使用QListWidget插入一条数据时,默认的方式,如下:
  1. ui.listWidget->insertItem(0, "Text Content"); //方法1
  2. ui.listWidget->addItem("Text Content"); //方法2
复制代码
使用上述代码是无法实现的,因为参数中只能添加QString类型的字符串,那么该如何实现添加自定义项呢?
在QListWidget类中提供了叫做QListWidgetItem的子类,用于实现自定义的item。
132135wy6m4y6476txesy6.jpeg

这时,我们就需要重新定义一个类,并且将该类与ListWidgetItem进行绑定,就可以实现每一行的item上展示属于我们自定义的格式了。
例子中展示的item中显示了一个选择框、文件名称以及删除按钮。
在这里,采用了QCheckBox以及QPushButton两个按钮实现的。
有人会询问:文件名称不应该使用QLabel控件表示吗?
回答是:当前可以使用QLabel控件显示文件名称,这里采用QCheck主要是想要展示文件的图标,根据不同的文件名后缀显示不同的图标。
自定义Widget
该类继承自QWidget。假设叫做:CustomItem
有些新手会直接创建一个纯的C++类,这样做肯定是有问题的,当我们在外部使用当前自定义类时,你会发现,为什么新创建的类会单独分出来呢?
如果直接使用纯C++类,还有另一个至关重要的问题,当前类需要进行消息交互时,你该如何传递给外部调用者呢?回调吗?是不是有点大材小用呢?
  1. class CustomItem : public QWidget
  2. {
  3.         Q_OBJECT

  4. public:
  5.         CustomItem(QWidget *parent);
  6.         ~CustomItem();
  7. private:
  8.         QCheckBox* m_checkName; //文件名
  9.         QCheckBox* m_checkSelect; //选择
  10.         QPushButton* m_btnDelete; //删除

  11. };
复制代码
自定义类CustomItem中创建了三个控件变量,分别表示了:选择框、文件名称以及删除按钮。
就是文章开始显示效果图的三个控件了。
接下来,需要定义一个外部调用接口,插入一条有效数据,假设接口名称是:AddINewtemData
  1. class CustomItem : public QWidget
  2. {
  3.         Q_OBJECT

  4. public:
  5.         CustomItem(QWidget *parent);
  6.         ~CustomItem();
  7. public: //对外开放接口
  8.         void AddINewtemData(int nRow, QString qsFileName); //添加一条新数据
  9. private:
  10.         int m_nRow;
  11.         QCheckBox* m_checkName; //附件名
  12.         QCheckBox* m_checkSelect; //选择
  13.         QPushButton* m_btnDelete; //删除

  14. };
复制代码
AddINewtemData 参数
参数1:代表的是当前自定义widget属于QListWidget的行编号,用于后续消息传递使用。
参数2:需要展示的文件名称
根据用户传入的文件名称,根据文件后缀展示不同的图标。
  1. void CustomItem::AddINewtemData(int nRow, QString qPath)
  2. {
  3.         m_nRow = nRow; //记录当前自定义widget对应的QListWidget的行号
  4.         
  5.         //根据路径名,获取文件名称,并设置
  6.         QFileInfo info(qPath);
  7.         QString qsFileName = info.fileName();
  8.         m_checkName->setText(qsFileName);
  9.         //获取文件后缀
  10.         QString qsCheckStyle = "";
  11.         if (info.suffix() == "mp4") //视频文件
  12.         {
  13.             //自定义QCheckBox风格
  14.         }
  15.         else if (info.suffix() == "png") //图片文件
  16.         {
  17.             //自定义QCheckBox风格
  18.         }
  19.         else if (info.suffix() == "xlsx") //表格文件
  20.         {
  21.             //自定义QCheckBox风格
  22.         }
  23.         else if (info.suffix() == "pdf")
  24.         {
  25.             //自定义QCheckBox风格
  26.         }
  27.         else //文档文件
  28.         {
  29.             //自定义QCheckBox风格
  30.         }
  31.         m_checkName->setStyleSheet(qsCheckStyle);
  32. }
复制代码
构造完自定义widget类之后,接下来就需要将该类与QListWidgetItem进行绑定,显示到QListWidget上去。
外部调用方法,如下:
  1. int nCount = ui.listWidget->count();

  2. CustomItem* widget = new CustomItem(this);
  3. widget->AddINewtemData(nCount, qsFileName);
  4. widget->show();

  5. QListWidgetItem* item = new QListWidgetItem;
  6. item->setSizeHint(QSize(48, 48));
  7. ui.listWidget->addItem(item);
  8. ui.listWidget->setItemWidget(item, widget);
复制代码
自定义CustomItem响应
上述功能可以实现QListWidget中展示自定义的widget之后,该如何点击QListWidget中的每一条做出不同的响应呢?
此时,我们对每一行的QListWigetItem绑定自定义类之后,是无法响应QListWidget自身的选择消息的!这一点需要大家记清楚了。
那么,该怎么触发呢?
针对于每一个QWidget类,只要是继承自QWidget,都会有鼠标的四大响应:
  1. virtual void mousePressEvent(QMouseEvent *event);
  2. virtual void mouseReleaseEvent(QMouseEvent *event);
  3. virtual void mouseDoubleClickEvent(QMouseEvent *event);
  4. virtual void mouseMoveEvent(QMouseEvent *event);
复制代码
当鼠标在自定义类做了点击效果后,肯定可以在鼠标按下事件中获取点击响应的。
所以,在自定义类CustomItem中需要重写QWidget的系统消息:mousePressEvent
  1. void CustomItem::mousePressEvent(QMouseEvent *event)
  2. {
  3.     QWidget::mousePressEvent(event);
  4. }
复制代码
断点设在该响应函数中时,肯定是会触发的,如果不可以肯定是当前widget处于禁用状态,或者是被遮盖住了。
这里还有一个隐藏问题:有些同学在点击自定义窗口时会发现这样一个奇怪的现象,为什么点击有些区域是响应mousePressEvent消息的,而点击有些区域是不响应呢?
以下是重中之重了!!
这就是前一段话提到的内容了,当前widget不触发时,肯定是禁用或者是被遮挡住了。
在我们这个自定义Widget中有三个活跃的控件,两个QCheck,一个QPushButton,当我们的鼠标在任意控件上点击时,此时的点击响应应该是响应到子控件上,而不是自定义的Widget(CustomItem)上。
为了让鼠标点击任何控件时,所有的响应都响应到父类Widget,也就是CustomItem上时,我们应该对支持鼠标响应操作的控件做特殊处理
setAttribute(Qt::WA_TransparentForMouseEvents)
每个控件都要设置以上的操作,当前控件只是用来显示,不做任何消息处理,是当前窗口做的消息处理
自定义Widget控件响应并通知外界处理
下面,来说一说第三个重点问题,如何通知外界处理。
我们使用了自定义的Widget之后就不能再使用QListWidget的内部选中消息了,为了让外部窗口获取内部Widget的消息时,此时我们需要采用发信号的方式,通知外界,模拟QListWidget消息。
  1. signals:
  2.     void Msg_SendDeleteItemData
复制代码
外部窗口直接操作该消息,使用方法跟普通的方法一致,这里就不再过多介绍Qt中消息机制了。
以上实现QListWidget内嵌自定义窗口的核心功能就说清楚了。
到此这篇关于详解QListWidget如何实现自定义Item效果的文章就介绍到这了,更多相关QListWidget自定义Item内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
17
积分
14
注册时间
2022-12-27
最后登录
2022-12-27

发表于 2025-1-16 09:23:37 | 显示全部楼层
顶顶更健康!!!
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
16
积分
12
注册时间
2022-12-24
最后登录
2022-12-24

发表于 2025-2-23 19:55:35 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
17
积分
14
注册时间
2022-12-26
最后登录
2022-12-26

发表于 前天 05:33 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼
4楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表