У меня есть два QTableWidget, имеющие одинаковое количество строк и столбцов. Теперь каждый выбор в одной таблице должен автоматически обновлять выбор в другой и наоборот.
Следующий код работает нормально, за одним исключением:
#include <QApplication>
#include <QTableWidget>
#include <QHBoxLayout>
#include <functional>
QTableWidget* create() {
auto table = new QTableWidget;
table->setSortingEnabled(true);
table->setRowCount(20);
table->setColumnCount(1);
for (auto i = 0; i < 20; i++) {
{
auto item = new QTableWidgetItem(QString("%1").arg(i+1));
table->setItem(i, 1, item);
}
}
return table;
}
int main(int argc, char** args) {
QApplication app(argc, args);
QTableWidget* table1 = create();
QTableWidget* table2 = create();
auto frame = new QFrame;
frame->setLayout(new QHBoxLayout);
frame->layout()->addWidget(table1);
frame->layout()->addWidget(table2);
frame->show();
auto func = [&](QTableWidget* senderTable, QTableWidget* receiverTable) {
const QSignalBlocker blocker(receiverTable);
receiverTable->selectionModel()->clearSelection();
for (auto item : senderTable->selectedItems()) {
receiverTable->item(item->row(), item->column())->setSelected(true);
}
};
QObject::connect(table2, &QTableWidget::itemSelectionChanged, std::bind(func, table2, table1));
QObject::connect(table1, &QTableWidget::itemSelectionChanged, std::bind(func, table1, table2));
app.exec();
}
Исключения возникают, если я сортирую один столбец. В этом случае wrong
элементы выбраны в другой таблице.
Другими словами, поведение синхронизации выбора должно быть независимым от выбранной сортировки. Содержимое моих таблиц — только примеры.
Какой может быть самый простой способ добиться желаемого поведения?
Я изменил ваш пример, чтобы он работал как задумано. Идея состоит в том, что мы не должны полагаться на строки и столбцы элементов, а хранить некоторые уникальные идентификаторы в каждом из элементов и выполнять поиск по этому идентификатору, а не по строке и столбцу, которые могут различаться в зависимости от порядка сортировки.
Итак, вот код, который демонстрирует то, что я сказал:
#include <QApplication>
#include <QTableWidget>
#include <QHBoxLayout>
#include <functional>
#include <assert.h>
QTableWidget* create()
{
auto table = new QTableWidget;
table->setSortingEnabled(true);
table->setRowCount(20);
table->setColumnCount(1);
for (auto i = 0; i < 20; i++) {
auto item = new QTableWidgetItem(QString("%1").arg(i + 1));
item->setData(Qt::UserRole, i); // It can be any kind of unique identifier.
table->setItem(i, 1, item);
}
return table;
}
int main(int argc, char** args)
{
QApplication app(argc, args);
QTableWidget* table1 = create();
QTableWidget* table2 = create();
auto frame = new QFrame;
frame->setLayout(new QHBoxLayout);
frame->layout()->addWidget(table1);
frame->layout()->addWidget(table2);
frame->show();
auto func = [&](QTableWidget* senderTable, QTableWidget* receiverTable) {
const QSignalBlocker blocker(receiverTable);
receiverTable->selectionModel()->clearSelection();
auto model = receiverTable->model();
for (auto item : senderTable->selectedItems()) {
// Find the item with the same identifier.
auto found = model->match(model->index(0, 0), Qt::UserRole, item->data(Qt::UserRole));
assert(!found.empty());
auto idx = found.first();
receiverTable->item(idx.row(), idx.column())->setSelected(true);
}
};
QObject::connect(table2, &QTableWidget::itemSelectionChanged, std::bind(func, table2, table1));
QObject::connect(table1, &QTableWidget::itemSelectionChanged, std::bind(func, table1, table2));
app.exec();
}
Других решений пока нет …