首页 > 其他分享 >【Qt笔记】QTableView控件详解

【Qt笔记】QTableView控件详解

时间:2024-09-02 17:22:05浏览次数:10  
标签:控件 return Qt tableView index QTableView row

 

目录

引言 

一、定义与架构

二、主要功能与特点

2.1 显示表格数据

2.2 编辑表格数据

2.3 自定义外观和交互

2.4 数据排序和过滤

2.5 支持拖放操作

2.6 自适应大小

2.7 上下文菜单

2.8 信号与槽

三、常用属性设置

3.1 设置模型

3.2 设置选择模型

3.3 隐藏垂直标题

3.4 设置图标大小

3.5 选择模式

3.6 选择行为

3.7 调整列宽

3.8 设置行高

3.9 交替颜色绘制背景

3.10 自动排序功能

四、应用场景

五、代码示例

5.1 自定义模型(MyTableModel) 

5.2 主窗口和QTableView

5.3 解析

5.4 实现效果 

结语


引言 

QTableView是Qt框架中非常重要的一个控件,专门用于展示和编辑二维表格数据。 

一、定义与架构

  • 定义:QTableView是一个基于模型的视图,用于显示和编辑由QAbstractItemModel派生的模型中的数据。
  • 模型-视图架构:QTableView不直接存储数据,而是通过与数据模型(如QStandardItemModel)的交互来展示和编辑数据。这种架构分离了数据的处理和展示,提高了代码的模块化和可维护性。

二、主要功能与特点

2.1 显示表格数据

主要用于显示二维表格形式的数据,其中数据可以来自文件、数据库查询结果或其他来源。

#include <QApplication>  
#include <QTableView>  
#include <QStandardItemModel>  
  
int main(int argc, char *argv[]) {  
    QApplication app(argc, argv);  
  
    // 创建模型  
    QStandardItemModel *model = new QStandardItemModel(4, 2); // 4行2列  
    model->setHeaderData(0, Qt::Horizontal, "姓名");  
    model->setHeaderData(1, Qt::Horizontal, "年龄");  
  
    // 填充数据  
    for (int row = 0; row < 4; ++row) {  
        for (int column = 0; column < 2; ++column) {  
            QStandardItem *item = new QStandardItem(QString("数据 %1,%2").arg(row).arg(column));  
            model->setItem(row, column, item);  
        }  
    }  
  
    // 创建视图  
    QTableView *tableView = new QTableView;  
    tableView->setModel(model);  
    tableView->show();  
  
    return app.exec();  
}

2.2 编辑表格数据

提供了对表格数据的编辑功能,用户可以直接在表格中进行数据的修改和输入。 编辑功能通常不需要额外的代码,因为QTableView和QStandardItemModel默认支持编辑。

// 与上面的示例相同,因为编辑是默认启用的。  
// 如果需要限制编辑,可以在模型的flags()方法中返回不同的标志。

2.3 自定义外观和交互

  • 允许通过自定义委托(QAbstractItemDelegate)或子类化QTableView来实现自定义单元格的外观和交互。
  • 支持设置不同的视图委托来自定义表格单元格的外观和编辑器,以实现对单元格内容的自定义渲染和编辑。
#include <QStyledItemDelegate>  
#include <QPainter>  
  
class MyDelegate : public QStyledItemDelegate {  
public:  
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {  
        if (!index.isValid()) return;  
  
        QStyleOptionViewItem opt = option;  
        initStyleOption(&opt, index);  
  
        // 自定义绘制逻辑  
        painter->save();  
        painter->setBrush(Qt::lightGray);  
        painter->drawRect(opt.rect);  
        painter->drawText(opt.rect, Qt::AlignCenter, index.data().toString());  
        painter->restore();  
    }  
};  
  
// 在main函数中设置委托  
// ...  
tableView->setItemDelegate(new MyDelegate);  
// ...

2.4 数据排序和过滤

