我正在开发一个程序来查看和编辑文件中的记录。它的特点是QTableView
显示所有记录的a,QLineEdit
用于搜索记录的a以及显示所选记录详细信息的一些标签:
有一个QAbstractTableModel
用于保存数据的QSortFilterProxyModel
类和一个用于帮助过滤中的行的类QTableView
。
搜索和过滤工作正常。在搜索框中键入文本会立即过滤记录列表。但是有两件事我无法上班:
例如,当我键入“ tesla”时,该列表将为空,因为没有项目匹配。但是,一旦我退格到“ te”,“ Forester”就匹配了,我希望它被选中。第二个例子:当(在启动程序之后)我键入“ f”时,列表将缩小到8个项目,并且选择了“ Pacifica”。当我删除“ f”时,仍然选择了Pacifica,但不再位于列表的可见部分。
我已经在Pastie上发布了完整的源代码,这里是一些(希望如此)相关的代码片段。
void MainWindow::on_lineEditSearch_textChanged(const QString & text)
{
itemProxy->setFilterFixedString(text);
updateStatusBar();
}
void MainWindow::currentRowChangedSlot(QModelIndex const & current, QModelIndex const & /*previous*/)
{
Car * car = 0;
if (current.isValid())
{
QModelIndex sibling = current.sibling(current.row(), COLUMN_THIS);
QVariant variant = itemProxy->data(sibling);
car = static_cast<Car *> (variant.value<void *> ());
}
updateCarMake(car);
updateCarModel(car);
}
MainWindow::MainWindow(QWidget * parent, CarItemModel * itemModel, CarSortFilterProxyModel * itemProxy) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
this->itemModel = itemModel;
this->itemProxy = itemProxy;
ui->setupUi(this);
setupStatusBar();
ui->tableView->setModel(itemProxy);
ui->tableView->setColumnHidden(COLUMN_THIS, true);
QItemSelectionModel * selectionModel = ui->tableView->selectionModel();
connect(selectionModel, SIGNAL(currentRowChanged(QModelIndex const &, QModelIndex const &)),
this, SLOT(currentRowChangedSlot(QModelIndex const &, QModelIndex const &)));
connect(selectionModel, SIGNAL(selectionChanged(QItemSelection const &, QItemSelection const &)),
this, SLOT(selectionChangedSlot(QItemSelection const &, QItemSelection const &)));
ui->tableView->selectRow(0);
ui->lineEditSearch->setFocus();
updateStatusBar();
}
<widget class="QTableView" name="tableView">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
因此,我的问题是:如何确保始终选择一个项目并在列表的可见部分(当然,除非用户正在滚动)?
这就是我所做的
该解决方案甚至更新颖,因为当从无可见项转到一些可见项时,将选择最近选择的项,而不仅仅是第一项。
首先,我向该类添加了一个QModelIndex lastModelIndex;
私有成员MainWindow
,并将其设置在SelectionChanged
插槽中。请注意,模型索引是存储的,而不是代理索引。
void MainWindow::selectionChangedSlot(QItemSelection const & selected, QItemSelection const & /*deselected*/)
{
if (selected.count() > 0)
{
QModelIndex index = selected.indexes().first();
QModelIndex modelIndex = itemProxy->mapToSource(index);
lastModelIndex = modelIndex;
}
}
接下来,我添加了两种方法:ensureSelected()
...
void MainWindow::ensureSelected(QItemSelectionModel * selectionModel, int const proxyCount)
{
if (selectionModel->hasSelection())
{
// an item is currently selected - don't have to do anything
}
else if (proxyCount == 1)
{
// no item is currently selected, but there is exactly one item in the list - select it
QModelIndex proxyIndex = itemProxy->index(0, 0);
selectionModel->setCurrentIndex(proxyIndex, QItemSelectionModel::Select | QItemSelectionModel::Rows);
}
else if (proxyCount > 1)
{
// no item is currently selected, but there are several items in the list
QModelIndex proxyIndex; // !isValid
if (lastModelIndex.isValid())
{
// there's a most recently selected item - compute its index in the list
proxyIndex = itemProxy->mapFromSource(lastModelIndex);
}
if (proxyIndex.isValid())
{
// the most recently selected item is in the list - select it
proxyIndex = proxyIndex.sibling(proxyIndex.row(), COLUMN_THIS);
}
else
{
// there's no most recently selected item or it is no longer in the list - select the first item
proxyIndex = itemProxy->index(0, 0);
}
selectionModel->setCurrentIndex(proxyIndex, QItemSelectionModel::Select | QItemSelectionModel::Rows);
}
else
{
// There are no items in the list - cannot select anything.
}
}
...和ensureVisible()
:
void MainWindow::ensureVisible(QItemSelectionModel * selectionModel)
{
if (selectionModel->hasSelection())
{
const QModelIndex index = ui->tableView->currentIndex();
ui->tableView->scrollTo(index);
ui->tableView->selectRow(index.row());
ui->tableView->scrollTo(index);
}
}
看起来很奇怪,我必须打scrollTo()
两次电话,否则tableView不会滚动。
这些新方法的调用方式on_lineEditSearch_textChanged()
如下:
void MainWindow::on_lineEditSearch_textChanged(const QString & text)
{
itemProxy->setFilterFixedString(text);
QItemSelectionModel * selectionModel = ui->tableView->selectionModel();
int modelCount = itemModel->rowCount(); // number of items in the model
int proxyCount = itemProxy->rowCount(); // number of items in tableview
ensureSelected(selectionModel, proxyCount);
ensureVisible(selectionModel);
updateStatusBar();
}
请在Pastie上找到更新的完整源代码。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句