Скрыть будущие столбцы QStandardItemModel в QTreeView

У меня есть QStandardItemModel, Эта модель может получить дополнительные столбцы через виджет ввода.

В дополнение QStandardItemModel это модель QTreeView,

Я хотел бы гарантировать, что только первые n столбцов QStandardItemModel визуализируются в QTreeView,

Как я мог этого добиться?

Но:

  • Модель не знает о представлении (предположим, что Qt что-то делает в фоновом режиме)
  • Представление не информируется об обновленных столбцах моим кодом. Тем не менее, новые столбцы визуализируются.

Какова моя мотивация?

Я хотел бы визуализировать первые n столбцов в QTreeView, При выборе элемента остальные столбцы (строки выбранного элемента) должны быть представлены в QTableWidget как строки.

1 ответ

Решение

Но:

  • Модель не знает о представлении (предположим, что Qt что-то делает в фоновом режиме)
  • Представление не информируется об обновленных столбцах моим кодом. Тем не менее, новые столбцы визуализируются.

Вы правы, что модель не знает о представлении. Именно так и должно быть, и это хорошая практика. Каркас Qt Model-View является хорошей практической реализацией шаблона Model-View-Controller (MVC).

Модели не должны знать, что будет просматриваться или нет, их обязанность - хранить и систематизировать данные и свойства этих данных.

Представления подключаются к моделям и имеют с ними отношения только для чтения. Они должны быть уведомлены о внесении изменений в модели, чтобы они знали, что они должны обновить себя. В Qt это делается путем подключения сигналов в модели к слотам на виде. Эти соединения сделаны в функции QAbstractItemView::setModel

Ваш вопрос касается конкретно отображения столбцов и в Qtосновные классы Item View делегируют ответственность за видимость столбцов и строк QHeaderView класс, который создается автоматически всеми представлениями по умолчанию.

Если вы хотите создать специальную функциональность, вам нужно либо манипулировать этими представлениями по умолчанию, либо установить настраиваемый вид заголовка для основного вида.

Я сделал второй вариант.

Я также подключил модель к двум представлениям, одно из которых ограничено отображением только первых 5 столбцов, а второе - без настраиваемого представления заголовка. Это должно показать, что базовая модель полностью не знает об ограничениях просмотра и все еще содержит полный набор данных.

#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();
}
Другие вопросы по тегам