QMainWindow auto resize
-
Hi all,
Please take a look at these files:
List.h:
#ifndef LIST_H #define LIST_H #include <QMainWindow> #include "task.h" #include <QVector> class QLabel; class QPushButton; class QHBoxLayout; class QVBoxLayout; class List : public QMainWindow { Q_OBJECT public: explicit List(QWidget *parent = nullptr); void updateStatus(); ~List(); public slots: void addTask(); void removeTask(Task*); void taskStatusChanged(); private: QVector<Task*> mTasks; QLabel* statusLabel; QPushButton* addTaskButtun; QHBoxLayout* hBox; QVBoxLayout* vBox; }; #endif // LIST_H
List.cpp:
#include "list.h" #include <QPushButton> #include <QLabel> #include <QHBoxLayout> #include <QVBoxLayout> #include <QString> #include <QInputDialog> #include <QLineEdit> List::List(QWidget *parent) : QMainWindow(parent), mTasks() { statusLabel = new QLabel(tr("Status: 0 todo / 0 done")); addTaskButtun = new QPushButton(tr("Add task")); hBox = new QHBoxLayout; hBox->addWidget(statusLabel); hBox->addStretch(); hBox->addWidget(addTaskButtun); vBox = new QVBoxLayout; vBox->addLayout(hBox); vBox->addStretch(); QWidget *widget = new QWidget; widget->setLayout(vBox); setCentralWidget(widget); connect(addTaskButtun, &QPushButton::clicked, this, &List::addTask); updateStatus(); } //************************************************ void List::addTask() { bool ok; QString name = QInputDialog::getText(this, tr("Add Task"), tr("Task name"), QLineEdit::Normal, tr("Untitled task"), &ok); if(ok && !name.isEmpty()) { Task* task = new Task(name); connect(task, &Task::removed, this, &List::removeTask); connect(task, &Task::statusChanged, this, &List::taskStatusChanged); mTasks.append(task); vBox->addWidget(task); updateStatus(); } } //********************************************* void List::removeTask(Task* task) { mTasks.removeOne(task); vBox->removeWidget(task); delete task; updateStatus(); } //************************************** void List::taskStatusChanged() { updateStatus(); } //************************************ void List::updateStatus() { int completedCount = 0; for(auto t: mTasks) if(t->isCompleted()) completedCount++; int todoCount = mTasks.size() - completedCount; statusLabel->setText(QString("Statuse: %1 todo / %2 completed") .arg(todoCount) .arg(completedCount)); } //***************************** List::~List() { delete vBox; }
Task.h:
#ifndef TASK_H #define TASK_H #include <QWidget> #include <QString> class QCheckBox; class QPushButton; class QHBoxLayout; class Task : public QWidget { Q_OBJECT public: explicit Task(const QString&, QWidget* parent = nullptr); void setName(const QString&); QString name() const; bool isCompleted() const; ~Task(); public slots: void rename(); signals: void removed(Task*); void statusChanged(Task*); private slots: void checked(bool); private: QCheckBox* checkbox; QPushButton* editButton; QPushButton* removeButton; QHBoxLayout* hBox; }; #endif // TASK_H
Task.cpp:
#include "task.h" #include "list.h" #include <QInputDialog> #include <QWidget> #include <QHBoxLayout> #include <QPushButton> #include <QCheckBox> Task::Task(const QString& name, QWidget* parent) : QWidget (parent) { checkbox = new QCheckBox; editButton = new QPushButton(tr("Edit")); removeButton = new QPushButton(tr("Remove")); hBox = new QHBoxLayout; hBox->addWidget(checkbox); hBox->addStretch(); hBox->addWidget(editButton); hBox->addWidget(removeButton); setLayout(hBox); setName(name); connect(editButton, &QPushButton::clicked, this, &Task::rename); connect(removeButton, &QPushButton::clicked, [this]()->void { emit removed(this); }); connect(checkbox, &QCheckBox::toggled, this, &Task::checked); }; //************************************* void Task::setName(const QString& name) { checkbox->setText(name); } //******************************************** QString Task::name() const { return checkbox->text(); } //***************************** bool Task::isCompleted() const { return checkbox->isChecked(); } //**************************************** void Task::rename() { bool ok; QString value = QInputDialog::getText(this, tr("Edit task"), tr("Task name"), QLineEdit::Normal, this->name(), &ok); if(ok && !value.isEmpty()) setName(value); } //************************************ void Task::checked(bool checked) { QFont font(checkbox->font()); font.setStrikeOut(checked); checkbox->setFont(font); emit statusChanged(this); } //************************************************** Task::~Task() { delete hBox; }
When I add tasks "untitled task 1" to "untitled task 3", number 1 below:
then remove "untitled task 2", the frame/window doesn't shrink and the space for that task is just vacant, number 2. I like it to decrease and fit the remained tasks, like number 3. When a task is added, the window increases in size, so when one is removed, it should decreases in size too.
I tested the followings one by one in
void List::updateStatus() {
, but none worked as expected!What should be used instead, please?
this->sizeHint(); this->update(); this->resize(sizeHint()); this->adjustSize();
-
When the central widget resizes, call adjustSize on the window to make the window shrink to fit the size of the central widget. So, call
adjustSize();
at the end ofaddTask
andremoveTask
. -
When the central widget resizes, call adjustSize on the window to make the window shrink to fit the size of the central widget. So, call
adjustSize();
at the end ofaddTask
andremoveTask
.thanks for the answer. I used that:
void List::removeTask(Task* task) { mTasks.removeOne(task); vBox->removeWidget(task); delete task; updateStatus(); adjustSize(); }
But no changes in result! :|
-
@tomy The central widget isn't being resized when widgets are removed from the
vBox
layout. Call setSizeConstraint to ensure that the layout will set the size of the parent widget when child widgets are added and removed. So callvBox->setSizeConstraint(QLayout::SetFixedSize);
in theList
constructor. -
@tomy The central widget isn't being resized when widgets are removed from the
vBox
layout. Call setSizeConstraint to ensure that the layout will set the size of the parent widget when child widgets are added and removed. So callvBox->setSizeConstraint(QLayout::SetFixedSize);
in theList
constructor.SizeConstraint and the fixedsize, as the names suggest, keep the size fixed, although it doesn't in effect and the window is being larger each time a new task is added. Of course, it doesn't work vice versa, Yet!
I hoped there's a simple built-in function for that either in central widget or the window itself.
-
SizeConstraint and the fixedsize, as the names suggest, keep the size fixed, although it doesn't in effect and the window is being larger each time a new task is added. Of course, it doesn't work vice versa, Yet!
I hoped there's a simple built-in function for that either in central widget or the window itself.
@tomy
don't let the name fool you, according to this thread, it's exactly what you're looking for, and the name- setSizeConstraint(QLayout::SetFixedSize);- is just misleadinghttps://stackoverflow.com/questions/14980620/qt-layout-resize-to-minimum-after-widget-size-changes
-
@tomy
don't let the name fool you, according to this thread, it's exactly what you're looking for, and the name- setSizeConstraint(QLayout::SetFixedSize);- is just misleadinghttps://stackoverflow.com/questions/14980620/qt-layout-resize-to-minimum-after-widget-size-changes
-
setSizeConstraint(QLayout::SetFixedSize);- is just misleading
Do you mean it works in practice for the problem, even though the name suggests something else?
But in effect, it doesn't solve the issue.I didn't find a correct answer for my question here, but I like first to review most of the code. Starting from the header file
task.h
, on the top, we've got:class Task : public QWidget { Q_OBJECT
we here say that we need to inherit
QWdiegt
because without that,Task
is a simple C++ class with no GUI. Right, completely?This way, we both create a GUI widget and inherit worthwhile functions from
QWidget
. Right, once again?But
QWidget
is a big and heavy class, the QWidget class is the base class of all user interface objects, while the output window we create using it ultimately is very simple:Couldn't we inherit from a lighter class for that purpose?
-
@tomy said in QMainWindow auto resize:
while the output window we create using it ultimately is very simple:
But it's still a widget what you want to show - so yes you must derive from QWidget and there is also no way around it (and also no need for it).