子类化QAbstractTableModel,实现table列排序和整列拖动功能

2023-11-16

子类化QAbstractTableModel,实现table列排序和整列拖动功能

本程序基于Qt5.9.9,Qt creator 4.11.0实现。
效果图

在这里插入图片描述

1、子类化QAbstractTableModel

主要是实现QAbstractTableModel中的rowCount、columnCount、data这三个纯虚函数;

headerData是用来实现上方和左侧的头显示的接口,这里我也重新override了。

下面看主要代码:

头文件MyTableModel.h

#ifndef MYTABLEMODEL_H
#define MYTABLEMODEL_H
#include <QAbstractTableModel>
#include <vector>
#include <QDateTime>

typedef struct StuInfo
{
    QString id_;
    QString name_;
    int age_;
    float score_;
    QDateTime time_;
}STUINFO;

class MyTableModel : public QAbstractTableModel
{
public:
    MyTableModel(QObject *parent = 0);
    // 设置数据源
    void setStudents(const std::vector<STUINFO> &students);
    // 主要override的函数
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role) const override;
    QVariant headerData(int section, Qt::Orientation orientation,
                        int role = Qt::DisplayRole) const override;
    // 排序用到的函数
    void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
    bool lessThan(const QVariant &left,const QVariant &right);

private:
    // 数据源
    std::vector<STUINFO> m_students;
    // 上方表格显示的头名称
    QStringList headers;
};

#endif // MYTABLEMODEL_H

rowCount、columnCount、data、headerData接口的具体实现

int MyTableModel::rowCount(const QModelIndex &parent) const
{
    // 源数据数量
    return m_students.size();
}

int MyTableModel::columnCount(const QModelIndex &parent) const
{
    // 头数量
    return headers.size();
}

QVariant MyTableModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();
    switch(role){
            // 对齐模式
    case Qt::TextAlignmentRole:
        return int(Qt::AlignHCenter | Qt::AlignVCenter);
    case Qt::DisplayRole:
        int row = index.row();
        int column = index.column();
        switch(column){
        case 0:
            return m_students[row].id_;
        case 1:
            return m_students[row].name_;
        case 2:
            return m_students[row].age_;
        case 3:
            return m_students[row].score_;
        case 4:
            return m_students[row].time_;
        default:
            return QVariant();
        }
    }
    return QVariant();
}

QVariant MyTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role != Qt::DisplayRole)
        return QVariant();
    if(orientation == Qt::Horizontal){
        // 水平方向的就是上方显示的header
        return headers[section];
    }else{
        // 垂直方向就是左侧显示的header,这里用section+1的方式返回,效果就是1,2....
        return section + 1;
    }
    return QVariant();
}

2、实现案列排序功能

首先需要在QTableView上设置可以排序,使用setSortingEnabled(true)这个接口进行设置

然后override QAbstractTableModel接口中的sort接口实现自己的排序方式,代码如下:

void MyTableModel::sort(int column, Qt::SortOrder order)
{
    if(m_students.empty() || column < 0 || column >= headers.size())
        return;

    const bool is_asc = (order == Qt::AscendingOrder);

    std::sort(m_students.begin(),m_students.end(),
              [column,is_asc,this](const STUINFO &left, const STUINFO &right){
       QVariant left_val, right_val;
       switch(column){
       case 0:
           left_val = left.id_;
           right_val = right.id_;
           break;
       case 1:
           left_val = left.name_;
           right_val = right.name_;
           break;
       case 2:
           left_val = left.age_;
           right_val = right.age_;
           break;
       case 3:
           left_val = left.score_;
           right_val = right.score_;
           break;
       case 4:
           left_val = left.time_;
           right_val = right.time_;
           break;
       }
       return is_asc ?
                   lessThan(left_val, right_val):
                   lessThan(right_val,left_val);
    });
    dataChanged(index(0,0),index(m_students.size()-1,headers.size()-1));
}

