問題描述
我有一個簡單的 QTableView,帶有一個 QSortFilterProxyModel 和一個從 QAbstractTableModel 繼承的自定義 TableModel 子類的源模型.該模型使用附加行動態更新.
I have a simple QTableView with a QSortFilterProxyModel and a source model of a custom TableModel subclass that inherits from QAbstractTableModel. The model is dynamically updated with additional rows.
我的問題是:如果我按列對表格進行排序,然后滾動到特定行,然后在該行上方添加更多行,則會將該行向下推.數據輸入的速度足夠快,以至于很難在光標下方的行發生變化的情況下單擊行進行編輯.
My problem is this: If I sort the table on a column, then scroll to a specific row, and then more rows are added above this row it pushes the row down. Data is coming in fast enough that it makes it difficult to click on rows to edit them without the row changing underneath my cursor.
有沒有辦法阻止表格滾動并保持表格相對于選定行的位置?
Is there a way to stop the table from scrolling and maintain the position of the table relative to say a selected row?
推薦答案
QTableView::rowViewportPosition()
可用于獲取當前視口位置,如果之前插入了某些內容,則必須更正該位置當前索引.
QTableView::rowViewportPosition()
can be used to get the current view port position which has to be corrected if something is inserted before current index.
可以使用信號處理程序在插入行之前和之后檢索它.
It can be retrieved before and after insertion of a row using signal handlers.
因此,插入后可以在信號處理程序中相應地調整滾動.這是通過更改垂直滾動條的值來完成的.(垂直滾動模式更改為QTableView::ScrollPerPixel
以確保正確的垂直調整.)
Thus, the scrolling can be adjusted accordingly in the signal handler after the insertion. This is done changing the value of the vertical scrollbar. (The vertical scroll mode is changed to QTableView::ScrollPerPixel
to ensure correct vertical adjustment.)
一個最小的代碼示例:
#include <iostream>
#include <QApplication>
#include <QMainWindow>
#include <QScrollBar>
#include <QStandardItemModel>
#include <QTableView>
#include <QTimer>
enum { NCols = 2 }; // number of columns
enum { Interval = 1000 }; // interval of auto action
enum { NRep = 5 }; // how often selected auto action is repeated
// fills a table model with sample data
void populate(QStandardItemModel &tblModel, bool prepend)
{
int row = tblModel.rowCount();
if (prepend) tblModel.insertRow(0);
for (int col = 0; col < NCols; ++col) {
QStandardItem *pItem = new QStandardItem(QString("row %0, col %1").arg(row).arg(col));
tblModel.setItem(prepend ? 0 : row, col, pItem);
}
}
// does some auto action
void timeout(QTimer &timer, QStandardItemModel &tblModel)
{
static int step = 0;
++step;
std::cout << "step: " << step << std::endl;
switch (step / NRep % 3) {
case 0: break; // pause
case 1: populate(tblModel, false); break; // append
case 2: populate(tblModel, true); break; // prepend
}
}
// managing the non-scrolling when something is inserted.
struct NoScrCtxt {
QTableView &tblView;
int y;
NoScrCtxt(QTableView &tblView_): tblView(tblView_) { }
void rowsAboutToBeInserted()
{
y = tblView.rowViewportPosition(tblView.currentIndex().row());
}
void rowsInserted()
{
int yNew = tblView.rowViewportPosition(tblView.currentIndex().row());
if (y != yNew) {
if (QScrollBar *pScrBar = tblView.verticalScrollBar()) {
pScrBar->setValue(pScrBar->value() + yNew - y);
}
}
}
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
// build some GUI
QMainWindow win;
QStandardItemModel tblModel(0, NCols);
for (int i = 0; i < 10; ++i) populate(tblModel, false);
QTableView tblView;
tblView.setVerticalScrollMode(QTableView::ScrollPerPixel);
tblView.setModel(&tblModel);
win.setCentralWidget(&tblView);
win.show();
// setup a "no-scroll manager"
NoScrCtxt ctxt(tblView);
QObject::connect(&tblModel, &QStandardItemModel::rowsAboutToBeInserted,
[&ctxt](const QModelIndex&, int, int) { ctxt.rowsAboutToBeInserted(); });
QObject::connect(&tblModel, &QStandardItemModel::rowsInserted,
[&ctxt](const QModelIndex&, int, int) { ctxt.rowsInserted(); });
// initiate some auto action
QTimer timer;
timer.setInterval(Interval); // ms
QObject::connect(&timer, &QTimer::timeout,
[&timer, &tblModel]() { timeout(timer, tblModel); });
timer.start();
// exec. application
return app.exec();
}
我在 Windows 10、VS2013、Qt 5.7 中編譯并測試了這個:
I compiled and tested this in Windows 10, VS2013, Qt 5.7:
這篇關于當數據添加到當前位置上方時停止 QTableView 滾動的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!