QTableView + QStandardItemModel模式显示表格冻结列(模板)

2024-07-29 20:11:49 浏览数 (2)

点击上方"蓝字"关注我们

01、QTableView

QTableView 是 Qt 框架中一个用于显示和编辑表格数据的控件。它提供了一个灵活的界面,允许用户通过行和列来浏览和修改数据。QTableView 支持多种数据模型,如 QAbstractItemModel,并且可以与模型一起使用,以提供数据视图。此外,QTableView 还提供了排序、筛选和分组等功能,以满足不同的需求。

02、QStandardItemModel

QStandardItemModel 是 Qt 框架中一个常用的数据模型,用于存储和管理表格数据。它是一个基于 QAbstractItemModel 的实现,提供了简单易用的 API 来创建和管理表格数据。使用 QStandardItemModel,你可以轻松地将数据填充到表格中,并通过行和列索引访问和修改数据。此外,QStandardItemModel 还支持数据类型转换、数据校验和信号槽机制等功能,使得它在开发过程中非常实用。

03、QStandardItem

QStandardItem 是 Qt 框架中一个用于表示表格单元格的数据对象。它是 QStandardItemModel 的基本构建块,每个 QStandardItem 可以包含一个值和一些附加属性,如文本、图标、状态等。通过将 QStandardItem 添加到 QStandardItemModel 中,你可以构建一个完整的表格数据模型。

QStandardItem 提供了一系列方法来设置和获取其属性,例如 setText() 用于设置文本内容,setIcon() 用于设置图标,setCheckState() 用于设置复选框状态等。此外,QStandardItem 还支持父子关系管理,可以通过 setChild() 和 child() 方法来添加和访问子项。

在 QTableView 中,QStandardItem 作为数据模型中的基本元素,负责展示和编辑表格中的数据。通过操作 QStandardItem,你可以实现对表格数据的增删改查等操作。

04、QModelIndex

QModelIndex 是 Qt 框架中一个用于表示模型中某个节点的对象。在 QTableView、QListView 等控件中,QModelIndex 用来唯一标识模型中的一个元素,以便于获取和操作该元素的数据。

QModelIndex 的主要作用包括:

1. 定位元素:通过 QModelIndex 可以获取到模型中指定位置的元素,例如获取第一行的第一个单元格的 QModelIndex。

2. 访问数据:通过 QModelIndex 可以访问到模型中对应元素的数据,例如获取该元素的文本内容或图片资源。

3. 操作元素:通过 QModelIndex 可以对模型中对应元素进行操作,例如修改文本内容或更改图片资源。

在使用 QModelIndex 时,需要注意以下几点:

1. QModelIndex 是一个轻量级对象,可以在多个地方传递和使用,而不会增加内存开销。

2. QModelIndex 不包含任何数据本身,它只是一个指向模型中某个节点的指针。因此,在使用 QModelIndex 时,需要确保它指向的是一个有效的节点。

3. QModelIndex 是不可变的,即不能直接修改它的属性。如果需要对模型中的元素进行操作,需要通过模型提供的接口来实现。

05、grades.txt

 France , Norway , YDS , UK(tech.), UK(adj.) , UIAA , Ger , Australia , Finland , Brazil

1,   , 5.2,   ,   , I , I ,   ,   , Isup

2,   , 5.3,   ,   , II , II , 11,   , II

3, 3, 5.4,   ,   , III , III , 12,   , IIsup

4, 4, 5.5, 4a , VD , IV , IV , 12,   , III

5a , 5-, 5.6,   , S , V- , V , 13, 5-, IIIsup

5b , 5, 5.7, 4b , HS , V , VI , 14, 5, IV

  ,   ,   , 4c ,   , V ,   , 15,   ,  

5c , 5 , 5.8,   , VS , VI- , VIIa , 16, 5, IVsup

6a , 6-, 5.9, 5a , HVS , VI , VIIb , 17,   , V

6a , 6-/6 , 5.10a ,   , E1 , VI , VIIc , 18, 6-, VI

6b ,   , 5.10b , 5b ,   ,   ,   , 19,   , VI/VI

6b , 6, 5.10c ,   , E2 , VII- , VIIIa , 20, 6, VIsup/VI

6c , 6 , 5.10d , 5c ,   , VII , VIIIb , 21,   , VIsup

6c , 7-, 5.11a ,   , E3 , VII , VIIIc , 22, 6, 7a

6c , 7, 5.11b ,   ,   ,   ,   , 23,   , 7b