bool MyTableModel::lessThan(const QVariant &left, const QVariant &right)
{
    qDebug() << "^^^^^^" << left.userType() << "******" << right.userType() << "&&&&" << QMetaType::UnknownType;
    if(left.userType() == QMetaType::UnknownType)
        return false;
    if(right.userType() == QMetaType::UnknownType)
        return true;
    switch (left.userType()) {
    case QMetaType::Int:
        return left.toInt() < right.toInt();
    case QMetaType::Float:
        return left.toFloat() < right.toFloat();
    case QMetaType::Double:
        return left.toDouble() < right.toDouble();
    case QMetaType::QDateTime:
        return left.toDateTime() < right.toDateTime();
    case QMetaType::QString:
        break;
    default:
        break;
    }
    return left.toString().localeAwareCompare(right.toString()) < 0;
}

详情可参考:https://blog.csdn.net/gongjianbo1992/article/details/108674875

3、实现整列拖拽功能

只需要在QTableView设置horizontalHeader的setSectionMovable为true便可。

代码如下:main.cpp

#include <QApplication>
#include "mytablemodel.h"
#include <QTableView>
#include <QHeaderView>
#include <vector>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    std::vector<STUINFO> stus;
    stus.push_back({"1","wangqiang",23,120, QDateTime::fromString("20170112 12:13:14","yyyyMMdd HH:mm:ss")});
    stus.push_back({"2","liuwei",21,110.2, QDateTime::fromString("20170113 12:13:14","yyyyMMdd HH:mm:ss")});
    stus.push_back({"3","zhaoqian",22,150.2, QDateTime::fromString("20170112 15:13:14","yyyyMMdd HH:mm:ss")});
    stus.push_back({"4","wuxue",25,112.3, QDateTime::fromString("20170114 12:21:14","yyyyMMdd HH:mm:ss")});
    stus.push_back({"5","lifei",24,134.2, QDateTime::fromString("20170122 12:22:14","yyyyMMdd HH:mm:ss")});
    stus.push_back({"6","qianjiang",22,120.1, QDateTime::fromString("20170212 13:13:14","yyyyMMdd HH:mm:ss")});
    MyTableModel model;
    model.setStudents(stus);

    QTableView view;
    view.setModel(&model);
    view.setAlternatingRowColors(true);
    // 设置排序功能
    view.setSortingEnabled(true);
    // 设置水平头可拖动功能
    view.horizontalHeader()->setSectionsMovable(true);
    view.show();
    return a.exec();
}

完整代码可私信发送,谢谢!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

