PDA

View Full Version : Resizing issues, minimum size is ignored by parent widgets



TheComet
21st March 2016, 07:30
I have created a Qt application with the following structure:
*

.
└── QMdiArea
* * └── QTabWidget
* * * * └── HeaderDataBrowser
* * * * * * └── QVBoxLayout
* * * * * * * * └── QSplitter
* * * * * * * * * * ├── QScrollArea1
* * * * * * * * * * │ * └── QVBoxLayout
* * * * * * * * * * │ * * * └── QTreeWidget
* * * * * * * * * * └── QScrollArea2
* * * * * * * * * * * * └── QVBoxLayout
* * * * * * * * * * * * * * ├── QwtPlot1
* * * * * * * * * * * * * * └── QwtPlot2

I'm having multiple issues.
1) It appears the parent widgets of the QwtPlot widgets are ignoring the minimum size constraints. The plots just start overlapping when things get small.
2) Even though the QwtPlot widgets are inside a QScrollArea, no scrollbars ever appear, even when resizing ridiculously small. Why?
3) Issue 1) applies to a lot of the other parent widgets. They just ignore the minimum size constraints of their child widgets.

*
This video demonstrates the issues I'm having.
1) The first run shows that the app can be scaled right down to a size that shouldn't be possible.
2) I then set the minimum size of both QwtPlot widgets to 200, 200. Now the plots don't resize smaller than 200, 200, but they begin overlapping each other. What I really want is to restrict the app's minimum size so that doesn't happen.
3) I then set the minimum size of the splitter widget to 300, 300 and show that the parent widgets of the application simply do not care. The scroll area gets clipped as the application is scaled down.
*

https://www.youtube.com/watch?v=bNPu9lbscCY
*
The following code replicates this behaviour (note: I'm running Qt5. Qt4 seems to have different behaviour for some reason):


#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QVBoxLayout>
#include <QMdiArea>
#include <QSplitter>
#include <QScrollArea>
#include <QTreeWidget>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

ui->centralWidget->setLayout(new QVBoxLayout);
QMdiArea* mdi = new QMdiArea;
ui->centralWidget->layout()->addWidget(mdi);

QTabWidget* tabWidget = new QTabWidget;
mdi->addSubWindow(tabWidget);
tabWidget->showMaximized();

QWidget* headerDataBrowser = new QWidget;
tabWidget->addTab(headerDataBrowser, "Header");

// Header data tree goes on the left side, TxSeq plots on the right
QVBoxLayout* browserLayout = new QVBoxLayout;
QSplitter* splitter = new QSplitter(headerDataBrowser);
browserLayout->addWidget(splitter);
headerDataBrowser->setLayout(browserLayout);

// Create scroll area and put a tree view inside it. Then add the scroll
// area to the left side of the splitter
QScrollArea* scroll = new QScrollArea;
scroll->setWidgetResizable(true);
splitter->addWidget(scroll);
QVBoxLayout* scrollLayout = new QVBoxLayout;
scroll->setLayout(scrollLayout);
QTreeWidget* treeWidget = new QTreeWidget;
scrollLayout->addWidget(treeWidget);

// Create layout on right side of splitter. This is where the plots are
// inserted. Also add it to a scroll area, but disable horizontal
// scrolling.
QScrollArea* plotArea = new QScrollArea;
//plotArea->setWidgetResizable(true);
//plotArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOf f);
splitter->addWidget(plotArea);
QVBoxLayout* plotLayout = new QVBoxLayout;
plotArea->setLayout(plotLayout);

// add some crap
for(int i = 0; i != 20; ++i)
(new QTreeWidgetItem(treeWidget))->setText(0, "Test " + QString::number(i));
}

MainWindow::~MainWindow()
{
delete ui;
}

*

anda_skoa
21st March 2016, 08:50
I don't think you are supposed to set a layout on a QScrollArea.
You just set its content widget and it can have any layout you want.

Cheers,
_

TheComet
21st March 2016, 10:21
Thanks, I tried what you said but I'm still getting the same behaviour. Even though the QTreeWidget has a minimum size, it's still possible to scale the window down to something that shouldn't be possible. The QTreeWidget simply gets clipped after it stops shrinking.

