QT listView学习

article/2025/9/26 9:41:10

文章目录

  • listView
    • demo说明
    • demo演示
    • model定义
    • 委托 QStyledItemDelegate
    • 总结

listView

listView 对比 tableView 、 treeView来说,最大的不同就是数据结构的不同。treeView是像树一样的层次结构,而listView则就是像链表一样的结构

跟之前的treeView,tableView一样,使用一个简单的demo来演示一下这个过程,同样的我们使用自定义的model定义。

demo说明

实现一个简单的demo,一个item里有图片、按钮、文字三个部分组成,双击文字出现combobox下拉框。按钮分为选中和非选中,单机修改按钮状态,通过一个额外的按钮将所有按钮为选中的那行item删除

demo演示

listViewDemo

model定义

listView的数据结构似乎比较简单,这里直接用一个List链表来当做数据源了

struct ListData 
{bool m_isSelect; QString m_txt;
};class ListModel : public QAbstractListModel
{Q_OBJECTpublic:ListModel();~ListModel();int rowCount(const QModelIndex &parent) const;QVariant data(const QModelIndex &index, int role) const;bool setData(const QModelIndex &index, const QVariant &value, int role);QModelIndex index(int row, int column, const QModelIndex &parent) const;int columnCount(const QModelIndex &parent) const;Qt::ItemFlags flags(const QModelIndex& index) const override;void insertData(const ListData &data);QList<ListData> getData() {return m_listData;}void SetData(const QList<ListData> &data){ beginResetModel();m_listData = data;endResetModel();}private:QList<ListData> m_listData;
};

委托 QStyledItemDelegate

从demo的定义来看,我们需要在一个item上绘制按钮、文本框、图片,这里我们需要使用到委托。

  • 委托是视图中处理用户输入的部件。
  • 视图可以设置委托对象用于处理用户输入。
  • 委托能够提供编辑时需要的上下文环境(编辑器)。
  • 不同委托提供的编辑器类型不同(文本框、单选框等)。
  • 编辑器从模型中获取数据,并将编辑结果返回模型。

委托中的关键函数:

  • createEditor:需要编辑数据时,创建编辑器组件。
  • updateEditorGeometry:更新编辑器组件的大小。
  • setEditorData:通过索引从模型中获取数据。
  • setModelData:将编辑后的新数据返回模型。
  • (print: 描绘画面显示)
  • (editorEvent: 处理鼠标事件)
class MyDelegate : public QStyledItemDelegate
{Q_OBJECT;public:MyDelegate();~MyDelegate();//描绘画面显示void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;//处理鼠标事件bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const;virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;void setEditorData(QWidget *editor, const QModelIndex &index) const ;       //为editor提供编辑的原始数据virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const ;
};

我们需要在paint中绘制我们需要的item

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{QRect retc = option.rect;//这里取的数据 对应model里面的rolebool isSelect = index.data(Qt::UserRole + 1).toBool();QString txt = index.data(Qt::UserRole + 2).toString();{// picture beginQPixmap pix;painter -> save();if (pix.isNull()){	auto success = pix.load("D:/3.ico");}painter->setPen(QColor("#Ff0000"));painter->setPen(Qt::DashDotLine);painter->drawRect(retc);int xoffset = 10;auto szPix = pix.size();auto dy = szPix.height() * 1.0 /  retc.height();auto dx = szPix.width() * 1.0 / retc.width();auto d = std::max(dy, dx);int w = szPix.width() / d;int h = szPix.height() /d;auto x = retc.left() + xoffset;auto y = retc.top() + (retc.height() - h) / 2;painter->drawPixmap(x, y, w, h, pix);// picture end// buttom beging_hight = h;//p11.setX(x);p11 = QPoint(x, (retc.height() - h) / 2);x = x + w + 50;//绘制按钮QRect butRect(x, y, 100, h);p22 = QPoint(x, p11.y());if(isSelect){painter->setPen(QPen(QColor("#8f9ae6")));painter->setBrush(QColor("#8f9ae6"));painter->setPen(QPen(QColor("#000000")));painter->drawRoundedRect(butRect,0,0);painter->drawText(butRect,Qt::AlignCenter,"选中");}else{painter->setPen(QPen(QColor("#FFFFFF")));painter->setBrush(QColor("#FFFFFF"));painter->setPen(QPen(QColor("#000000")));painter->drawRoundedRect(butRect,0,10);painter->drawText(butRect,Qt::AlignCenter,"未选");}//buttom end//text beginbutRect = QRect(w * 3 + 150, y, 200, h);p33 = QPoint(butRect.left(), p11.y());painter->drawRoundedRect(butRect,0,10);painter->drawText(butRect,Qt::AlignCenter,txt);painter->restore();return;}
}

