Qt基础控件学习03 QTableView冻结列(可自定义冻结数量)
阅读原文时间:2021年04月23日阅读:1

最近项目需求,需要冻结前两列的内容,不随着水平滑块的移动而移动。于是参考了好几个博客,也没发现有好用的。然后有人说qt 自带示例f有类似的 frozen 于是,很欢喜。可以运行起来发现,只是第一行冻结。于是就开启修改demo之路。在这里总结一下,为有需求的童鞋,少走点弯路。

demo的思路大概是自定义一个继承qtableview的类。这个类中在加一个qtableview的实例。可以理解为父table上面加载一个子table。实质上两个table的数据一模一样。只是把子table放在父table上,隐藏掉子table不需要显示的列。子table需要显示的列正好盖在父table上。同时重写qtableview类下面两个函数即可:

void resizeEvent(QResizeEvent *event) override;
void scrollTo(const QModelIndex & index, ScrollHint hint = EnsureVisible) override;

使用这个类最好注意:1.先把要冻结的行放在前面。否则需要再改代码
                                         2.冻结列数最好不要大于等于总列数(相信不会有人那么干。)

先上图看效果,上代码

根据demo改编。加了点注释,和逻辑

#ifndef FREEZETABLEWIDGET_H
#define FREEZETABLEWIDGET_H

#include

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

public:
      FreezeTableWidget(QAbstractItemModel * model , int freezeColCounts);
      ~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();
      int m_iFreezeColCounts = 1;

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

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

include "freezetablewidget.h"

#include
#include
#include

//! [constructor]
FreezeTableWidget::FreezeTableWidget(QAbstractItemModel * model, int freezeColCounts)
{
    setModel(model);
    //setSelectionBehavior(QAbstractItemView::SelectRows);
    frozenTableView = new QTableView(this);
    m_iFreezeColCounts = freezeColCounts;

    init();

    //connect the headers and scrollbars of both tableviews together
    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);

}
//! [constructor]

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

//! [init part1]
void FreezeTableWidget::init()
{
    frozenTableView->setModel(model());
    frozenTableView->setFocusPolicy(Qt::NoFocus);
    frozenTableView->verticalHeader()->hide();
    frozenTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    //frozenTableView->setSelectionBehavior(QAbstractItemView::SelectRows);

    viewport()->stackUnder(frozenTableView);
    //! [init part1]

    //! [init part2]
    frozenTableView->setStyleSheet("QTableView { border: none;"
                                   "background-color: #8EDE21;"
                                   "selection-background-color: #999}"); //for demo purposes
    //设置和父table同步的光标选择单元格(必要)
    frozenTableView->setSelectionModel(selectionModel());

    qDebug()<columnCount()<columnCount(); ++col)
        frozenTableView->setColumnHidden(col, true);

    for(int i = 0; i setColumnWidth(i, columnWidth(0));
    }

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

    setHorizontalScrollMode(ScrollPerPixel);
    setVerticalScrollMode(ScrollPerPixel);
    frozenTableView->setVerticalScrollMode(ScrollPerPixel);
}
//! [init part2]

//! [sections]
void FreezeTableWidget::updateSectionWidth(int logicalIndex, int /* oldSize */, int newSize)
{
    if (logicalIndex == m_iFreezeColCounts-1){

        int width = 0;
        for(int i = 0; i< m_iFreezeColCounts-1; i++)
        {
            width += columnWidth(i);
        }

        for(int i = 0; i< m_iFreezeColCounts; i++)         {             frozenTableView->setColumnWidth(i, (newSize+width)/m_iFreezeColCounts);
        }

        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() < columnWidth(0) ){ //            const int newValue = horizontalScrollBar()->value() + visualRect(current).topLeft().x()
//                                 - frozenTableView->columnWidth(0);
//            horizontalScrollBar()->setValue(newValue);
//      }

//      return current;
//}
//! [navigate]

void FreezeTableWidget::scrollTo (const QModelIndex & index, ScrollHint hint){
    //if (index.column() > 0)
    QTableView::scrollTo(index, hint);
}

//! [geometry]
void FreezeTableWidget::updateFrozenTableGeometry()
{
    int width = 0;
    for(int i = 0; i< m_iFreezeColCounts; i++)     {         width += columnWidth(i);     }     frozenTableView->setGeometry(verticalHeader()->width() + frameWidth(),
                                 frameWidth(),width ,
                                 viewport()->height()+horizontalHeader()->height());
}
//! [geometry]

#include
#include
#include

#include "freezetablewidget.h"

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

    QApplication app( argc, argv );
    QStandardItemModel *model=new QStandardItemModel();

    QFile file(":/grades.txt");
    if (file.open(QFile::ReadOnly)) {
        QString line = file.readLine(200);
        QStringList list = line.simplified().split(',');
        model->setHorizontalHeaderLabels(list);

        int row = 0;
        QStandardItem *newItem = 0;
        while (file.canReadLine()) {
            line = file.readLine(200);
            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,3);

    tableView->setWindowTitle(QObject::tr("Frozen Column Example"));
    tableView->resize(560, 680);
    tableView->show();
    return app.exec();
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章