支持用户对表格数据进行排序和过滤,提高数据的查看和管理效率。

// 启用排序  
tableView->setSortingEnabled(true);

过滤通常需要额外的逻辑,这里不展示完整的过滤实现,但您可以通过重写模型的filter()方法或使用代理模型(如QSortFilterProxyModel)来实现。 

2.5 支持拖放操作

允许用户通过拖放操作在表格中移动、复制或重新排列数据。

tableView->setDragEnabled(true);  
tableView->setAcceptDrops(true);  
tableView->setDropIndicatorShown(true);  
  
// 如果需要处理拖放事件,可以重写QTableView的dragEnterEvent()、dragMoveEvent()和dropEvent()

2.6 自适应大小

支持自适应大小,可以根据内容的大小自动调整单元格、行和列的大小,以确保内容适合显示区域。

// 自动调整列宽以适合内容  
tableView->resizeColumnsToContents();  
  
// 自动调整行高到内容的最小高度  
tableView->resizeRowsToContents();

2.7 上下文菜单

可以为QTableView添加上下文菜单,以提供对数据的额外操作(如复制、粘贴、删除等)。

#include <QMenu>  
#include <QAction>  
  
// ...  
QMenu *menu = new QMenu(tableView);  
QAction *copyAction = menu->addAction("复制");  
QAction *pasteAction = menu->addAction("粘贴");  
  
QObject::connect(tableView, &QTableView::customContextMenuRequested, [&](const QPoint &pos) {  
    menu->exec(tableView->viewport()->mapToGlobal(pos));  
    // 这里可以根据选中的动作执行相应的操作,但复制和粘贴需要额外的逻辑  
});  
// ...

2.8 信号与槽

支持信号与槽机制,可以连接特定的信号(如单元格编辑完成、行选中等)到自定义的槽函数,以实现特定的功能。

QObject::connect(tableView->selectionModel(), &QItemSelectionModel::selectionChanged, [&](const QItemSelection &selected, const QItemSelection &deselected) {  
    qDebug() << "选中了新的行或列";  
    // 这里可以根据需要处理选中的项  
});  
  
// 对于编辑完成,通常不需要直接连接信号,因为数据变化会通过模型的dataChanged信号发出  
// 但如果您需要,可以像上面那样连接dataChanged信号

三、常用属性设置

3.1 设置模型

设置模型:通过setModel()函数设置QTableView的数据模型。

#include <QTableView>  
#include <QStandardItemModel>  
  
QTableView *tableView = new QTableView;  
QStandardItemModel *model = new QStandardItemModel(4, 2); // 示例:4行2列  
// 填充模型...  
tableView->setModel(model);

3.2 设置选择模型

设置选择模型:通过setSelectionModel()函数设置选择模型,用于跟踪视图上的选择操作。

#include <QItemSelectionModel>  
  
QItemSelectionModel *selectionModel = new QItemSelectionModel(model);  
tableView->setSelectionModel(selectionModel);  
// 注意:这里的model必须是已经设置给tableView的同一个模型

3.3 隐藏垂直标题

隐藏垂直标题:通过verticalHeader()->hide()函数隐藏垂直标题。

tableView->verticalHeader()->hide();

3.4 设置图标大小

设置图标大小:通过setIconSize()函数设置图标大小。

// 假设您已经有一个委托或自定义项设置了图标  
// 通常这里不需要为QTableView设置图标大小
// 如果需要设置
tableView->setIconSize(QSize(32,32));

3.5 选择模式

选择模式:通过setSelectionMode()函数设置选择模式,如单选、多选、扩展选择等。

tableView->setSelectionMode(QAbstractItemView::SingleSelection); // 单选  
// 或  
tableView->setSelectionMode(QAbstractItemView::MultiSelection); // 多选  
// 或  
tableView->setSelectionMode(QAbstractItemView::ExtendedSelection); // 扩展选择

3.6 选择行为

选择行为:通过setSelectionBehavior()函数设置选择行为,如选择项、选择行或选择列。