7a , 7 , 5.11c , 6a , E4 , VIII- , IXa , 24, 7-, 7c

7a , 7 /8- , 5.11d ,   ,   , VIII , IXb ,   , , 7c

7a , 8-, 5.12a ,   , E5 , VIII , IXc , 25, 7, 8a

7b , 8, 5.12b , 6b ,   ,   ,   , 26, 8-, 8b

7b , 8/8 , 5.12c ,   , E6 , IX- , Xa , 27, 8, 8c

7c , 8 , 5.12d , 6c ,   , IX , Xb , 28, 8, 9a

7c , 9-, 5.13a ,   , E7 , IX , Xc , 29, 9-, 9b

8a ,   , 5.13b ,   ,   ,   ,   ,   , 9, 9c

8a , 9-/9 , 5.13c , 7a ,   , X- ,   , 30, 9, 10a

8b , 9, 5.13d ,   , E8 , X ,   , 31, 10-, 10b

8b , 9/9 , 5.14a ,   ,   , X ,   , 32, 10, 10c

8c , 9 , 5.14b , 7b ,   ,   ,   , 33, 10, 11a

8c , 10-, 5.14c ,   , E9 , XI- ,   , 34, 11-, 11b

9a , 10, 5.14d , 7c ,   , XI ,   , 35, 11, 11c

9a ,   , 5.15a , ,   , XI ,   ,   ,   , 12a

9b , , 5.15b  , ,   , , , , , 12b

# Wikipedia contributors. Grade (climbing). Wikipedia, The Free Encyclopedia. May 15, 2009, 20:42 UTC. 

06、main.cpp

代码语言:javascript复制
#include <QApplication>
#include <QStandardItemModel>
#include <QFile>
#include <QTextStream>

#include "freezetablewidget.h"

int main(int argc, char* argv[])
{
    Q_INIT_RESOURCE(grades);

    QApplication app( argc, argv );

    // QStandardItemModel类提供了一个用于存储自定义数据的通用模型
    QStandardItemModel *model=new QStandardItemModel();

    QFile file(":/grades.txt");
    if (file.open(QFile::ReadOnly)) {
        QTextStream stream(&file);

        QString line = stream.readLine();
        QStringList list = line.simplified().split(',');

        // 设置水平头
        model->setHorizontalHeaderLabels(list);

        int row = 0;
        QStandardItem *newItem = nullptr;
        while (!stream.atEnd()) {
            line = stream.readLine();
            if (!line.startsWith('#') && line.contains(',')) {
                list = line.simplified().split(',');
                for (int col = 0; col < list.length();   col){
                    newItem = new QStandardItem(list.at(col));
                    // 将给定行和列的项设置为项
                    model->setItem(row, col, newItem);
                }
                  row;
            }
        }
    }
    file.close();

    FreezeTableWidget *tableView = new FreezeTableWidget(model);

    tableView->setWindowTitle(QObject::tr("公众号:Qt历险记"));
    tableView->resize(560, 680);
    tableView->show();
    return app.exec();
}

07、freezetablewidget.h

代码语言:javascript复制
#ifndef FREEZETABLEWIDGET_H
#define FREEZETABLEWIDGET_H

#include <QTableView>

//! [Widget definition]
class FreezeTableWidget : public QTableView {
     Q_OBJECT

public:
      FreezeTableWidget(QAbstractItemModel * model);
      ~FreezeTableWidget();


protected:
      void resizeEvent(QResizeEvent *event) override;
      QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override;
      void scrollTo (const QModelIndex & index, ScrollHint hint = EnsureVisible) override;

private:
      QTableView *frozenTableView;
      void init();
      void updateFrozenTableGeometry();


private slots:
      void updateSectionWidth(int logicalIndex, int oldSize, int newSize);
      void updateSectionHeight(int logicalIndex, int oldSize, int newSize);

};
//! [Widget definition]
#endif // FREEZETABLEWIDGET_H

08、freezetablewidget.cpp

代码语言:javascript复制
#include "freezetablewidget.h"

#include <QScrollBar>
#include <QHeaderView>