子类化QAbstractTableModel,实现table列排序和整列拖动功能 的相关文章

  • 使用 QSet 作为 Qt 地图容器中的键

    我需要一个映射 其中键是唯一的 并且每个键都是一组或自定义 POD 结构 其中包含 3 个数据项 这些值只是指向对象实例的指针 从阅读Qt 的 QMap 与 QHash 的文档 http qt project org doc qt 4 8
  • 在 4K 屏幕上使用 Matplotlib 和 TKAgg 或 Qt5Agg 后端

    我在 Ubuntu 16 04 上使用 Matplotlib 2 0 和 Python 3 6 来创建数据图 电脑显示器的分辨率为 4k 分辨率为 3840x2160 绘图数字看起来非常小 字体也很小 我已经尝试过TKAgg and Qt5
  • 通过CMake实现Qt项目

    我正在尝试通过 Cmake 构建并运行非常简单且基本的 Qt 示例 删除 pro 文件 以下是Qt项目的代码 自动生成的Qt项目的目录结构为 Cmake my project name headers mainwindow h source
  • QGraphicsScene没有删除QWidget的功能

    QGraphicsScene 有一个addWidget QWidget 有函数 但是没有对应的removeWidget QWidget 它只有removeItem QGraphicsItem 如何删除 QWidget 这是一个基本示例 看看
  • 另一个宏中的 Q_PROPERTY 宏

    如何放置Q PROPERTY另一个宏里面 辅助宏 define SimpleAllinOne member type public void Set member type arg member m member arg member ty
  • 如何在 QT 安装程序框架中区分每用户安装与系统范围安装?

    我正在使用一些名为 pgModeler 的应用程序 它的当前版本提供了一个基于 QT 安装程序框架的安装程序 Windows 上该安装程序的问题是它安装每个用户的开始菜单条目 https github com pgmodeler pgmod
  • 获取 QPushButton 在 2D 数组 QPushButton 上的索引

    我有一个二维数组QPushButton 当用户单击按钮时如何获取按钮的索引 例如当用户单击按钮时a 2 3 它会显示 2 3 该示例如下所示 Qt 4 5 使用对象名称 您可以为按钮指定唯一的对象名称 理想情况下 名称应该是有效的 C 标识
  • 如何从浮点数组创建新的 QImage

    我有一个代表图像的浮点数数组 列在前 我想在 QGraphicsSecene 上将图像显示为 QPixmap 为了做到这一点 我尝试使用 QImage 构造函数 QImage const uchar data int width int h
  • PyQt - 如何从给定的小部件获取顶级父级?

    给定的小部件如何访问它最旧的父级 即顶级小部件 我需要 showMinimized it 现在我正在使用 self parent parent parent showMinimized 但这似乎不是最好的方法 如果它移动了 我需要手动更改父
  • 打开和关闭附加窗口 (QML)

    目前我有一个通过以下方式打开的窗口 property variant win Button id testButton MouseArea onClicked var component Qt createComponent test qm
  • new 运算符(以及 malloc)无法分配约 450 MB 的内存 [重复]

    这个问题在这里已经有答案了 我正在开发一个程序 该程序在内存中存储大约 2 2 亿个短值的数组 该数据块的分配方式如下 short arrayName new short SIZE OF ARRAY 然后将文件的内容读入内存 在团队中的另一
  • 如何在 OS X 上的 Qt 应用程序中设置应用程序图标,足以进行分发?

    跟进这个答案 https stackoverflow com a 20918932 368896 to 这个问题 https stackoverflow com questions 20909341 what is the fastest
  • 如何让小部件在上下文菜单出现时接收鼠标释放事件

    在Ubuntu20 04上 当上下文菜单出现时 我无法让小部件接收鼠标释放事件 而Windows可以接收 我的pyqt版本是5 15 2 我考虑过手动发送鼠标释放事件 但我不知道当上下文菜单出现时哪些系统会收到鼠标释放事件 这样做可能会导致
  • 如何在QT上暂停和重新启动Qtimer

    我有 Ubuntu 我正在使用 IDEQT on C 我将暂停和恢复计时器 例如 void Ordonnancer les taches on pushButton clicked connect dataTimer SIGNAL time
  • 清除pyqt中布局中的所有小部件

    有没有办法清除 删除 布局中的所有小部件 self plot layout QtGui QGridLayout self plot layout setGeometry QtCore QRect 200 200 200 200 self r
  • 完全彻底卸载QT Creator

    问题 如何从 Linux 机器上卸载 QT Creator 我的 Debian Jessie 机器上的安装已损坏 我尝试过重新安装 修复等 但没有成功 建议我完全卸载 获取最新版本并重新安装 问题是我不确定如何执行此操作 每次我尝试时 QT
  • 如何在Qt 5中的paintEvent上使用mouseMoveEvent?

    我是 Qt 和 c 的新手 所以我遇到了一些困难 我正在尝试创建一个小部件 它可以获取 mouseMoveEvent 位置并在鼠标位置的像素图上绘制椭圆 下面你可以看到代码 include myimage h include
  • 如何去除QWizard中的水平线?

    我正在研究一个样式表QWizard我想删除按钮上方的水平线 我尝试递归浏览所有小部件并将其边框设置为无 但似乎没有任何小部件具有此边框 这是我的代码 可以找到完整的可构建示例here https gist github com ardeid
  • 将 jstring 转换为 QString

    我正在调用一个返回字符串的 Java 函数 QAndroidJniObject obj QAndroidJniObject callStaticObjectMethod
  • Qt QML 数据模型似乎不适用于 C++

    我一直在使用中的示例http doc qt digia com 4 7 qdeclarativemodels html http doc qt digia com 4 7 qdeclarativemodels html这是 QML 声明性数

随机推荐