// 选择模式设置如上,它影响了用户如何做出选择  
// 对于整行/列的选择,更多的是通过样式或委托来实现视觉上的反馈

3.7 调整列宽

调整列宽:可以通过setColumnWidth()或resizeColumnToContents()函数设置列宽。

tableView->setColumnWidth(0, 100); // 将第一列的宽度设置为100  
// 或  
tableView->resizeColumnToContents(1); // 根据内容自动调整第二列的宽度

3.8 设置行高

设置行高:通过verticalHeader()->setDefaultSectionSize()函数设置默认行高。

tableView->verticalHeader()->setDefaultSectionSize(50); // 设置默认行高为50

3.9 交替颜色绘制背景

交替颜色绘制背景:通过setAlternatingRowColors()函数设置是否使用交替颜色绘制背景。

tableView->setAlternatingRowColors(true); // 启用交替颜色绘制背景

3.10 自动排序功能

自动排序功能:通过setSortingEnabled()函数启用或禁用自动排序功能。

tableView->setSortingEnabled(true); // 启用自动排序功能  
// 注意:为了让自动排序工作,您的模型必须支持排序(如QStandardItemModel)  
// 并且您需要确保模型的列是通过sortRole()能够排序的

四、应用场景

QTableView广泛应用于需要展示和编辑二维数据的场景中,如:

  • 数据库管理工具:用于展示和编辑数据库中的数据。
  • 电子表格应用:类似于Microsoft Excel的应用,用于数据处理和分析。
  • 自定义数据展示:在需要以表格形式展示自定义数据的场景中,如科学计算、统计分析等。
  • 报表生成:用于生成和展示报表数据,支持用户查看和编辑报表中的数据。
  • 数据分析工具:在数据分析工具中,QTableView可以显示和分析大量的数据,支持排序和过滤功能。
  • 任务调度管理:在任务调度管理系统中,QTableView可以显示任务列表,支持用户对任务进行编辑和排序。

五、代码示例

以下是一个使用QTableView控件的完整Qt6代码示例,该示例将包括自定义模型、排序、筛选以及委托(用于自定义单元格渲染)的高级功能实现与解析。

首先,我们需要定义一个自定义模型,该模型将继承自QAbstractTableModel。然后,我们将创建一个主窗口,其中包含QTableView并使用该自定义模型。接下来,我们将实现排序和筛选功能,并最后通过委托来自定义单元格的渲染。

5.1 自定义模型(MyTableModel) 

#include <QAbstractTableModel>  
#include <QVector>  
#include <QVariant>  
  
class MyTableModel : public QAbstractTableModel {  
    Q_OBJECT  
  
public:  
    MyTableModel(QObject *parent = nullptr) : QAbstractTableModel(parent) {  
        // 初始化数据  
        headers << "Name" << "Age" << "Email";  
        data << {"Alice", "30", "[email protected]"}  
             << {"Bob", "25", "[email protected]"}  
             << {"Charlie", "35", "[email protected]"};  
    }  
  
    int rowCount(const QModelIndex &parent = QModelIndex()) const override {  
        Q_UNUSED(parent);  
        return data.size();  
    }  
  
    int columnCount(const QModelIndex &parent = QModelIndex()) const override {  
        Q_UNUSED(parent);  
        return headers.size();  
    }  
  
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {  
        if (!index.isValid() || index.row() >= data.size() || index.column() >= headers.size())  
            return QVariant();  
  
        if (role == Qt::DisplayRole) {  
            const QVector<QString> &row = data[index.row()];  
            return row[index.column()];  
        }  
        return QVariant();  
    }  
  
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override {  
        if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {  
            return headers[section];  
        }  
        return QVariant();  
    }  
  
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override {  
        if (index.isValid() && index.row() < data.size() && index.column() < headers.size() && role == Qt::EditRole) {  
            QVector<QString> &row = data[index.row()];  
            row[index.column()] = value.toString();  
            emit dataChanged(index, index);  
            return true;  
        }  
        return false;  
    }  
  
