【Qt6】列表模型——几个便捷的列表类型

这篇具有很好参考价值的文章主要介绍了【Qt6】列表模型——几个便捷的列表类型。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前面一些文章,老周简单介绍了在Qt 中使用列表模型的方法。很明显,使用 Item Model 在许多时候还是挺麻烦的——要先建模型,再放数据,最后才构建视图。为了简化这些骚操作,Qt 提供了几个便捷类。今天咱们逐个看看。

一、QListWidget

 这厮对应的 List View,用来显示简单的列表。要添加列表项,此类有两个方法

void addItem(const QString &label) ;
void addItem(QListWidgetItem *item);

void addItems(const QStringList &labels);

前两个方法是调用一次就添加一个列表项,新加的列表项将追加到列表末尾;addItems 方法是一次性添加多个项,以字符串列表的方式添加。

对于简单的列表项,可以用第一个方法,直接传个字符串就完事了。第二个方法需要一个 QListWidgetItem 对象,它可以对列表项做一些其他设置,如放个图标,文本对齐方式等。当然,如果你不想用追加模式添加列表项,也可以用插入方法:

void insertItem(int row, const QString &label);
void insertItem(int row, QListWidgetItem *item);
void insertItems(int row, const QStringList &labels);

和 addItem 方法一样,但多了一个 row 参数。因为简单的列表模型只有一个列,所以 row 就是子项的索引。索引从 0 起计算,指定 row 参数表示在此处插入列表项,而列表中原有的元素会向后移一位。比如 5、6、7,在row=1 处插入9,即列表变成 5、9、6、7。

要删除列表项,调用 takeItem 方法。

QListWidgetItem* takeItem(int row)

调用后,指定索引处的项被移除,并返回该项的实例引用(指针类型)。不要调用 removeItemWidget 方法,那个只删除用于显示列表项的组件罢了,列表项并未真正删除。

下面咱们动动手,做个练习。

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    // 实例化组件
    QListWidget *view = nullptr;
    view = new QListWidget;
    // 窗口标题
    view->setWindowTitle("烧烤档常见食物");
    // 窗口大小
    view->resize(255, 200);
    // 添加点子项
    view->addItem("烤羊肺");
    view->addItem("烤年糕");
    // 选创建QListWidgetItem实例,再添加
    QListWidgetItem* item = new QListWidgetItem("烤狗腿");
    view->addItem(item);// 也可以用字符串列表
    QStringList strs;
    strs << "臭豆腐" << "烤鸭肉" << "烤鸡翅";
    view->addItems(strs);

    // 显示窗口
    view->show();
    // 进入事件循环
    return QApplication::exec();
}

第一、二项直接用字符串添加列表项;第三项是先创建 QListWidgetItem 实例,然后再添加;第四、五、六项是通过字符串列表一次性添加的。QStringList 其实就是 QList<QString> 类。

效果如下图所示:

【Qt6】列表模型——几个便捷的列表类型

前面我们提到过一个 removeItemWidget 方法。提到它就得提一下 setItemWidget 方法,因为这俩是青梅竹马的。这一对方法的作用是为某个列表项添加(或删除)一个自定义组件(QWidget 或其子类)。被添加的组件会显示在该列表项上面——其实是覆盖在原有内容上面的。这个方法虽然方便我们为列表项定制 UI,但它不支持动态行为,比如,你如果加一个文本框用来编辑数据,编辑好后数据是不会自动保存的,所有的逻辑都要你自己写代码实现。

咱们拿上面的示例开刀,为最后三项加入个按钮,看看会怎样。代码修改如下:

// 获取最后三项的引用
int len = view->count();  // 猜猜它返回什么
QListWidgetItem* tmpItem1 = view->item(len - 3);
QListWidgetItem* tmpItem2 = view->item(len - 2);
QListWidgetItem* tmpItem3 = view->item(len - 1);
// 弄三个按钮
QPushButton* b1 = new QPushButton;
b1->setText("A");
QPushButton* b2= new QPushButton;
b2->setText("B");
QPushButton* b3 = new QPushButton;
b3->setText("C");
// 调整一下列表项的高度,不然按钮可能显示不全
QSize size(0, 32);
tmpItem1->setSizeHint(size);
tmpItem2->setSizeHint(size);
tmpItem3->setSizeHint(size);
// 设置三个按钮与三个列表项关联
view->setItemWidget(tmpItem1, b1);
view->setItemWidget(tmpItem2, b2);
view->setItemWidget(tmpItem3, b3);
// 为了能发现其中的秘密,咱们让按钮的宽度缩小一点
b1->setFixedWidth(25);
b2->setFixedWidth(25);
b3->setFixedWidth(25);