我们需要一个Combobox的Editor来做下拉框

QWidget * MyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{QStringList m_ls_itemtext;m_ls_itemtext<<"第一行"<<"第二行"<<"第三行"<<"第四行"<<"第五行"<<"第六行"<<"第七行"<<"第八行"<<"第九行";QComboBox *editor = new QComboBox(parent);editor->setEditable(true);editor->addItems(m_ls_itemtext);return editor;
}void MyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{if (!index.isValid()){return;}QString value = index.model()->data(index, Qt::EditRole).toString();QComboBox *comboBox = static_cast<QComboBox*>(editor);int icurIndex = comboBox->findText(value);if (icurIndex <= -1){icurIndex = 0;}comboBox->setCurrentIndex(icurIndex);
}

双击选中的下拉框应该在此item的那一行位置

void MyDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{auto xx = option.rect;auto yy = editor->rect();auto x = p33.x() + (200 - editor->geometry().width()) / 2;editor->move(x, xx.top());
}

我们需要把选中下拉框的值给到model

void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{if (dynamic_cast<QComboBox*>(editor)->currentText() == ""){return;}model->setData(index, dynamic_cast<QComboBox*>(editor)->currentText(), Qt::UserRole+2);
}

请添加图片描述

总结

我们通过直接通过一个 List 实现 model 的数据源,通过 paint 来绘制每一个item(每个item里可以放一些内容如按钮),通过 editorEvent 来处理鼠标的点击事件,通过 updateEditorGeometry 来处理更新编辑器的位置, createEditor、setEditorData 来创建和设置一个需要的Editor(下拉框、文本行等等),通过 setModelData 来将editor修改的值返回给model来交互,model值修改了又会反馈给View,达到修改视图的效果


http://chatgpt.dhexx.cn/article/w35n4IUQ.shtml

相关文章

还在用ListView?

还在用Lisview&#xff1f;RecyclerView都已经出来一年多了&#xff01; 想必大家多或多或少的接触过或者了解过RecyclerView&#xff0c;为什么没有用起来&#xff0c;原因大概如下&#xff1f; ListView我用的挺好的&#xff0c;为什么要换RecyclerView&#xff1f;ListView…

ListView用法

ListView是用于显示数据的&#xff0c;先在窗体中拉一个lisview控件&#xff0c;还有一些新增、修改、删除、查询按钮和文本框&#xff0c;控件名称为listview,按钮为btnInsert,btnUpate,btnDeleteOne,btnDelete,btnSelect,文本框的名称为txtName,txtSex,txtPhone,txtAddress,设…

ListView的基础用法

最近学到ListView和RecyclerView&#xff0c;感觉有点难理解&#xff0c;于是自己找到了篇文章&#xff0c;感觉写的挺详细的&#xff08;文章链接在文末&#xff09;&#xff0c;然后自己再整理敲了跑了一遍&#xff0c;总结了一下&#xff0c;方便自己以后回头温习。 一个Li…

Android(14) ArrayAdapter(数组适配器)的三种方法

ArrayAdapter数组适配器用于绑定格式单一的数据&#xff0c;数据源可以是集合或者数组 列表视图(ListView)以垂直的形式列出需要显示的列表项。 实现过程&#xff1a;新建适配器->添加数据源到适配器->视图加载适配器 第一种&#xff1a;直接用ListView组件创建 列表…

Android——列表视图(ListView)

1、什么是ListView&#xff1f;它可以实现怎样的功能&#xff1f; 列表视图是android中最常用的一种视图组件&#xff0c;它以垂直列表的形式列出需要显示的列表项。手机屏幕空间有限&#xff0c;能显示的内容不多。可以借助ListView来显示更多、更丰富的内容。ListView允许用…

ListView详细介绍与使用

前言介绍&#xff1a; 关于 ListView 我们大家都应该是非常的熟悉了&#xff0c;在 Android 开发中是经常用到的&#xff0c;今天就再来回顾一下&#xff0c;ListView 的使用方法&#xff0c;和一些需要优化注意的地方&#xff0c;还有日常开发过程中的一些小技巧和经验。 Li…

Android最常用的控件ListView(详解)

一.ListView简介 在Android开发中&#xff0c;ListView是一个比较常用的控件。它以列表的形式 展示具体数据内容&#xff0c;并且能够根据数据的长度自适应屏幕显示。 二.ListView简单用法 代码部分 1.布局界面 activity_main.xml 代码&#xff1a; <?xml version"1…

ListView的用法

一、 ListView的使用 <ListView>:用于展示大量数据的一种列表视图,通过上下滑动的方式将屏幕外的数据滚动到屏幕内。 数据无法直接传递给ListView,需要适配器 Adapter:作用是将各种数据以合适的形式展示到View上 实例&#xff1a; Food.java: public class Food {priv…

