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

首先,我们来看以下实现的最终效果吧!

我觉得这并不是一个很难得问题,最近新招了一个应届生,发现在实现上述效果时,被困扰住了,是不是刚刚接触Qt的这种稍微有难度的界面时,都会有些无头绪呢?

所以,我打算分享给大家实现的思路,以及会出现的问题,就我一个开发5年C++的员工而言,针对新手会遇到哪些不懂的问题。

当前的开发环境:win10 VS2017 + Qt5.14.2 x64

在实现过程中新手会出现的难点,如下

1:如何在QListWidget中添加带有按钮、文本等其它控件的一条数据?

2:选中每一条之后如何响应?QListWidget自带的item响应为什么不生效?

3:如何选中删除按钮并通知QListWidget做出具体的响应?

就根据上述三个问题,边讲述问题边实现带有自定义控件的Item内容吧!

在使用QListWidget插入一条数据时,默认的方式,如下:

ui.listWidget->insertItem(0, "Text Content"); //方法1
ui.listWidget->addItem("Text Content"); //方法2

使用上述代码是无法实现的,因为参数中只能添加QString类型的字符串,那么该如何实现添加自定义项呢?

在QListWidget类中提供了叫做QListWidgetItem的子类,用于实现自定义的item。

这时,我们就需要重新定义一个类,并且将该类与ListWidgetItem进行绑定,就可以实现每一行的item上展示属于我们自定义的格式了。

例子中展示的item中显示了一个选择框、文件名称以及删除按钮。

在这里,采用了QCheckBox以及QPushButton两个按钮实现的。

有人会询问:文件名称不应该使用QLabel控件表示吗?

回答是:当前可以使用QLabel控件显示文件名称,这里采用QCheck主要是想要展示文件的图标,根据不同的文件名后缀显示不同的图标。

自定义Widget

该类继承自QWidget。假设叫做:CustomItem

有些新手会直接创建一个纯的C++类,这样做肯定是有问题的,当我们在外部使用当前自定义类时,你会发现,为什么新创建的类会单独分出来呢?

如果直接使用纯C++类,还有另一个至关重要的问题,当前类需要进行消息交互时,你该如何传递给外部调用者呢?回调吗?是不是有点大材小用呢?

class CustomItem : public QWidget
{
	Q_OBJECT

public:
	CustomItem(QWidget *parent);
	~CustomItem();
private:
	QCheckBox* m_checkName; //文件名
	QCheckBox* m_checkSelect; //选择
	QPushButton* m_btnDelete; //删除

};

自定义类CustomItem中创建了三个控件变量,分别表示了:选择框、文件名称以及删除按钮。

就是文章开始显示效果图的三个控件了。

接下来,需要定义一个外部调用接口,插入一条有效数据,假设接口名称是:AddINewtemData

class CustomItem : public QWidget
{
	Q_OBJECT

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

};

AddINewtemData 参数

参数1:代表的是当前自定义widget属于QListWidget的行编号,用于后续消息传递使用。

参数2:需要展示的文件名称

根据用户传入的文件名称,根据文件后缀展示不同的图标。

void CustomItem::AddINewtemData(int nRow, QString qPath)
{
	m_nRow = nRow; //记录当前自定义widget对应的QListWidget的行号

	//根据路径名,获取文件名称,并设置
	QFileInfo info(qPath);
	QString qsFileName = info.fileName();
	m_checkName->setText(qsFileName);
	//获取文件后缀
	QString qsCheckStyle = "";
	if (info.suffix() == "mp4") //视频文件
	{
            //自定义QCheckBox风格
	}
	else if (info.suffix() == "png") //图片文件
	{
            //自定义QCheckBox风格
	}
	else if (info.suffix() == "xlsx") //表格文件
	{
            //自定义QCheckBox风格
	}
	else if (info.suffix() == "pdf")
	{
            //自定义QCheckBox风格
	}
	else //文档文件
	{
            //自定义QCheckBox风格
	}
	m_checkName->setStyleSheet(qsCheckStyle);
}

构造完自定义widget类之后,接下来就需要将该类与QListWidgetItem进行绑定,显示到QListWidget上去。

外部调用方法,如下:

int nCount = ui.listWidget->count();

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

QListWidgetItem* item = new QListWidgetItem;
item->setSizeHint(QSize(48, 48));
ui.listWidget->addItem(item);
ui.listWidget->setItemWidget(item, widget);

