Унаследованный класс от QSplitter

190
17 октября 2018, 18:40

В процессе изучения Qt столкнулся с небольшой проблемой, есть программа "Обозреватель", она в книге написана в функции main(), все работает как надо, я же хочу этот код вписать в отдельный файл/класс унаследованный от QSplitter, ошибку не выдает, но запускается с пустым окном.

сам код:

Splitter::Splitter(QSplitter* parent) : QSplitter(Qt::Horizontal,     parent)
{
    QFileSystemModel                model;
    model.setRootPath(QDir::rootPath());
    QTreeView*                      pTreeView = new QTreeView;
    pTreeView->setModel(&model);
    QTableView*                     pTableView = new QTableView;
    pTableView->setModel(&model);
    QObject::connect(pTreeView,     SIGNAL(clicked(const QModelIndex&)),    pTableView, SLOT(setRootIndex(const QModelIndex&)));
    QObject::connect(pTableView,    SIGNAL(activated(const QModelIndex&)),  pTreeView,  SLOT(setCurrentIndex(const QModelIndex&)));
    QObject::connect(pTableView,    SIGNAL(activated(const QModelIndex&)),  pTableView, SLOT(setRootIndex(const QModelIndex&)));
    addWidget(pTreeView);
    addWidget(pTableView);
    resize(600, 400);
    setWindowTitle("Файловый менеджер");
}
Answer 1

QFileSystemModel model - этот объект существует лишь в пределах конструктора. Вы передаете его адресс в метод setModel, но после выхода из конструктора этот объект деструктурируется и QTableView и QTreeView остаются без модели, отсюда все проблемы.

Сделайте model указателем на QFileSystemModel и распределите для него динамически память.

Splitter::Splitter(QSplitter* parent) : QSplitter(Qt::Horizontal,     parent)
{
    QFileSystemModel * model = new QFileSystemModel;
    model->setRootPath(QDir::rootPath());
    QTreeView*                      pTreeView = new QTreeView;
    pTreeView->setModel(model);
    QTableView*                     pTableView = new QTableView;
    pTableView->setModel(model);
    QObject::connect(pTreeView,     SIGNAL(clicked(const QModelIndex&)),    pTableView, SLOT(setRootIndex(const QModelIndex&)));
    QObject::connect(pTableView,    SIGNAL(activated(const QModelIndex&)),  pTreeView,  SLOT(setCurrentIndex(const QModelIndex&)));
    QObject::connect(pTableView,    SIGNAL(activated(const QModelIndex&)),  pTableView, SLOT(setRootIndex(const QModelIndex&)));
    addWidget(pTreeView);
    addWidget(pTableView);
    resize(600, 400);
    setWindowTitle("Файловый менеджер");
}

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

Answer 2

А зачем так наследоваться от сплиттера? Вы же не добавляете никакую новую функциональность в него. К тому же задача сплиттера, как следует из названия, всего лишь отобразить нечто с разделительной полосой, которую можно двигать, уменьшая/увеличивая виджеты, которые в нем есть. Скорее всего, вам нужно сделать класс окна - либо Widget, либо MainWindow, в котором будет весь этот функционал. Сплиттер можно сделать центральным виджетом окна.

    class MainWindow : public QMainWidget {
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr) 
    {
        model_ = new QFileSystemModel(this);
        model_->setRootPath(QDir::rootPath());
        pTreeView_ = new QTreeView(this);
        pTreeView_->setModel(model);
        pTableView_ = new QTableView(this);
        pTableView_->setModel(model);
        // connect signal slots
        mainSplitter_->addWidget(pTreeView_);
        mainSplitter_->addWidget(pTableView_);
        setMCentralWidget(mainSplitter_);
        resize(600, 400);
        setWindowTitle("Файловый менеджер");
    }
private:
    //...
    QFileSystemModel *model_;
    QTreeView *pTreeView_;
    QTableView *pTableView_;
    QSplitter *mainSplitter_;
}

P.S. и как говорят Эрик и Элизабет Фримен композиция зачастую предпочтительнее наследования. Отличная книга, советую.

READ ALSO
lvalue to rvalue conversion

lvalue to rvalue conversion

Что такое lvalue to rvalue conversion? В этой статье непонятно следующее:

186
Qt Android в Linux

Qt Android в Linux

Можно ли писать приложения под Android на c++ с qt в Linux и какие для этого нужны компоненты?

158
Реализация архитектуры приложения MVP

Реализация архитектуры приложения MVP

Представление строит свой презентер, презентер получает ссылку на IView и строит свою модельВопрос: где строить подчиненные IView, в презентере...

164
Ссылка на реализацию без экземпляра

Ссылка на реализацию без экземпляра

Начал изучать книгу Эрика и Элизабет Фримен Паттерны проектированияПытаюсь написать на C++ архитектуру из первой главы

224