This is the updated code:


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

ui->centralWidget->setLayout(new QVBoxLayout);
QMdiArea* mdi = new QMdiArea;
ui->centralWidget->layout()->addWidget(mdi);

QTabWidget* tabWidget = new QTabWidget;
mdi->addSubWindow(tabWidget);
tabWidget->showMaximized();

QWidget* headerDataBrowser = new QWidget;
tabWidget->addTab(headerDataBrowser, "Header");

// Header data tree goes on the left side, TxSeq plots on the right
QVBoxLayout* browserLayout = new QVBoxLayout;
headerDataBrowser->setLayout(browserLayout);
QSplitter* splitter = new QSplitter;
browserLayout->addWidget(splitter);

// Create scroll area and put a tree view inside it. Then add the scroll
// area to the left side of the splitter
QTreeWidget* treeWidget = new QTreeWidget;
treeWidget->setMinimumSize(100, 100);
splitter->addWidget(treeWidget);

// add some crap
for(int i = 0; i != 20; ++i)
(new QTreeWidgetItem(treeWidget))->setText(0, "Test " + QString::number(i));
}

anda_skoa
21st March 2016, 10:32
There is no QScrollArea in this code.

Maybe use Designer for the widget that you then put into a tab, it makes working with splitters/layouts easier as you can test/preview more easily

Cheers,
_

TheComet
21st March 2016, 12:09
Okay I'm really confused. I built the hierarchy in Designer and it works exactly how I expected it to work. I then programmed the hierarchy out 1:1 and guess what? The code version doesn't work. The code version can be scaled down to a size that shouldn't be possible.

http://i.imgur.com/eCSMRP1.png

What am I missing? There must be some minor detail in the code version that I'm doing wrong, right?

Here is the designer .ui file:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>563</width>
<height>433</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QMdiArea" name="mdiArea">
<property name="viewMode">
<enum>QMdiArea::TabbedView</enum>
</property>
<widget class="QWidget" name="subwindow">
<property name="windowTitle">
<string>Subwindow</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTabWidget" name="tabWidget">
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Tab 1</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTreeWidget" name="treeWidget">
<column>
<property name="text">
<string>1</string>
</property>
</column>
<column>
<property name="text">
<string>New Column</string>
</property>
</column>
<column>
<property name="text">
<string>New Column</string>
</property>
</column>
<column>
<property name="text">
<string>New Column</string>
</property>
</column>
<column>
<property name="text">
<string>New Column</string>
</property>
</column>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
<property name="text">
<string>dfsdf</string>
</property>
<property name="text">
<string>ssdddf</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
<item>
<property name="text">
<string>New Item</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Tab 2</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>


Here is the code:

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QVBoxLayout>
#include <QMdiArea>
#include <QSplitter>
#include <QScrollArea>
#include <QTreeWidget>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

ui->centralWidget->setLayout(new QVBoxLayout);
QMdiArea* mdi = new QMdiArea;
mdi->setDocumentMode(true);
ui->centralWidget->layout()->addWidget(mdi);

QTabWidget* tabWidget = new QTabWidget;
mdi->addSubWindow(tabWidget);
tabWidget->showMaximized();

QWidget* tab = new QWidget;
tabWidget->addTab(tab, "Header");

QVBoxLayout* tabLayout = new QVBoxLayout;
tab->setLayout(tabLayout);

QWidget* widget = new QWidget;
tabLayout->addWidget(widget);

QVBoxLayout* widgetLayout = new QVBoxLayout;
widget->setLayout(widgetLayout);

QTreeWidget* treeWidget = new QTreeWidget;
treeWidget->setMinimumSize(200, 200);
widgetLayout->addWidget(treeWidget);

// add some crap
for(int i = 0; i != 20; ++i)
(new QTreeWidgetItem(treeWidget))->setText(0, "Test " + QString::number(i));
}

MainWindow::~MainWindow()
{
delete ui;
}

anda_skoa
21st March 2016, 12:29
Have you had a look at the generated code?
Maybe you are not having exactly the same thing?

Cheers,
_