    Qt::ItemFlags flags(const QModelIndex &index) const override {  
        if (!index.isValid())  
            return Qt::NoItemFlags;  
  
        return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;  
    }  
  
private:  
    QVector<QString> headers;  
    QVector<QVector<QString>> data;  
};

5.2 主窗口和QTableView

#include <QAbstractTableModel>  
#include <QVector>  
#include <QVariant>  
  
class MyTableModel : public QAbstractTableModel {  
    Q_OBJECT  
  
public:  
    MyTableModel(QObject *parent = nullptr) : QAbstractTableModel(parent) {  
        // 初始化数据  
        headers << "Name" << "Age" << "Email";  
        data << {"Alice", "30", "[email protected]"}  
             << {"Bob", "25", "[email protected]"}  
             << {"Charlie", "35", "[email protected]"};  
    }  
  
    int rowCount(const QModelIndex &parent = QModelIndex()) const override {  
        Q_UNUSED(parent);  
        return data.size();  
    }  
  
    int columnCount(const QModelIndex &parent = QModelIndex()) const override {  
        Q_UNUSED(parent);  
        return headers.size();  
    }  
  
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {  
        if (!index.isValid() || index.row() >= data.size() || index.column() >= headers.size())  
            return QVariant();  
  
        if (role == Qt::DisplayRole) {  
            const QVector<QString> &row = data[index.row()];  
            return row[index.column()];  
        }  
        return QVariant();  
    }  
  
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override {  
        if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {  
            return headers[section];  
        }  
        return QVariant();  
    }  
  
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override {  
        if (index.isValid() && index.row() < data.size() && index.column() < headers.size() && role == Qt::EditRole) {  
            QVector<QString> &row = data[index.row()];  
            row[index.column()] = value.toString();  
            emit dataChanged(index, index);  
            return true;  
        }  
        return false;  
    }  
  
    Qt::ItemFlags flags(const QModelIndex &index) const override {  
        if (!index.isValid())  
            return Qt::NoItemFlags;  
  
        return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;  
    }  
  
private:  
    QVector<QString> headers;  
    QVector<QVector<QString>> data;  
};

5.3 解析

自定义模型:MyTableModel类提供了基本的数据存储和访问功能,包括数据获取、设置和头部信息。
主窗口:在MainWindow中,我们创建了QTableView、自定义模型以及一个排序/筛选代理模型。通过代理模型,我们可以轻松地添加排序和筛选功能。
排序和筛选:通过QSortFilterProxyModel,我们可以对模型数据进行排序和筛选,而无需修改原始模型。
委托:虽然在这个示例中没有完全实现,但委托允许您自定义单元格的渲染方式,包括颜色、字体、背景等。

5.4 实现效果 

 

结语

注意事项

  • 在使用QTableView与数据模型配合时,需要注意内存管理,避免内存泄漏。
  • 在处理大量数据时,需要考虑性能优化,如分页加载、异步更新等策略。
  • 为了提供良好的用户体验,需要确保QTableView的响应速度和交互流畅性。

综上所述,QTableView是Qt框架中一个强大且灵活的控件,适用于各种需要展示和编辑二维数据的场景。通过合理地配置和使用,可以构建出功能丰富、交互性强的用户界面。

以上就是关于Qt中QTableView的全部介绍,如有不足与缺陷之处,欢迎评论区留言!!!   

 

标签:控件,return,Qt,tableView,index,QTableView,row
From: https://blog.csdn.net/qq_52924376/article/details/141823346

