Results 1 to 20 of 21

Thread: How to shrink a QMainWindow when its central widget is shrinked

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to shrink a QMainWindow when its central widget is shrinked

    We firstly have a button and label of the list on the top, and to hold it on top we need the spacer which comes after these.
    Well, that's the problem. Your code calls addWidget() instead of insertWidget() (see my post from earlier in this thread), which means that the spacer stays at the top of the vbox and pushes both up and down. The button and label get pushed up and the tasks get pushed down. When you add new tasks, this results in the window expanding. When you remove a task, the spacer just expands to add more space between the top and the remaining tasks and the window doesn't shrink.

    When you add a task, you need to insert it -above- the spacer so that the spacer is always the last thing in the vbox. When you remove a task, you need to resize the window so the spacer will shrink.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  2. #2
    Join Date
    Jan 2016
    Posts
    76
    Thanks
    28
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: How to shrink a QMainWindow when its central widget is shrinked

    Yes, thank you. These are right in theory, but when tested in practice, the result is quite different!

    I did these:
    Firstly removed vBox->addStretch(); in List's constructor. Then changed void List::addTask() to this:


    Qt Code:
    1. void List::addTask() {
    2. bool ok;
    3. QString name = QInputDialog::getText(this, tr("Add Task"), tr("Task name"),
    4. QLineEdit::Normal, tr("Untitled task"), &ok);
    5.  
    6. if(ok && !name.isEmpty()) {
    7. Task* task = new Task(name);
    8. connect(task, &Task::removed, this, &List::removeTask);
    9. connect(task, &Task::statusChanged, this, &List::taskStatusChanged);
    10. mTasks.append(task);
    11. vBox->insertWidget(vBox->count()-1, task);
    12. vBox->addStretch();
    13. updateStatus();
    14. }
    15. }
    To copy to clipboard, switch view to plain text mode 

    And here's also:

    Qt Code:
    1. void List::removeTask(Task* task) {
    2. mTasks.removeOne(task);
    3. vBox->removeWidget(task);
    4. task->deleteLater();
    5. updateStatus();
    6.  
    7. resize(height() - 100, width());
    8. }
    To copy to clipboard, switch view to plain text mode 

    The result is:

    3.PNG

    Why don't you test the project once?

  3. #3
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to shrink a QMainWindow when its central widget is shrinked

    Why don't you test the project once?
    Because I have my own code to write...

    In your addTask() slot, lines 11 and 12, you are adding a new stretch item every time you add a new task, but in the removeTask() slot, you are only removing the task widget. So you end up with a vbox that contains one stretch item for every task you add, and they never go away. So when you call insertWidget(), you are probably putting the new task in between two stretch items and then sticking a new stretch item onto the end of that.

    Going back to your original post in this thread, you are building the central widget by:

    1 - creating a generic QWidget to act as the central widget.
    2 - adding a vbox as its layout.
    3 - inserting an hbox layout with your buttons, etc. as the first item in the vbox
    4 - adding a stretch to the end of the vbox to push the hbox to the top of the vertical layout

    OK so far. Your desired behavior is for the main window to grow as you add Task items (widgets) to it and to shrink as they are removed.

    To add a new task, you want to insert it between the stretch item (which is always at the bottom of the vbox) and whatever is above it (the hbox, more tasks, whatever).

    After the initial construction of the vbox, the item count is 2 (the hbox and the stretch). So you want to call insertWidget() with the argument count - 1. You do not add new stretch and you do not change the position of the stretch that you added at the start. It always stays at the bottom of the vbox and everything else goes above it and below the hbox.

    To add more tasks to the list, you do exactly the same - insertWidget with count - 1 as the position argument.

    To remove a task, your existing code should be OK. Find the task widget in the vbox, take it, then resize the vbox to remove the space taken up by the widget you just removed. The stretch still stays at the bottom and the hbox at the top, unchanged.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  4. #4
    Join Date
    Jan 2016
    Posts
    76
    Thanks
    28
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: How to shrink a QMainWindow when its central widget is shrinked

    Only these parts are changed compared to the first code:

    Qt Code:
    1. List::List(QWidget *parent)
    2. : QMainWindow(parent), mTasks()
    3. {
    4. statusLabel = new QLabel(tr("Status: 0 todo / 0 done"));
    5. addTaskButtun = new QPushButton(tr("Add task"));
    6. cWidget = new QWidget;
    7.  
    8. hBox = new QHBoxLayout;
    9. hBox->addWidget(statusLabel);
    10. hBox->addStretch();
    11. hBox->addWidget(addTaskButtun);
    12.  
    13. vBox = new QVBoxLayout;
    14. vBox->addLayout(hBox);
    15. vBox->addStretch();
    16.  
    17. cWidget->setLayout(vBox);
    18. setCentralWidget(cWidget);
    19.  
    20. connect(addTaskButtun, &QPushButton::clicked, this, &List::addTask);
    21. updateStatus();
    22. }
    23.  
    24. //************************************************
    25.  
    26. void List::addTask() {
    27. bool ok;
    28. QString name = QInputDialog::getText(this, tr("Add Task"), tr("Task name"),
    29. QLineEdit::Normal, tr("Untitled task"), &ok);
    30.  
    31. if(ok && !name.isEmpty()) {
    32. Task* task = new Task(name);
    33. connect(task, &Task::removed, this, &List::removeTask);
    34. connect(task, &Task::statusChanged, this, &List::taskStatusChanged);
    35. mTasks.append(task);
    36. vBox->insertWidget(vBox->count()-1, task);
    37. updateStatus();
    38. }
    39. }
    40.  
    41. //*********************************************
    42.  
    43. void List::removeTask(Task* task) {
    44. mTasks.removeOne(task);
    45. vBox->removeWidget(task);
    46. task->deleteLater();
    47. updateStatus();
    48. resize(height() - task->height(), task->width()); // Here we resize the window, List
    49. }
    To copy to clipboard, switch view to plain text mode 


    The outcome is not very bad but still far from a decent app!

    3.PNG

    4.PNG

  5. #5
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to shrink a QMainWindow when its central widget is shrinked

    OK, here's one last thing to try. The stretch at the bottom really seems to be messing things up when trying to dynamically resize the main window.

    In removeTask(), try this:

    - remove the task.
    - remove the stretch
    - resize the height
    - add the stretch back in

    If this still doesn't work, then I will implement some code and solve it. It can't be this hard.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  6. #6
    Join Date
    Jan 2016
    Posts
    76
    Thanks
    28
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: How to shrink a QMainWindow when its central widget is shrinked

    A question, in vBox->insertWidget(vBox->count()-1, task);
    Isn't "count" one beyond the last element? And "count-1" the last indeed element? Also, isn't "stretch" counted as an element in the layout?

    Anyway, I used this for the function:

    Qt Code:
    1. void List::removeTask(Task* task) {
    2. mTasks.removeOne(task);
    3. vBox->removeWidget(task);
    4. task->deleteLater();
    5. delete vBox->takeAt(vBox->count()-1);
    6. resize(height() - task->height(), task->width()); // Here we resize the window, List
    7. vBox->addStretch();
    8. updateStatus();
    9. }
    To copy to clipboard, switch view to plain text mode 

    And after adding a number of task and removing them continually reaching the fist task, the following result emerged:

    1.PNG

  7. #7
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to shrink a QMainWindow when its central widget is shrinked

    The "index" argument in insertWidget() is the place where the new widget will be placed. So if the vbox has two items in it (the hbox and the stretch), count = 2, count - 1 = 1, so the widget will be inserted at index 1, which is between the hbox and the stretch. The stretch becomes index 3. The hbox stays at index 0.

    So in order for insertWidget( vbox->count() - 1 ) to work correctly, there has to be a minimum of two items in the vbox, so you have to build it with the hbox and the stretch in place before you start adding tasks. If you don't have the stretch, then the first task will be added at 0, on top of the hbox. Subsequent tasks will be added on top of the hbox as well.

    If I can find time, I will work on this sometime before the end of the week.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  8. The following user says thank you to d_stranz for this useful post:

    franky (31st July 2019)

  9. #8
    Join Date
    Jan 2016
    Posts
    76
    Thanks
    28
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: How to shrink a QMainWindow when its central widget is shrinked

    Thank you.
    I'm looking forward to seeing your solution.

Similar Threads

  1. Replies: 1
    Last Post: 10th August 2014, 21:06
  2. Replies: 0
    Last Post: 28th March 2013, 00:22
  3. Widget auto shrink
    By been_1990 in forum Qt Programming
    Replies: 9
    Last Post: 24th January 2013, 01:43
  4. Replies: 8
    Last Post: 28th June 2011, 14:57
  5. Central Widget of QMainWindow
    By sumsin in forum Qt Programming
    Replies: 3
    Last Post: 13th March 2006, 18:32

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.