自定义CustomItem响应

上述功能可以实现QListWidget中展示自定义的widget之后,该如何点击QListWidget中的每一条做出不同的响应呢?

此时,我们对每一行的QListWigetItem绑定自定义类之后,是无法响应QListWidget自身的选择消息的!这一点需要大家记清楚了。

那么,该怎么触发呢?

针对于每一个QWidget类,只要是继承自QWidget,都会有鼠标的四大响应:

virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void mouseDoubleClickEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);

当鼠标在自定义类做了点击效果后,肯定可以在鼠标按下事件中获取点击响应的。

所以,在自定义类CustomItem中需要重写QWidget的系统消息:mousePressEvent

void CustomItem::mousePressEvent(QMouseEvent *event)
{
    QWidget::mousePressEvent(event);
}

断点设在该响应函数中时,肯定是会触发的,如果不可以肯定是当前widget处于禁用状态,或者是被遮盖住了。

这里还有一个隐藏问题:有些同学在点击自定义窗口时会发现这样一个奇怪的现象,为什么点击有些区域是响应mousePressEvent消息的,而点击有些区域是不响应呢?

以下是重中之重了!!

这就是前一段话提到的内容了,当前widget不触发时,肯定是禁用或者是被遮挡住了。

在我们这个自定义Widget中有三个活跃的控件,两个QCheck,一个QPushButton,当我们的鼠标在任意控件上点击时,此时的点击响应应该是响应到子控件上,而不是自定义的Widget(CustomItem)上。

为了让鼠标点击任何控件时,所有的响应都响应到父类Widget,也就是CustomItem上时,我们应该对支持鼠标响应操作的控件做特殊处理

setAttribute(Qt::WA_TransparentForMouseEvents)

每个控件都要设置以上的操作,当前控件只是用来显示,不做任何消息处理,是当前窗口做的消息处理

自定义Widget控件响应并通知外界处理

下面,来说一说第三个重点问题,如何通知外界处理。

我们使用了自定义的Widget之后就不能再使用QListWidget的内部选中消息了,为了让外部窗口获取内部Widget的消息时,此时我们需要采用发信号的方式,通知外界,模拟QListWidget消息。

signals:
    void Msg_SendDeleteItemData

外部窗口直接操作该消息,使用方法跟普通的方法一致,这里就不再过多介绍Qt中消息机制了。

以上实现QListWidget内嵌自定义窗口的核心功能就说清楚了。

