最近项目需求,需要冻结前两列的内容,不随着水平滑块的移动而移动。于是参考了好几个博客,也没发现有好用的。然后有人说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()<
frozenTableView->setColumnHidden(col, true);
for(int i = 0; i
}
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();
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章