问题
I have a QStandardItemModel
. This model might get additional columns via an input widget.
In addition, the QStandardItemModel
is the model of a QTreeView
.
I would like to guarantee that just the first n columns of the QStandardItemModel
are visualised in the QTreeView
.
How could I achieve this?
But:
- The model is not aware of the view (expect Qt does something in the background)
- The view is not informed about the updated columns by my code. Nevertheless, the new columns are visualised.
What is my motivation?
I would like to visualise the first n columns in a QTreeView
. On selection of an item the remaining columns (of the row of the selected item) shall be presented in a QTableWidget
as rows.
回答1:
But:
- The model is not aware of the view (expect Qt does something in the background)
- The view is not informed about the updated columns by my code. Nevertheless, the new columns are visualised.
You are correct that the model is unaware of the view. This is exactly how it should be and is good practice. The Qt Model-View Framework is a good practical implementation of the Model-View-Controller (MVC) Pattern
Models are not supposed to know what's going to be viewed or not, thier responsibility is to store and organise data and properties of those data.
Views connect to models and have a read-only relationship with them. They must be notified when changes are made to the models so that they know that they must update themselves. In Qt
this is done by connecting signals in the model to slots in the view. These connections are made in the function QAbstractItemView::setModel
Your question deals specifically with the display of columns and in Qt
, the main Item View classes delegate the responsibility of column and row visibility to the QHeaderView
class, which is created automatically by all views by default.
If you want to create special functionality, you need to either manipulate these default views, or else setting a custom header view to the main view.
I've done the second option.
I've also connected the model to two views, one that is limited to show only the first 5 columns and the second one without a custom header view. This is to show that the underlying model is completely unaware of the viewing restrictions and still contains the complete data set.
#include <QtWidgets/QApplication>
#include <QtWidgets/qtreeview.h>
#include <QtGui/qstandarditemmodel.h>
#include <QtWidgets/QHeaderView>
class RestrictedHeaderView : public QHeaderView {
Q_OBJECT
public:
RestrictedHeaderView(int cols, QWidget *parent = 0) : QHeaderView(Qt::Horizontal, parent), visibleColumns(cols) {}
protected slots:
virtual void sectionsInserted(QModelIndex const &parent, int logicalFirst, int logicalLast){
if (!parent.isValid() && logicalLast >= visibleColumns){
for (int col = visibleColumns; col <= logicalLast; ++col){
hideSection(col);
}
}
}
private:
int visibleColumns;
};
#include "main.moc"
int main(int argc, char** argv){
QApplication app(argc, argv);
QTreeView view;
view.setWindowTitle("Limited View");
QTreeView view2;
view2.setWindowTitle("Complete View");
QStandardItemModel model(4, 4);
for(int row = 0; row < 4; ++row){
for(int column = 0; column < 4; ++column){
QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
model.setItem(row, column, item);
}
}
// Apply the model to both views and show them
view.setModel(&model);
view.show();
view2.setModel(&model);
view2.show();
// set a custom header to the limited view only so that it automatically hides all columns that are inserted after the fifth column
view.setHeader(new RestrictedHeaderView(5));
// Add new columns to the underlying model
model.insertColumns(4, 3);
for (int row = 0; row < 4; ++row){
for(int column = 4; column < 7; ++column){
QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
model.setItem(row, column, item);
}
}
return app.exec();
}
来源:https://stackoverflow.com/questions/33053125/hide-future-columns-of-qstandarditemmodel-in-qtreeview