#qt #filter #tableview #show #qsqltablemodel
#qt #Фильтр #просмотр таблицы #показать #qsqltablemodel
Вопрос:
Я загрузил базу данных с помощью QSqlTableModel
и показываю ее в tableView1
. Теперь я настроил фильтр для этого QSqlTableModel
и хочу показать отфильтрованные данные в tableView2
. tableView1
и tableView2
не должны взаимодействовать друг с другом. Тогда, как это показать, и какой самый быстрый способ?
Примечание:
- База данных содержит только число без строки, а размер невелик (около 500 * 5);
- Данные в
tableView2
не нужно сохранять.
Основной код выглядит следующим образом:
QSqlTableModel *model = new QSqlTableModel(NULL, db);
model->setTable(tableName);
model->select();
tableView->setModel(model);
tableView->show();
model->setFilter("colum5 > 10");
Я не хочу записывать отфильтрованные данные в другую базу данных, а затем сохранять их, показывать. Я хочу найти несколько лучших способов показать это. Или мне нужно извлечь отфильтрованные данные в матрицу и отобразить эту матрицу в tableView
? Кто-нибудь может высказать какие-нибудь соображения? Спасибо
Комментарии:
1. Есть ли какая-либо причина, по которой вы не можете иметь два
QSqlTableModel
s — по одному для каждогоQTableView
— но которые оба используют один и тот жеQSqlDatabase
экземпляр?2. @G.M. потому что я хочу иметь только одну копию этой базы данных. Если я использую два
QSqlTableModel
, это пустая трата памяти.
Ответ №1:
Поскольку вы хотите отобразить обе модели, я думаю, что самым чистым способом сделать то, что вы хотите, было бы использовать QSortFilterProxyModel
подкласс (я буду называть его model2
) в tableView2
, переопределить filterAcceptsRow()
, чтобы принимать только строки с column5 > 10
, и установить для его исходной модели значение model1
(ваш оригинал QSqlTableModel
).
Это приведет к синхронизации обеих моделей вместе, редактирование любой из них будет автоматически применено к обеим моделям.
Вот как может выглядеть ваш QSortFilterProxyModel
подкласс:
class MyFilterModel : public QSortFilterProxyModel{
public:
explicit MyFilterModel(QObject* parent= nullptr):QSortFilterProxyModel(parent){}
~MyFilterModel(){}
void setCol5Min(int val){
col5Min= val;
invalidateFilter();
}
protected:
bool filterAcceptsRow(int source_row, const QModelIndex amp;/*source_parent*/) const{
//get index using source_row, and the column you want to filter
QModelIndex index4= sourceModel()->index(source_row, 4);
//accept the row only when col5's value is greater than col5Min
return (sourceModel()->data(index4).toInt() > col5Min);
}
private:
int col5Min;
};
и вы можете использовать это следующим образом:
QSqlTableModel *model1 = new QSqlTableModel(this, db);
model1->setTable(tableName);
model1->select();
tableView1->setModel(model1);
MyFilterModel* model2= new MyFilterModel(this);
model2->setCol5Min(10);
model2->setSourceModel(amp;model1);
tableView2->setModel(model2);
Единственным недостатком вышеупомянутого подхода является то, что фильтрация не выполняется в базе данных (это делается в коде вашего приложения), поэтому вы не можете воспользоваться преимуществами любых индексов, которые у вас могут быть, col5
например (но если у вас 500 строк, это вообще не проблема).
Если вы хотите, чтобы фильтрация выполнялась в базе данных, вам придется использовать два отдельных QSqlTableModel
с:
QSqlTableModel *model1 = new QSqlTableModel(this, db);
model1->setTable(tableName);
model1->select();
tableView1->setModel(model1);
QSqlTableModel *model2 = new QSqlTableModel(this, db);
model2->setTable(tableName);
model2->setFilter("colum5 > 10");
model2->select();
tableView2->setModel(model2);
Но это не приведет к синхронизации ваших табличных представлений. Когда пользователь редактирует одно из табличных представлений, вам придется обновить другое.
Комментарии:
1. Большое вам спасибо.
QSortFilterProxyModel
это хороший способ решения моей проблемы, поскольку мне нужно синхронизировать с представлениями модели. Еще раз спасибо.