How to set the base size of QDockWidget?
-
I've been scratching my head on how to do this for a while and nothing seems to be working.
I have a
QDockWidget
on the Designer in which I have promoted the innards to a custom class. It looks like this on the designer side:Object Class DockWidget QDockWidget | | -> TestPanel -> TestWidget
The
TestWidget
class inherits aQWidget
in which I have another class,PageLayout
create the contents of the widget so it can be placed inside theTestWidget
class.The problem seems to be whenever I am creating a new page for the
QTabWidget
and laying it inside theQGridLayout
. Not matter what I do I cannot seem to resize it from it's base size. I have tried overriding the size hint and that hasn't worked, I have tried setting all of the widgets base size in the designer and in the code, and that doesn't work either. I am running out of options and I am not sure where to go at this point.Here is the problematic
TestPage
class (header first):#ifndef TESTPAGE_HPP #define TESTPAGE_HPP #include <QWidget> #include <QGridLayout> #include <QCheckBox> #include <QButtonGroup> #include <QLabel> #include <QComboBox> #include <QRadioButton> #include <QStringList> #include <QSpinBox> #include <QToolButton> #include <vector> #include <functional> class TestPage : public QWidget { Q_OBJECT public: TestPage(); signals: private: void setButtonGroup(); void setComboBox(); void addRow0(); void addRow1(); void addRow2(); void addRow3(); void addRow4(); void addRow5(); void addRow6(); void constructLayout(); QGridLayout *gridLayout = new QGridLayout(); QCheckBox *rotationCheckBox = new QCheckBox("Rotation"); QCheckBox *timeBatchCheckBox = new QCheckBox("Time Sequence/Batch"); QButtonGroup *buttonGroup = new QButtonGroup(); QRadioButton *xButton = new QRadioButton(); QRadioButton *yButton = new QRadioButton(); QRadioButton *zButton = new QRadioButton(); QSpinBox *degreesSpinbox = new QSpinBox(); QSpinBox *startTimeSpinbox = new QSpinBox(); QSpinBox *endTimeSpinbox = new QSpinBox(); QSpinBox *currentTimeSpinbox = new QSpinBox(); QSpinBox *secondsSpinbox = new QSpinBox(); QLabel *degreesLabel = new QLabel("Degrees"); QLabel *styleLabel = new QLabel("Style: "); QLabel *currentTimeLabel = new QLabel("Current Time: "); QLabel *startTimeLabel = new QLabel("Start Time: "); QLabel *endTimeLabel = new QLabel("End Time: "); QLabel *movieLenLabel = new QLabel("Moview Length: "); QLabel *secondsLabel = new QLabel("seconds"); const QStringList styleList = { "Linear", "Smooth" }; QComboBox *styleComboBox = new QComboBox(); QToolButton *minusPushbutton = new QToolButton(); QToolButton *plusPushbutton = new QToolButton(); const std::vector<std::function<void()>> rowFuncs = { std::bind(&TestPage::addRow0,this), std::bind(&TestPage::addRow1,this), std::bind(&TestPage::addRow2,this), std::bind(&TestPage::addRow3,this), std::bind(&TestPage::addRow4,this), std::bind(&TestPage::addRow5,this), std::bind(&TestPage::addRow6,this) }; virtual QSize sizeHint() const; }; #endif // TESTPAGE_HPP
Source File:
#include "testpage.hpp" TestPage::TestPage() { setButtonGroup(); setComboBox(); constructLayout(); this->setLayout(gridLayout); this->resize(300,200); this->setBaseSize(300,200); // I've tried setting base size to sizeHint() here, did not work. } void TestPage::setComboBox() { styleComboBox->addItems(styleList); } void TestPage::setButtonGroup() { buttonGroup->addButton(xButton); buttonGroup->addButton(yButton); buttonGroup->addButton(zButton); } void TestPage::addRow0() { gridLayout->addWidget(rotationCheckBox,0,0,1,2); } void TestPage::addRow1() { gridLayout->addWidget(xButton,1,0); } void TestPage::addRow2() { gridLayout->addWidget(yButton,2,0); gridLayout->addWidget(degreesSpinbox,2,1); gridLayout->addWidget(degreesLabel,2,2); gridLayout->addWidget(styleLabel,2,4); gridLayout->addWidget(styleComboBox,2,5,1,2); } void TestPage::addRow3() { gridLayout->addWidget(zButton,3,0); } void TestPage::addRow4() { gridLayout->addWidget(timeBatchCheckBox,4,0,1,3); gridLayout->addWidget(currentTimeLabel,4,5,1,2); } void TestPage::addRow5() { gridLayout->addWidget(startTimeLabel,5,0); gridLayout->addWidget(startTimeSpinbox,5,1); gridLayout->addWidget(endTimeLabel,5,2); gridLayout->addWidget(endTimeSpinbox,5,3); gridLayout->addWidget(minusPushbutton,5,5); gridLayout->addWidget(currentTimeSpinbox,5,6); gridLayout->addWidget(plusPushbutton,5,7); } void TestPage::addRow6() { gridLayout->addWidget(movieLenLabel,6,3,1,2); gridLayout->addWidget(secondsSpinbox,6,6); gridLayout->addWidget(secondsLabel,6,7); } void TestPage::constructLayout() { for(const auto &fn : rowFuncs) fn(); } QSize TestPage::sizeHint() const { QSize baseSize(300,200); return baseSize; }
This class then get's set inside the
PageLayout
class (Header):#ifndef PAGELAYOUT_HPP #define PAGELAYOUT_HPP #include <QGridLayout> #include <QTabWidget> #include <QString> #include "testpage.hpp" #include <utility> class PageLayout : public QGridLayout { public: PageLayout(); private: QTabWidget *tabWidget = new QTabWidget(); void constructPages(); std::vector<std::pair<QWidget*,const QString>> pages = { {new QWidget(), "Dummy"}, //a test to see if this was a problem when TestPage is commented out. {new TestPage(), "Basic"} }; }; #endif // PAGELAYOUT_HPP
Source:
#include "pagelayout.hpp" PageLayout::PageLayout() { constructPages(); this->addWidget(tabWidget); } void PageLayout::constructPages() { for(const auto &page : pages) tabWidget->addTab(page.first,page.second); }
Which then finally get's passed to the final class
TestWidget
which is header only:#ifndef TESTWIDGET_HPP #define TESTWIDGET_HPP #include <QWidget> #include <QGroupBox> #include <QGridLayout> #include <QFrame> #include "pagelayout.hpp" class TestWidget : public QWidget { Q_OBJECT public: TestWidget() { topFrame->setLayout(pageLayout); frameLayout->addWidget(topFrame,0,0); testExportFrame->setLayout(frameLayout); widgetLayout->addWidget(testExportFrame); this->setLayout(widgetLayout); } private: QGroupBox *testExportFrame = new QGroupBox(); QGridLayout *frameLayout = new QGridLayout(); QGridLayout *widgetLayout = new QGridLayout(); QFrame *topFrame = new QFrame(); PageLayout *pageLayout = new PageLayout(); }; #endif // TESTWIDGET_HPP
When the program is run, the size of the
QDockWidget
never changes and it is really frustrating. I can set it to a maxSize and minSize, but I want the user to be able to resize the widget whenever they would like to. The Page that I have provided seems to be the problematic one as the other pages in theQTabWidget
that I have created do not seem to be a problem. I have four other pages that I have created but isolating them one by one shows that the specific page that I have provided to be the problem.If there is anyone that can help me out with this problem I would appreciate it.
If you want to build this project, simply add the files that I have provided to a new project, place a
QDockWidget
in the designer, and simply rename them to the Object to what I have provided up top. And promote the Widget underneath the Dock Widget to aTestWidget
and it should compile. Or see if this link will work: https://drive.google.com/open?id=1tP_KkIzfl48va8odluWmhDgPl4VvNjDu -
Hi,
I haven't fully read your code but the PageLayout class triggers warnings when I read it. Why are you subclassing a layout to put widgets in it ?
Since you do not do anything particular with that layout, you should rather have a widget that manages that, especially since that layout only contains a tab widget.
-
@SGaist That's a fair question and to answer that it's because on the actual dock widget itself, in the production code, there are two widgets that get placed inside the dock widget itself. The
topFrame
contains the layout for the QTabWidget as you have pointed out. The code that is not present,botFrame
contains another QGridLayout. These two then get placed inside the QGridLayout which is the layout ofQGroupBox
.Then to answer Why am I subclassing a layout to put widgets in it? I guess this is a personal decision and can be argued either way. For now, I will say that you are correct, that the Widget should manage the way the GridLayout adds widgets to them. However, I will argue that since QGridLayout is it's own class; the Widget does not "own" the widgets, rather, the layout owns the widgets since QWidget does not have a
addWidgets
function in it. Therefore, QGridLayout owns and is responsible for the Widgets that it owns. Hence the decision that the QWidget is the parent, which has a QGridLayout, which the QGridLayout as the Child, has the widgets that belong inside of it.This is a programming decision that I made with these arguments.