解决Qt 6.5.0中QTableView列头拖动后表格自动左滚问题
Qt 6.5.0 QTableView列头拖动后滚动到最左侧的解决办法
这是Qt 6.5.0版本的已知BUG,当开启setSectionsMovable(true)后,轻微拖动列头再释放鼠标,会触发表格错误滚动到最左侧。以下是几种可行的解决方式:
方法一:升级Qt版本到6.5.1及以上
官方在Qt 6.5.1版本中修复了这个表头拖动导致的滚动异常问题,升级到新版本是最彻底的解决方案。
方法二:重写QHeaderView拦截释放事件恢复滚动位置
自定义水平表头类,在鼠标释放时记录并恢复表格的滚动位置:
// CustomHorizontalHeader.h #ifndef CUSTOMHORIZONTALHEADER_H #define CUSTOMHORIZONTALHEADER_H #include <QHeaderView> class CustomHorizontalHeader : public QHeaderView { Q_OBJECT public: explicit CustomHorizontalHeader(Qt::Orientation orientation, QWidget *parent = nullptr); protected: void mouseReleaseEvent(QMouseEvent *event) override; }; #endif // CUSTOMHORIZONTALHEADER_H
// CustomHorizontalHeader.cpp #include "CustomHorizontalHeader.h" #include <QMouseEvent> #include <QTableView> CustomHorizontalHeader::CustomHorizontalHeader(Qt::Orientation orientation, QWidget *parent) : QHeaderView(orientation, parent) {} void CustomHorizontalHeader::mouseReleaseEvent(QMouseEvent *event) { // 记录当前表格水平滚动位置 QTableView* tableView = qobject_cast<QTableView*>(parentWidget()); const int scrollPos = tableView ? tableView->horizontalScrollBar()->value() : 0; // 调用父类处理释放逻辑 QHeaderView::mouseReleaseEvent(event); // 恢复滚动位置 if (tableView) { tableView->horizontalScrollBar()->setValue(scrollPos); } }
在主程序中替换默认表头:
// main.cpp 修改部分 auto tableView = new QTableView(); auto model = new MyModel(); tableView->setModel(model); // 使用自定义表头 auto customHeader = new CustomHorizontalHeader(Qt::Horizontal, tableView); tableView->setHorizontalHeader(customHeader); customHeader->setSectionsMovable(true); tableView->show();
方法三:使用事件过滤器修复
无需自定义表头类,给水平表头安装事件过滤器,在鼠标释放时恢复滚动位置:
// main.cpp 修改部分 #include <QEvent> class ScrollFixFilter : public QObject { protected: bool eventFilter(QObject *watched, QEvent *event) override { if (event->type() == QEvent::MouseButtonRelease) { QHeaderView* header = qobject_cast<QHeaderView*>(watched); if (header && header->orientation() == Qt::Horizontal) { QTableView* tableView = qobject_cast<QTableView*>(header->parentWidget()); if (tableView) { const int scrollPos = tableView->horizontalScrollBar()->value(); // 先让事件正常处理 const bool result = QObject::eventFilter(watched, event); // 恢复滚动位置 tableView->horizontalScrollBar()->setValue(scrollPos); return result; } } } return QObject::eventFilter(watched, event); } }; // 主逻辑部分 auto tableView = new QTableView(); auto model = new MyModel(); tableView->setModel(model); auto header = tableView->horizontalHeader(); header->setSectionsMovable(true); // 安装事件过滤器 ScrollFixFilter* filter = new ScrollFixFilter(); header->installEventFilter(filter); tableView->show();
内容的提问来源于stack exchange,提问作者vadimrm
相关产品推荐
相关产品推荐