setSizeHint 方法为项目的“期望”大小设置一个固定的高度,宽度为0表示由布局行为决定;而 32 是高度,告诉容器组件:“我需要32的高度”,毕竟默认的高度可能显示不全按钮。最后,我用 setFixedWidth 方法把三个按钮的宽度给固死了,它的宽度只能是25像素。这么做是为了让大伙看清楚,我们自定义的组件其实就是显示在原有列表项上面的。如下图,你看看,原列表项的文本还在呢。

【Qt6】列表模型——几个便捷的列表类型

不过,上述代码只是方便理解,没什么实际用处。下面咱们做有用的,重新做一下这个示例。

view->connect(view, &QListWidget::currentItemChanged, [=]
(QListWidgetItem* current, QListWidgetItem* previous) -> void{
    // 删除前一个列表项所关联的QWidget
    if(previous)
    {
        view->removeItemWidget(previous);
        // 还原列表项高度
        previous->setSizeHint(QSize(-1, -1));
    }
    // 如当前项为NULL,那后面的代码就没必要运行了
    if(!current){
        return;
    }
    // 为当前项创建QWidget
    QWidget* wg = new QWidget;
    // 设置背景色
    wg->setAutoFillBackground(true);
    wg->setStyleSheet("background: lightgray");
    // 布局
    QHBoxLayout* layout=new QHBoxLayout;
    wg->setLayout(layout);
    // 标签
    QLabel* lb=new QLabel;
    // 标签的文本就是列表项的文本
    lb->setText(current->text());
    layout->addWidget(lb);
    // 加个空白,填补剩余空间
    layout->addStretch(1);
    // 按钮
    QPushButton* btn= new QPushButton("删除");
    layout->addWidget(btn);
    // 套娃,又一个信号连接
    QObject::connect(btn, &QPushButton::clicked, [=](){
        // 当前索引
        int row = view->row(current);
        // 把当前列表项分离出来
        QListWidgetItem* _oldItem = view->takeItem(row);
        // 清除它
        delete _oldItem;
    });
    // 要改一下列表项的高度,不然按钮可能显示不全
    current->setSizeHint(QSize(0, 40));
    // 关联列表项与组件
    view->setItemWidget(current, wg);
});

这里实现的逻辑是:当列表项被选中才显示按钮。现在咱们也知道,setItemWidget 是创建一个自定义组件覆盖在列表项上的,所以,在列表项选中后,显示的自定义组件的背景不能透明,不然就穿帮了。组件里面放一个QLabel 组件显示列表项的文本,然后再放一个“删除”按钮,这样就差不多了。

需要用到 QListWidget 的一个信号:

void currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);

这个信号正符合咱们的需求,current 表示当前项(99.9% 的情况下就是被选中的项),previous 是前一个项——即被取消选择的项。有了这两个参数,咱们就可以用 removeItemWidget 方法删除 previous 关联的 Widget,并为 current 关联新的 Widget。

currentItemChanged 信号连接的 lambda 表达式内部又嵌套了一个 lambda 表达式—— 连接按钮的 clicked 信号。

QObject::connect(btn, &QPushButton::clicked, [=](){
    // 当前索引
    int row = view->row(current);
    // 把当前列表项分离出来
    QListWidgetItem* _oldItem = view->takeItem(row);
    // 清除它
    delete _oldItem;
});

删除列表项时,takeItem 方法返回指定索引处的列表项指针。正因为这货需要的参数是索引,所以不得不调用 row 方法选获取 current 的索引,再传给 takeItem 方法。列表项被移除后会返回其指针,因为这时候我们不需要它了,所以得 delete 掉其指向的对象。

运行程序后,选中“臭豆腐”。

【Qt6】列表模型——几个便捷的列表类型

然后单击右边的“删除”按钮,臭豆腐就没了。

【Qt6】列表模型——几个便捷的列表类型

 

二、QTableWidget

QTableWidget 类派生自 QTableView,也是一个便捷类,可以不创建模型对象而直接添加数据。对应的列表项类型是 QTableWidgetItem。注意,一个 QTableWidgetItem 仅表示一个单元格的数据,所以,如果数据表格有两行两列,那么,你得向里面四个 item。

在添加列表项之前,要先调用:

setRowCount—— 设置表格共有几行;

setColumnCount—— 设置表格共有多少列。

然后设置标题。包括列标题、行标题。一般设置列标题就可以了,行标题通常不用设置(默认显示行号)。

setHorizontalHeaderLabels—— 设置列标题;

