Qt基础控件学习03 QTableView冻结列(可自定义冻结数量)

最近项目需求,需要冻结前两列的内容,不随着水平滑块的移动而移动。于是参考了好几个博客,也没发现有好用的。然后有人说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.冻结列数最好不要大于等于总列数(相信不会有人那么干。)

 

先上图看效果,上代码

Qt基础控件学习03 QTableView冻结列(可自定义冻结数量)_第1张图片

根据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()<     for (int col = m_iFreezeColCounts; col < model()->columnCount(); ++col)
        frozenTableView->setColumnHidden(col, true);

    for(int i = 0; i     {
        frozenTableView->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();
}
 

 

你可能感兴趣的:(QT控件)