Android原生AlertDialog修改标题,内容,按钮颜色,字体大小等

private void showAlerDialog() {AlertDialog dialog new AlertDialog.Builder(this).setTitle("AlerDialog").setMessage("这是一个AlertDialog").setPositiveButton("确定",null).setNegativeButton("取消",null).create();dialog.…

【android学习】Dialog对话框

1&#xff0c;Dialog 1&#xff09;onCreateDialog(int) 2&#xff09;showDialog(int) 第一次请求时&#xff0c;会从Activity中调用onCreateDialog。 3&#xff09;onPrepareDialog(int,Dialog) 在每次打开对话框时被调用。 4&#xff09;dismissDialog(int) 关闭对话…

Android Dialog使用详解

对话框是提示用户作出决定或输入额外信息的小窗口&#xff0c;通常不会填充整个屏幕&#xff0c;用于进行一些额外交互 Dialog 类是对话框的基类&#xff0c;但应该避免直接实例化 Dialog&#xff0c;而应使用其子类&#xff0c;比如 AlertDialog 此对话框可显示标题、提示信…

Android 修改AlertDialog原生setPositiveButton的字体颜色背景颜色大小边距位置

看效果图&#xff1a; public void lanyaClick(View v) {//点击确定之后转向登陆框LayoutInflater factory LayoutInflater.from(Beforestart.this);//得到自定义对话框final View DialogView factory.inflate(R.layout.item_alert_dialog, null);//创建对话框android.app.Al…

setPositiveButton和setNegativeButton的区别

setPositiveButton和setNegativeButton的区别和setNeutralButton的区别 三者都是AlertDialog弹出框的按钮&#xff0c;都是封装好的button&#xff0c;只是显示的位置不同&#xff0c;项目中可根据情况选择使用&#xff0c;setNegativeButton一般用于确认&#xff0c;setNegat…

GPS(rinex格式)数据解析详细解读

RINEX格式现如今已成为GPS测量应用中的标准数据格式&#xff0c;目前应用最为广泛、最普遍的是RINEX格式的第2个版本&#xff0c;该版本能够用于包括静态和动态GPS测量在内的不同观测模式数据。在该版本中定义了6种不同类型的数据文件&#xff0c;分别用于存放不同类型的数据&a…

2020/10/23 GPS的数据格式学习

GPS的数据格式学习 一、在使用GPS的通过串口向电脑发送数据的时候&#xff0c;要注意GPS数据线的连接&#xff1b; 1.1 VCC接VCC&#xff1b;&#xff08;VCC表示接电源正极&#xff09; 1.2 GND接GND&#xff1b;&#xff08;GND表示接地或接电源负极&#xff09; 1.3 TX接RX…

GPS数据包格式+数据解析

GPS数据包格式数据解析 一、全球时区的划分&#xff1a; 每个时区跨15经度。以0经线为界向东向西各划出7.5经度&#xff0c;作为0时区。即0时区的经度范围是7.5W——7.5E。从7.5E与7.5W分别向东、向西每15经度划分为一个时区&#xff0c;直到东11区和西11区。东11区最东部的经度…

GPS研究---GPS 数据格式

GPS 数据处理时所采用的观测数据是来自观测的 GPS 接收机。由于接收机的型号很多&#xff0c;厂商设计的数据格式各不相同&#xff0c;国际上为了能统一使用不同接收机的数据&#xff0c; 设计了一种与接收机无关的 RINEX(The Receiver Independent Exchange Format)格式&#…

GPS数据格式的分析

文章目录 前言一、数据格式解析1、GPGGA2、GPRMC3、GPCHC4、Kitti数据集oxts数据 二、驱动1、功能包1.1 解析GPGGA1.2 华测GPCHC 2、ROS相关消息类型2.1 sensor_msgs::NavSatFix2.2 gps_common::GPSFix2.3 sensor_msgs::Imu 3、驱动思路 三、时间1、UTC时间2、时间戳 前言 GPS…

GPS GLONASS数据文件类型解析

GPS & GLONASS数据文件类型解析 一、GPS数据格式 RINEX格式现如今已成为GPS测量应用中的标准数据格式&#xff0c;目前应用最为广泛、最普遍的是RINEX格式的第2个版本&#xff0c;该版本能够用于包括静态和动态GPS测量在内的不同观测模式数据。在该版本中定义了6种不同类…

GPS的数据格式介绍

GPRMC&#xff08;建议使用最小GPS数据格式&#xff09; $GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11><CR><LF> 1) 标准定位时间&#xff08;UTC time&#xff09;格式&#xff1a…