我写了一个小Qt原型,其中包含QTreeView
,我插入QStandardItemModel
。从那里,我希望能够在QTableView
中查看我的树的最后一级,我希望它是可排序的,为什么不可以过滤。这似乎是使用QSortFilterProxyModel
的完美场景。实施后,全局视图看起来像我想要的左侧是QTreeView
,右侧是QTableView
(见附图)。
但是,我面临两个问题:
我可能误解了有关Qt代理模型的使用但不知道什么,我在堆栈或其他地方找不到任何明确的提示。
这是我的原型cpp文件:
#include <string>
#include <vector>
#include <QDebug>
#include <QAbstractProxyModel>
#include <QSortFilterProxyModel>
#include <QStandardItem>
#include <QStandardItemModel>
#include "mainwindow.h"
#include "ui_mainwindow.h"
struct Peak {
Peak(const std::string& name, int index, double qx, double qy, double qz);
std::string _name;
int _index;
double _qx;
double _qy;
double _qz;
};
Peak::Peak(const std::string& name, int index, double qx, double qy, double qz)
: _name(name),
_index(index),
_qx(qx),
_qy(qy),
_qz(qz)
{
}
struct PeakItem : public QStandardItem
{
PeakItem(const Peak& peak);
Peak _peak;
};
PeakItem::PeakItem(const Peak& peak)
: _peak(peak)
{
setText(QString::fromStdString(_peak._name));
appendRow(new QStandardItem(QString::number(_peak._index)));
appendRow(new QStandardItem(QString::number(_peak._qx)));
appendRow(new QStandardItem(QString::number(_peak._qy)));
appendRow(new QStandardItem(QString::number(_peak._qz)));
}
struct PeakListItem : public QStandardItem
{
PeakListItem(const std::vector<Peak>& peaks);
std::vector<Peak> _peaks;
};
PeakListItem::PeakListItem(const std::vector<Peak>& peaks)
: _peaks(peaks)
{
setText("Peaks");
setCheckable(true);
for (size_t r=0; r < _peaks.size(); ++r) {
auto item = new PeakItem(_peaks[r]);
appendRow(item);
}
}
struct PeakListProxyModel : public QSortFilterProxyModel {
PeakListProxyModel(PeakListItem* peak_list_item);
virtual QModelIndex mapFromSource(const QModelIndex &) const override;
virtual QModelIndex mapToSource(const QModelIndex &) const override;
virtual QModelIndex parent(const QModelIndex &) const override;
virtual QModelIndex index(int, int, const QModelIndex & p = QModelIndex()) const override;
virtual int rowCount(const QModelIndex & p = QModelIndex()) const override;
virtual int columnCount(const QModelIndex & p = QModelIndex()) const override;
virtual void sort(int column, Qt::SortOrder order) override;
PeakListItem* _peak_list_item;
};
PeakListProxyModel::PeakListProxyModel(PeakListItem* peak_list_item)
: _peak_list_item(peak_list_item)
{
}
QModelIndex PeakListProxyModel::parent(const QModelIndex &) const
{
return QModelIndex();
}
QModelIndex PeakListProxyModel::index(int row, int column, const QModelIndex& index) const
{
// qDebug()<<"create index "<<row<<" --- "<<column<<" --- "<<index;
return createIndex(row, column);
}
void PeakListProxyModel::sort(int column, Qt::SortOrder order)
{
qDebug()<<"sort "<<column;
QAbstractProxyModel::sort(column,order);
layoutChanged();
}
QModelIndex PeakListProxyModel::mapFromSource(const QModelIndex& source_index) const
{
if (!source_index.isValid()) {
return QModelIndex();
}
auto model = dynamic_cast<QStandardItemModel*>(sourceModel());
auto item = model->itemFromIndex(source_index);
auto parent_item = item->parent();
auto p = dynamic_cast<PeakItem*>(parent_item);
if (!p) {
return QModelIndex();
}
auto proxy_index = createIndex(parent_item->index().row(),item->index().row());
qDebug()<<"map from source --- "<<source_index<<" --- "<<proxy_index;
return proxy_index;
}
QModelIndex PeakListProxyModel::mapToSource(const QModelIndex& proxy_index) const
{
if (!proxy_index.isValid()) {
return QModelIndex();
}
auto peak_item = _peak_list_item->child(proxy_index.row());
auto prop_item = peak_item->child(proxy_index.column());
auto source_index = prop_item->index();
// qDebug()<<"map to source "<<proxy_index<<" --- "<<source_index<<" ---- "<<prop_item;
return source_index;
}
int PeakListProxyModel::rowCount(const QModelIndex& proxy_index) const
{
if (proxy_index.isValid()) {
return 0;
} else {
return _peak_list_item->rowCount();
}
}
int PeakListProxyModel::columnCount(const QModelIndex& proxy_index) const
{
if (proxy_index.isValid()) {
return 0;
} else {
return 4;
}
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QStandardItemModel* model = new QStandardItemModel();
QStandardItem* experiment = new QStandardItem("Experiment");
QStandardItem* peaks_item = new QStandardItem("Peaks");
std::vector<Peak> peaks;
peaks.reserve(4);
for (int i = 0; i < 4; ++i) {
peaks.emplace_back("Peak"+std::to_string(i),i,i,i,i);
}
// PeakListItem* peak_list_item1 = new PeakListItem(peaks);
// peaks_item->appendRow(peak_list_item1);
PeakListItem* peak_list_item2 = new PeakListItem(peaks);
peaks_item->appendRow(peak_list_item2);
experiment->appendRow(peaks_item);
model->appendRow(experiment);
ui->treeView->setModel(model);
PeakListProxyModel* proxy_model = new PeakListProxyModel(peak_list_item2);
proxy_model->setSourceModel(model);
ui->tableView->setModel(proxy_model);
ui->tableView->setSortingEnabled(true);
for (int i = 0; i < peaks.size(); ++i) {
// ui->treeView->setRowHidden(i,peak_list_item1->index(),true);
// ui->treeView->setRowHidden(i,peak_list_item2->index(),true);
}
}
MainWindow::~MainWindow()
{
delete ui;
}
答案 0 :(得分:1)
深入挖掘后,我发现link
基本上解释了如何解决我的问题。为了完成这项工作,我们必须管道两个模型,一个执行从QAbstractProxyModel
派生的映射,另一个执行排序/文件串,可以是标准QSortFilterProxyModel
。