QSplitter, how to change the widget of one side without resizing?



  • Hi,
    My use case is simple, I've an Horizontal Splitter, on the left side, I've a TreeView where a Model is displayed and on the right I've Editor that should be updated depending on the selected Item in the Model.
    So I'd like to be able to remove the right widget and replace it with another one and while doing this that the Splitter doesn't resize.
    how can I do that?
    If I delete the widget on the right, the Splitter resize...
    I've tried also to delete only the content of the right widget in order to refill the same one but this doesn't seem to work properly either...
    Any idea how I could achieve that?
    Cheers


  • Moderators

    @mbruel "I've tried also to delete only the content of the right widget in order to refill the same one but this doesn't seem to work properly either" - that's actualy what you should do. What did not work? Can you show the code?



  • When I say it is not working properly it is because the splitter is moving when I change the widget.

    Here is what I've done:
    On my Mainwindow I've a QTreeView on the left, and on the right a QWidget called propertyEditor.

    Solution 1: keeping the same propertyEditor and deleting its content:

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        _ui(new Ui::MainWindow),
        _treeModel(new TreeModel()),
        _treeItemDelegate(new TreeItemDelegate()),
        _propertyLayout(new QVBoxLayout())
    {
        _ui->setupUi(this);
    
        _ui->treeView->setModel(_treeModel);
        _ui->treeView->setItemDelegate(_treeItemDelegate);
    
        _ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
        connect(_ui->treeView, &QWidget::customContextMenuRequested, this, &MainWindow::showCustomContextMenu);
    
        connect(_ui->treeView, &QAbstractItemView::clicked, this, &MainWindow::handleTreeClick);
    
        _ui->propertyEditor->setLayout(_propertyLayout);
    }
    
    void MainWindow::handleTreeClick(const QModelIndex &index)
    {
        TreeItem *item = static_cast<TreeItem*>(_treeModel->itemFromIndex(index));
        if (!item)
            return;
    
        switch(item->getType())
        {
        case (TreeItemType::TreeElementItem):
            clearPropertyWidget();
           _propertyLayout->addWidget(static_cast<TreeElemItem*>(item)->getElement()->createEditorWidget());
           break;
    
        default:
            clearPropertyWidget();
           break;
        }
    }
    
    void MainWindow::clearPropertyWidget()
    {
        qDebug() << "[MainWindow::clearPropertyWidget] nb items: " << _propertyLayout->count();
        while (_propertyLayout->count())
        {
            QLayoutItem *item = _propertyLayout->takeAt(0);
            if (item->widget())
                delete item->widget();
            else if (item->layout())
                delete item->layout();
        }
    }
    
    

    Solution 2: Deleting the propertyWidget and adding a new one in the Splitter each time

    void MainWindow::handleTreeClick(const QModelIndex &index)
    {
        TreeItem *item = static_cast<TreeItem*>(_treeModel->itemFromIndex(index));
        if (!item)
            return;
    
        switch(item->getType())
        {
        case (TreeItemType::TreeElementItem):
            clearPropertyWidget();
    
            _ui->propertyEditor = new QWidget();
            _propertyLayout = new QVBoxLayout();
            _ui->propertyEditor->setLayout(_propertyLayout);
    
           _propertyLayout->addWidget(static_cast<TreeElemItem*>(item)->getElement()->createEditorWidget());
           _ui->splitter->addWidget(_ui->propertyEditor);
           break;
    
        default:
            clearPropertyWidget();
           break;
        }
    }
    
    void MainWindow::clearPropertyWidget()
    {
            if (_propertyLayout)
            {
                _ui->propertyEditor->hide();
                delete _ui->propertyEditor;
                _propertyLayout = nullptr;
            }
    }
    

    In both case, the Splitter is moving by itself when the propertyEditor is changing it's content or get empty.


  • Moderators

    @mbruel You could try different values for sizePolicy property in the right widget (maybe Ignored?).



  • I've set both my left QTreeView and the right QWidget with a Fixed size policy and add them both a minimum Size and that seems to solve the resizing issue.

    There is just a little thing that still annoys me: I can move the slider left or right until I reach the minimum size of the widgets but if I continue to slide until the limit one of the widget will take the whole area and the other one will disappear.
    Is there a way to block this behaviour?


  • Lifetime Qt Champion

    Hi,

    Use QSplitter::setCollapsible on your widgets and you should be good to go.



  • Cool thanks for this :)
    Last little thing: when I'm reducing my treeview, instead of having straight away the scrollbar of the QScrollArea containing the TreeView, first the Text of my TreeItems is truncated with ...
    How can I stop this behaviour?


  • Lifetime Qt Champion

    You might have to implement a custom QStyledItemDelegate and customise the QStyleOptionViewItem and disable the QStyleOptionViewItem::WrapText option.



  • The WrapText Option was already disabled (myOption.features.testFlag(QStyleOptionViewItem::WrapText) returns false)
    By digging a little bit in QStyleOptionViewItem, I've found the attribute I'm interested in:

    myOption.textElideMode = Qt::ElideNone;
    

    However I'm still not having my desired behaviour.
    My Widget is a QSplitter with on the left a QTreeView and on the Right a QScrollArea with a custom widget.
    When I decrease the area of the QTreeView, the Scrollbar is not kicking in as soon as the Text of some Items can't be displayed entirely.
    I've tried to put a _ui->treeView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) but it doesn't change anything.
    I've also tried to put my QTreeView inside a QScrollArea but this wouldn't work also and I would see 2 scrollbars.

    So what I would like is to stop the ElideMode and thus that the ViewPort of the QTreeView kicks in as soon as some Item would have been elided.
    Any idea how to achieve that?
    Cheers


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.