setVerticalHeaderLabels—— 设置行标题。

不管是行还是列标题,都可以使用字符串列表(QStringList)来传递,有几行/列就设置几个值。

设置完上述基本参数后,就可以用 setItem 方法来设置每个单元格的数据了。方法原型如下:

void setItem(int row, int column, QTableWidgetItem *item);

row 表示行索引,column 表示列索引,索引从 0 算起。

 

接下来咱们做个演示:

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    // 创建组件实例
    QTableWidget* viewWindow = new QTableWidget;
    // 设置标题和大小
    viewWindow->setWindowTitle("经典语录");
    viewWindow->resize(350, 270);
    // 设定行数和列数
    viewWindow->setColumnCount(3);  // 三列
    viewWindow->setRowCount(4);     // 四行
    // 先弄好列标题
    viewWindow->setHorizontalHeaderLabels({"编号", "句子", "伤害指数"});
    // 创建列表项
    // 注意,每个QTableWidgetItem代表一个单元格
    // 第一行
    viewWindow->setItem(0, 0, new QTableWidgetItem("001"));
    viewWindow->setItem(0, 1, new QTableWidgetItem("你就长这个样子啊?"));
    viewWindow->setItem(0, 2, new QTableWidgetItem("2"));
    // 第二行
    viewWindow->setItem(1, 0, new QTableWidgetItem("002"));
    viewWindow->setItem(1, 1, new QTableWidgetItem("你进化到灵长目动物了吗?"));
    viewWindow->setItem(1, 2, new QTableWidgetItem("3"));
    // 第三行
    viewWindow->setItem(2, 0, new QTableWidgetItem("003"));
    viewWindow->setItem(2, 1, new QTableWidgetItem("你脑细胞够不够用?"));
    viewWindow->setItem(2, 2, new QTableWidgetItem("5"));
    // 第四行
    viewWindow->setItem(3, 0, new QTableWidgetItem("004"));
    viewWindow->setItem(3, 1, new QTableWidgetItem("学姐,你有头吗?"));
    viewWindow->setItem(3, 2, new QTableWidgetItem("10"));
    // 显示视图窗口
    viewWindow->show();
    return QApplication::exec();
}

运行结果如下:

【Qt6】列表模型——几个便捷的列表类型

 

三、QTreeWidget

 QTreeWidget 类针对的就是树形结构的列表,是 QTreeView 的子类。它对应的列表项是 QTreeWidgetItem 类。

不过这里要注意的是,QTreeWidgetItem 虽然表示树形数据中的一个节点,但它在形式上就像一行数据。因为它可以包含多个列。Qt 的 Tree 视图是可以展示多列的。

下面咱们先做个单列的 Tree 视图。

int main(int argc, char** argv)
{
    QApplication app(argc, argv);

    // 创建视图窗口
    QTreeWidget* view = nullptr;
    view = new QTreeWidget;
    // 先来几个顶层节点
    QTreeWidgetItem* item1 = new QTreeWidgetItem({""});
    QTreeWidgetItem* item2 = new QTreeWidgetItem({""});
    QTreeWidgetItem* item3 = new QTreeWidgetItem({""});
    QTreeWidgetItem* item4 = new QTreeWidgetItem({""});
    QTreeWidgetItem* item5 = new QTreeWidgetItem({""});
    QTreeWidgetItem* item6 = new QTreeWidgetItem({""});
    // 给顶层节点添加子节点
    // 秦朝
    item1->addChild(new QTreeWidgetItem({"胡亥"}));
    item1->addChild(new QTreeWidgetItem({"扶苏"}));
    item1->addChild(new QTreeWidgetItem({"辛追"}));
    item1->addChild(new QTreeWidgetItem({"项籍"}));
    // 汉朝
    item2->addChildren({
        new QTreeWidgetItem({"霍光"}),
        new QTreeWidgetItem({"刘向"}),
        new QTreeWidgetItem({"司马迁"})
    });
    // 晋朝
    item3->addChildren({
        new QTreeWidgetItem({"卫铄"}),
        new QTreeWidgetItem({"司马承"}),
        new QTreeWidgetItem({"谢安"}),
        new QTreeWidgetItem({"王导"})
    });
    // 隋朝
    item4->addChild(new QTreeWidgetItem({"杨坚"}));
    item4->addChild(new QTreeWidgetItem({"史万岁"}));
    item4->addChild(new QTreeWidgetItem({"王通"}));
    // 唐朝
    item5->addChildren({
        new QTreeWidgetItem({"上官婉儿"}),
        new QTreeWidgetItem({"李龟年"}),
        new QTreeWidgetItem({"张旭"}),
        new QTreeWidgetItem({"杜牧"}),
        new QTreeWidgetItem({"武三思"}),
        new QTreeWidgetItem({"李靖"})
    });
    // 宋朝
    item6->addChildren({
        new QTreeWidgetItem({"王坚"}),
        new QTreeWidgetItem({"贾似道"}),
        new QTreeWidgetItem({"司马光"}),
        new QTreeWidgetItem({"宋慈"}),
        new QTreeWidgetItem({"张士逊"})
    });
    // 将顶层节点添加到QTreeWidget中
    view->addTopLevelItems({
        item1,
        item2,
        item3,
        item4,
        item5,
        item6
    });
    // 隐藏标题栏
    view->setHeaderHidden(true);
    // 设置窗口标题
    view->setWindowTitle("中华名人表");
    // 显示窗口
    view->show();

    return QApplication::exec();
}