到此这篇关于详解QListWidget如何实现自定义Item效果的文章就介绍到这了,更多相关QListWidget自定义Item内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • pyqt qlistwidget改变item颜色的操作

    我就废话不多说了,大家还是直接看代码吧~ 实例: from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * import sys class Win(QWidget): def __init__(self): super(Win, self).__init__() self.setObjectName("

  • PyQt QListWidget修改列表项item的行高方法

    百度,谷歌之后都说用setHintSize(self,QCore.QSize(width,height)),然并卵,后来用qss修改就可以了,具体用法如下 以上这篇PyQt QListWidget修改列表项item的行高方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • PyQt5 在QListWidget自定义Item的操作

    效果图 自定义一个Item 新建一个QWidget对象 在QWidget内添加Layout 在Layout内添加要的控件 为QWidget设置Layout 新建一个QListWidgetItem并调整大小 为QListWidgetItem设置QWidget 创建布局 首先我们创建一个最基本的布局, 只有一个listWidget和一个pushButton 实现点击button后在listWidget中添加数据 class Windows(QMainWindow, Ui_MainWindow): d

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

    首先,我们来看以下实现的最终效果吧! 我觉得这并不是一个很难得问题,最近新招了一个应届生,发现在实现上述效果时,被困扰住了,是不是刚刚接触Qt的这种稍微有难度的界面时,都会有些无头绪呢? 所以,我打算分享给大家实现的思路,以及会出现的问题,就我一个开发5年C++的员工而言,针对新手会遇到哪些不懂的问题. 当前的开发环境:win10 VS2017 + Qt5.14.2 x64 在实现过程中新手会出现的难点,如下 1:如何在QListWidget中添加带有按钮.文本等其它控件的一条数据? 2:选中每

  • 详解Android如何实现自定义的动画曲线

    目录 前言 Curve 类定义 实例解析 正弦动画曲线 总结 前言 最近在写动画相关的篇章,经常会用到 Curve 这个动画曲线类,那这个类到底怎么实现的?如果想自己来一个自定义的动画曲线该怎么弄?本篇我们就来一探究竟. 曲线 Curve 类定义 查看源码, Curve 类定义如下: abstract class Curve extends ParametricCurve<double> {   const Curve();   @override   double transform(dou

  • 详解Flutter如何完全自定义TabBar

    目录 前言 实现过程 完整代码 总结 前言 在App中TabBar形式交互是非常常见的,但是系统提供的的样式大多数又不能满足我们产品和UI的想法,这篇就记录下在Flutter中我在实现自定义TabBar的一个思路和过程,希望对你也有所帮助~ 先看下我最终的效果图: 实现过程 首先我们先看下TabBar的构造方法: const TabBar({ Key? key, required this.tabs,// tab组件列表 this.controller,// tabBar控制器 this.isS

  • 详解Java如何实现自定义注解

    目录 概念 作用 JDK中预定义的一些注解 注解生成文档案例 自定义注解 格式 本质 属性:接口中的抽象方法 元注解:用于描述注解的注解 在程序使用(解析)注解:获取注解中定义的属性值 案例:通过自定义注解定义一个简单的测试框架 总结 概念 概念:说明程序的.给计算机看的 注释:用文字描述程序的.给程序员看的 定义:注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举是在同一个层次.它可以声明在包.类.字段.方法.局部变量.方法

  • 详解Vue中的自定义指令

    除了默认设置的核心指令( v-model 和 v-show ),Vue 也允许注册自定义指令.在Vue里,代码复用的主要形式和抽象是组件.然而,有的情况下,仍然需要对纯 DOM 元素进行底层操作,这时候就会用到自定义指令.本文将详细介绍Vue自定义指令 指令注册 以一个input元素自动获得焦点为例,当页面加载时,使用autofocus可以让元素将获得焦点 .但是autofocus在移动版Safari上不工作.现在注册一个使元素自动获取焦点的指令 指令注册类似于组件注册,包括全局指令和局部指令两

  • 详解Python中的自定义密码验证

    目录 在测试:nut_and_bolt:️之前 试验contains_character TestContainsCharacter字符 试验is_valid_size TestIsValidSize 试验is_valid_password TestIsValidPassword 重构is_valid_password 结论 这些帖子将分为三个部分. 1.密码验证功能 2.重构密码验证函数 3.对密码验证功能进行单元测试 这是Python系列中自定义密码验证的第三部分,也是最后一部分.我们将看看

  • 详解Android Material Design自定义动画的编写

    新的动画Api,让你在UI控件里能创建触摸反馈,改变View的状态,切换activity的一系列自定义动画 具体有: 响应View的touch事件的触摸反馈动画 隐藏和显示View的循环展示动画 两个Activity间的切换动画 更自然的曲线运动的动画 使用View的状态更改动画,能改变一个或多个View的属性 在View的状态更改时显示状态列表动画 这些new animations Api,已内置在标准Widget中,如Button.在自定义view时也可使用这些api 动画在Material

  • 详解iOS应用中自定义UIBarButtonItem导航按钮的创建方法

    iOS系统导航栏中有leftBarButtonItem和rightBarButtonItem,我们可以根据自己的需求来自定义这两个UIBarButtonItem. 四种创建方法 系统提供了四种创建的方法: 复制代码 代码如下: - (instancetype)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(id)target action:(SEL)action; - (instancetype)init

  • 详解JavaScript中的自定义事件编写

    我们可以自定义事件来实现更灵活的开发,事件用好了可以是一件很强大的工具,基于事件的开发有很多优势(后面介绍). 与自定义事件的函数有 Event.CustomEvent 和 dispatchEvent. 直接自定义事件,使用 Event 构造函数: var event = new Event('build'); // Listen for the event. elem.addEventListener('build', function (e) { ... }, false); // Disp

  • 详解Angular中实现自定义组件的双向绑定的两种方法

    在 Angular 中,对于表单元素,通过 [(ngModel)] 即可以简单地实现双向绑定.对于自定义组件而言,希望实现同样的效果可以怎么做呢? 1 实现自定义组件的 ngModel 指令 如果希望自定义组件能够具有与表单元素相同的 ngModel 效果,可以通过在组件内实现 ControlValueAccessor 接口达到目的. 对于 [(ngModel)] ,需要至少实现该接口的如下方法: interface ControlValueAccessor { writeValue(obj:

随机推荐