相关文章

  • 原生JS实现城市选择(输入提示)组控件
    先看效果图:功能需求:国内城市、国际城市切换首字母索引分类输入变化提示HTML代码<divclass="m-list"><divclass="g-sch"><ulclass="f-cbz-blankhide"><liclass="first"><pclass="u-......
  • 1.QT-项目创建
    Qt项目创建项目名称不能有空格和中文项目路径不能有中文路径创建窗口三大基类QWidgetQMainWindowQDialogMain函数中QApplicationa应用程序对象在Qt中有且仅有一个MyWidgetw窗口对象w.show()函数显示窗口returna.exec()进入消息循环机制,阻塞功能.pro文件Qt中的......
  • qt实现三原色滑动条变色
    在qt中有这样一个控件:就是这个HorizontalSlider他的作用相信大家都知道了,也就是通过滑动来改变数值。今天我们就使用这个控件实现一个三原色滑动变色。实现效果:1.创建UI界面 这个就不用多说了,这个大家就按照我的这个去创建就好了。2.编写代码首先我们要初始话我们的......
  • 借助图形控件Aspose.PSD, 在 Java 中绘制几何形状
    最近,我们使用Aspose.PSDforJava实现了绘制诸如日食和线条等形状的功能。然而,这篇博文将更进一步,向您展示如何在Java中绘制几何形状。幸运的是,您可以使用这个Java绘图库以编程方式执行此操作,因为它是一个完整的包,可以在Java应用程序中处理形状。因此,没有额外的要求,我们可......
  • 【QTTabBar】手把手教你QTTabBar命令栏js脚本的自定义开发与实战
    本帖最后由二零一八小王子于2024-8-3121:45编辑<ignore_js_op>众所周知,360压缩有一个解压功能,也就是打开压缩包后点击“一键解压”就可解压完成并且打开目标文件夹。今天这里要实现的是在qttabbar的命令按钮,也就是上面的工具栏处,使用js编写一个一键解压功能。也就是对于一个......
  • 【编程规范具体案例(基于Qt、微软、谷歌和AUTOSAR C++14 参考)】 C++ 编码规范 之程序设
    目录标题基本元素3.1类和结构体3.1.1\[必须]使用恰当的访问修饰符来管理类成员的可见性3.1.2\[必须]在类中合理使用默认的特殊成员函数3.1.3\[必须]提供清晰且尽可能一致的类接口3.1.4\[建议]优先使用初始化列表来初始化类成员3.1.5\[建议]使用抽......
  • QT实战项目之音乐播放器
    项目效果演示myMusicShow项目概述在本QT音乐播放器实战项目中,开发环境使用的是QTCreator5.14版本。该项目实现了音乐播放器的基本功能,例如开始播放、停止播放、下一首播放、上一首播放、调节音量、调节倍速、设置音乐播放模式等。同时还具备搜索功能,通过搜索歌曲名字或......
  • C#自定义控件—转换开关
    C#用户控件之转换开关如何自定义一个转换键(Toggle)?三步绘制一个精美控件:定义属性;画布重绘;添加事件;主要技能:如何自定义属性;画布重绘的一般格式;控件的事件触发过程;技能扩展转换按钮使能时添加二次确认弹框?在From窗体中应用控件时,点击事件没有触发?属性名称在......
  • 【Qt 事件】—— 详解Qt事件处理
    目录 (一)事件介绍 (二)事件的处理(三)按键事件 3.1 单个按键3.2组合按键(四)鼠标事件4.1鼠标单击事件4.2鼠标释放事件 4.3鼠标双击事件4.4鼠标移动事件 4.5滚轮事件 (五) 定时器5.1QTimerEvent类5.2QTimer类(六)事件分发器 6.1概述6.2事件分发器工作......
  • ESP32-C3在MQTT访问时出现“Last error code reported from esp-tls: 0x8001”和问题
    接前一篇文章:ESP32-C3在MQTT访问时出现“Lasterrorcodereportedfromesp-tls:0x8001”和问题的分析(2)上一回讲解了所遇问题log中的“esp-tls:couldn'tgethostnamefor:iot-emqx-pre.nanshe-tech.com:getaddrinfo()returns202,addrinfo=0x0”,再来回顾一下。这一......