QTreeWidgetItem 类的构造函数可以使用字符串列表来初始化显示的文本。原型如下:

explicit QTreeWidgetItem(const QStringList &strings, int type = Type);

在赋值的时候,可以直接用 { },例如

QTreeWidgetItem({"天时", "地利", "人和"});

在上面例子中,因为咱们这次用的只是一列,所以传一个字符串元素就可以了。

QTreeWidgetItem 要添加子节点,可以用这些方法:

// 一次只加一个节点,新节点追加到末尾
void addChild(QTreeWidgetItem *child);

// 一次只添加一个节点,但可以指定新节点插入到哪个位置
void insertChild(int index, QTreeWidgetItem *child);

// 一次可以添加多个节点,参数是个列表对象
void addChildren(const QList<QTreeWidgetItem*> &children);

// 一次可以添加多个节点,能指定插入位置
void insertChildren(int index, const QList<QTreeWidgetItem*> &children);

QTreeWidget 组件用以下方法添加顶层节点:

// 添加一个节点,追加到末尾
void addTopLevelItem(QTreeWidgetItem *item);

// 添加一个节点,可以指定插入位置
void insertTopLevelItem(int index, QTreeWidgetItem *item);

// 添加多个节点,追加到末尾
void addTopLevelItems(const QList<QTreeWidgetItem*> &items);

// 添加多个节点,可指定插入位置
void insertTopLevelItems(int index, const QList<QTreeWidgetItem*> &items);

运行效果如下:

【Qt6】列表模型——几个便捷的列表类型

 

QTreeWidget 类也有 setItemWidget、removeItemWidget 方法。这个就不必多介绍了,和上面 QListWidget 类的一个意思,就是用一个自定义 Widget 显示在数据项上面。

下面咱们做个多列的 Tree 视图。

#include <qapplication.h>
#include <qtreewidget.h>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QTreeWidget * view = new QTreeWidget;
    // 设置列数
    view->setColumnCount(4);
    // 顶层节点
    auto itemA = new QTreeWidgetItem({"潜水部"});
    auto itemB = new QTreeWidgetItem({"洗脑部"});
    auto itemC = new QTreeWidgetItem({"韭菜部"});
    // 子节点
    itemA->addChildren({
        new QTreeWidgetItem({"01", "梁酷裆", "经理", "6"}),
        new QTreeWidgetItem({"02", "王晓意", "秘书", "3"})
    });
    itemB->addChildren({
        new QTreeWidgetItem({"03", "于三明", "经理", "4"}),
        new QTreeWidgetItem({"04", "周日清", "经理助理", "3"}),
        new QTreeWidgetItem({"05", "费洁合", "跟办", "5"})
    });
    itemC->addChildren({
        new QTreeWidgetItem({"06", "安德诗", "经理", "3"}),
        new QTreeWidgetItem({"07", "李殿驰", "助理", "2"}),
        new QTreeWidgetItem({"08", "易更菁", "文员", "3"})
    });
    // 添加顶层节点到视图
    view->addTopLevelItems({itemA, itemB, itemC});
    // 设置列标题
    view->setHeaderLabels({"编号", "姓名", "职务", "工龄"});
    // 设置窗口标题
    view->setWindowTitle("啃瓜装饰服务有限公司员工表");
    // 显示窗口
    view->show();

    return QApplication::exec();
}

效果如下:

【Qt6】列表模型——几个便捷的列表类型

代码就不用多解释了吧,单列和多列的节点用法是一样的,只是传递给 QTreeWidgetItem 类构造函数的列表元素个数不同罢了。文章来源地址https://www.toymoban.com/news/detail-711394.html