FreezeTableWidget::FreezeTableWidget(QAbstractItemModel * model)
{

     // QTableView
      setModel(model);
      frozenTableView = new QTableView(this);

      init();

      // 将两个表视图的标题和滚动条连接在一起
      connect(horizontalHeader(),&QHeaderView::sectionResized, this,
              &FreezeTableWidget::updateSectionWidth);
      connect(verticalHeader(),&QHeaderView::sectionResized, this,
              &FreezeTableWidget::updateSectionHeight);

      connect(frozenTableView->verticalScrollBar(), &QAbstractSlider::valueChanged,
              verticalScrollBar(), &QAbstractSlider::setValue);
      connect(verticalScrollBar(), &QAbstractSlider::valueChanged,
              frozenTableView->verticalScrollBar(), &QAbstractSlider::setValue);


}

FreezeTableWidget::~FreezeTableWidget()
{
      delete frozenTableView;
}

void FreezeTableWidget::init()
{
      frozenTableView->setModel(model());
      frozenTableView->setFocusPolicy(Qt::NoFocus);
      frozenTableView->verticalHeader()->hide();
      frozenTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);

      // 将小部件放置在父小部件堆栈中的frozenTableView下。
      // 为了实现这一点,小部件本身和frozenTableView必须是兄弟姐妹。
      viewport()->stackUnder(frozenTableView);

      frozenTableView->setStyleSheet("QTableView { border: none;"
                                     "background-color: #8EDE21;"
                                     "selection-background-color: #999}"); //for demo purposes
      frozenTableView->setSelectionModel(selectionModel());
      for (int col = 1; col < model()->columnCount();   col)
            frozenTableView->setColumnHidden(col, true);

      frozenTableView->setColumnWidth(0, columnWidth(0) );

      frozenTableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
      frozenTableView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
      frozenTableView->show();

      updateFrozenTableGeometry();

      setHorizontalScrollMode(ScrollPerPixel);
      setVerticalScrollMode(ScrollPerPixel);
      frozenTableView->setVerticalScrollMode(ScrollPerPixel);
}


//! [sections]
void FreezeTableWidget::updateSectionWidth(int logicalIndex, int /* oldSize */, int newSize)
{
      if (logicalIndex == 0){
            frozenTableView->setColumnWidth(0, newSize);
            updateFrozenTableGeometry();
      }
}

void FreezeTableWidget::updateSectionHeight(int logicalIndex, int /* oldSize */, int newSize)
{
      frozenTableView->setRowHeight(logicalIndex, newSize);
}
//! [sections]


//! [resize]
void FreezeTableWidget::resizeEvent(QResizeEvent * event)
{
      QTableView::resizeEvent(event);
      updateFrozenTableGeometry();
 }
//! [resize]


//! [navigate]
QModelIndex FreezeTableWidget::moveCursor(CursorAction cursorAction,
                                          Qt::KeyboardModifiers modifiers)
{
      QModelIndex current = QTableView::moveCursor(cursorAction, modifiers);

      if (cursorAction == MoveLeft && current.column() > 0
              && visualRect(current).topLeft().x() < frozenTableView->columnWidth(0) ){
            const int newValue = horizontalScrollBar()->value()   visualRect(current).topLeft().x()
                                 - frozenTableView->columnWidth(0);
            horizontalScrollBar()->setValue(newValue);
      }
      return current;
}
//! [navigate]

// 滚动到指定的模型索引(QModelIndex)
void FreezeTableWidget::scrollTo (const QModelIndex & index, ScrollHint hint){
    if (index.column() > 0)
        QTableView::scrollTo(index, hint);
}

//! [geometry]
//! updateFrozenTableGeometry()函数可以确保冻结表格总是显示在屏幕的可视区域内,并且其位置和大小会根据窗口的大小和表头的宽度自动调整。
void FreezeTableWidget::updateFrozenTableGeometry()
{
      frozenTableView->setGeometry(verticalHeader()->width()   frameWidth(),
                                   frameWidth(), columnWidth(0),
                                   viewport()->height() horizontalHeader()->height());
}
//! [geometry]


09、.pro

代码语言:javascript复制
QT  = widgets
requires(qtConfig(tableview))

HEADERS  = freezetablewidget.h
SOURCES  = main.cpp freezetablewidget.cpp
RESOURCES  = grades.qrc

# install
target.path = $$PWD/frozencolumn
INSTALLS  = target

10、演示

总结

同志们,想学什么Qt内容,记得在下方留言。

故我在

点击下方卡片 关注我

↓↓↓

Qt历险记

一名技术分享师,分享方向:->Qt(C/C 、linux、STM32、MySql/Sqlite3、TCP/UDP),设计方面->Ai、PS、visio、AD、Protues。 【v合作:Family_S_Health】

0 人点赞