到了这里,关于【Qt6】列表模型——几个便捷的列表类型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt6之模型和视图

    MVC是Model-View-Controller,即 模型 (Model)、 视图 (View)、 控制器 (Controller)。 模型 :用于管理数据; 视图 :就是呈现在用户面前的界面外观,视图负责把模型中的数据显示给用户; 控制器 :用于处理用户在用户界面的输入; MVC本质上目的是数据处理和显示分离,以提高灵活性

    2024年02月15日
    浏览(39)
  • 【QT性能优化】QT性能优化之QT6框架高性能模型视图代理框架千万级数据表分页查询优化

    QT性能优化之QT6框架高性能模型视图代理框架千万级数据表分页查询优化 简介 本文介绍了QT模型视图代理框架中的QT表格控件和QT数据库模块中的QT数据库查询模型结合使用的一个应用实践案例:QT高性能表格控件分页展示千万行数据。本文介绍了这个应用实践案例的运行效果

    2024年02月14日
    浏览(53)
  • [vscode]vscode运行cmake时候exe不执行而且前面多一些字符

    遇到一个奇怪问题,你单独打开cmd去执行vscode编译过程序没问题,但是你在vscode确不会执行,这是因为vscode没有读取到电脑环境变量导致加载DLL失败,但是在vscode终端不会给你提示少DLL,需要你自己把DLL复制到exe目录即可解决问题。还有个问题你运行代码时候,终端会多一些字

    2024年02月13日
    浏览(48)
  • QT6 for android 安装教程记录(版本Qt6.5.2)

    本文记录首次安装QT for andriod的详细记录。 网上的信息和资料非常多,收集和整理以及遇到的问题也各异,对新手首次接触相关开发和部署环境并不是清晰,因此,特将相关详细配置记录。 首先,开发QT for andriod 不建议使用QT5.15的版本,因为该版本不能区分相关的CPU架构,而

    2024年02月03日
    浏览(52)
  • 【C#】【System.Linq】一些便捷的数据处理方法(Range、Select)

    因为用习惯了Python中一些便捷的方法,随即查询C#中有没有类似的。  一、Range()方法 在Python中,range(Start,End,Step)可以直接生成一个可迭代对象,便用于需要循环多次处理某些代码块: (注:Range方法中的End是开区间,range(1,10)实际的取值是(1 ~ 9))   在C#中也

    2024年02月08日
    浏览(41)
  • 【QT教程】QT6物联网应用

    QT6物联网应用 使用AI技术辅助生成 QT界面美化视频课程 QT性能优化视频课程 QT原理与源码分析视频课程 QT QML C++扩展开发视频课程 免费QT视频课程 您可以看免费1000+个QT技术视频 免费QT视频课程 QT统计图和QT数据可视化视频免费看 免费QT视频课程 QT性能优化视频免费看 免费QT视

    2024年04月25日
    浏览(39)
  • Qt6中使用Qt Charts

     官方文档:Qt Charts 6.5.2           如果你是使用  CMake 构建的,则应在  CMakeLists.txt  中添加如下两行代码:         其中  mytarget 为你的项目名称。一共2处改动,如下截图:         改完之后,你在 .cpp 文件导入库名,就可以开始画图了。         关于怎么画出一个可

    2024年02月09日
    浏览(41)
  • 【Qt6】QStringList

    2023年10月31日,周二上午 QStringList 是 Qt 中的一个类,用于存储一组字符串。它提供了一些方便的方法来操作和管理字符串列表。 QStringList 可以用于存储任意数量的字符串,并提供了一些常用的操作,例如添加、删除、查找、排序等。它是基于 QStringList 类的 QVectorQString 的封装

    2024年02月06日
    浏览(36)
  • Qt5和Qt6的区别

    Qt4和Qt5的区别 之前有做过将项目从QT4迁移到QT5的操作,所以写了一篇QT4和Qt5的区别。在最近这一年接触过Qt6后,所以想要介绍一下Qt6和Qt5的区别,通过自己的试用感受和结合网上各路大佬的点拨,有了一个大概的了解。 各稳定版本: Qt4: 4.8.7 4.X 系列终结版本 Qt5 : 5.6 LTS 长期

    2024年01月18日
    浏览(55)
  • 【Qt6】嵌套 QWindow

    在上个世纪的文章中,老周简单介绍了 QWindow 类的基本使用——包括从 QWindow 类派生和从 QRasterWindow 类派生。 其实,QWindow 类并不是只能充当主窗口用,它也可以嵌套到父级窗口中,变成子级对象。咱们一般称之为【控件】。F 话不多讲,下面咱们用实际案例来说明。 这个例

    2024年02月02日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包