Good, thanks. There's always a way in programming!
I added the slot in List, but I think inside it, vBox should be resized, not? (And not the central widget of QMainWindow)
Good, thanks. There's always a way in programming!
I added the slot in List, but I think inside it, vBox should be resized, not? (And not the central widget of QMainWindow)
The QMainWindow is in charge of resizing its contents. I am pretty sure it asks the layout for the central widget for its size hint and adds the frame, menu bars, toolbars, status bars sizes as appropriate. So if the vbox layout never shrinks, it will return a size hint that includes the empty space.
But try it out to resize the vbox. If it works, it works. Riht now, I don't see any method in the QVBoxLayout class (or its base classes) that allows you to directly set the size.
<=== 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.
franky (23rd July 2019)
Thanks.
I was actually much dealt with height() and width() in the List.cpp file, but these two both belong to the central widget and hence, I couldn't make the job done using them.
How to access the height/width of the base class (QMainWindow) which is indeed in charge of the overall size, please, so that we can modify it when a remove is accomplished?
Your List class is derived from QMainWindow, isn't it? If your slots to add / remove new Task widgets are in the List class, then you can just call "height()" in those slots and you will get the height of the List widget. You then just call resize() after you compute the new height.
You don't want to change the height using the pointer to the central widget because QMainWindow (List) and the layout won't let it happen.
<=== 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.
I added resize(height() - 100, width()) to removeTask, (-100, just to test):Your List class is derived from QMainWindow, isn't it? If your slots to add / remove new Task widgets are in the List class, then you can just call "height()" in those slots and you will get the height of the List widget. You then just call resize() after you compute the new height.
Qt Code:
void List::removeTask(Task* task) { mTasks.removeOne(task); vBox->removeWidget(task); delete task; updateStatus(); resize(height() - 100, width()); }To copy to clipboard, switch view to plain text mode
When I hover the mouse on height(), this message is shown:
inline int QWidget::height() const , so that QWidget in our example is List, right?
So in that slot, when we use resize via a smaller height, the widget List must resize normally, and since this slot is called each time we remove a Task, therefore List is expected to shrink that way.
But it doesn't work as expected!
Well, what does happen? Anything? Nothing?But it doesn't work as expected!
You should probably call "task->deleteLater()" instead of "delete task". You are in the middle of a slot, and control needs to return to the event loop so that Qt can clean up properly and take whatever other action is needed to redraw the UI. deleteLater() will delete the widget when the event loop runs.
<=== 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.
franky (25th July 2019)
Very good, thanks for the precious info. I use the function this way:
Qt Code:
void List::removeTask(Task* task) { mTasks.removeOne(task); vBox->removeWidget(task); task->deleteLater(); updateStatus(); resize(height() - 100, width()); }To copy to clipboard, switch view to plain text mode
After entering 5 tasks:
3.PNG
And then deleting the first four ones, I got this! It's actually the way I meant I doesn't work.![]()
4.PNG
Your last screen shot looks like you still have the spacer item as the first thing in the vbox. If the spacer item was at the end, task 5 would be pushed to the top of the layout. Instead, it looks like the spacer item is first and is pushing everything down.
Please show your code for adding a new task to the list.
<=== 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.
Yes. 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. Afterwards, in the addTask slot, we have this code, as before:Your last screen shot looks like you still have the spacer item as the first thing in the vbox.
Qt Code:
void List::addTask() { bool 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(); } }To copy to clipboard, switch view to plain text mode
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.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.
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.
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:
void List::addTask() { bool 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->insertWidget(vBox->count()-1, task); vBox->addStretch(); updateStatus(); } }To copy to clipboard, switch view to plain text mode
And here's also:
Qt Code:
void List::removeTask(Task* task) { mTasks.removeOne(task); vBox->removeWidget(task); task->deleteLater(); updateStatus(); resize(height() - 100, width()); }To copy to clipboard, switch view to plain text mode
The result is:
3.PNG
Why don't you test the project once?
Because I have my own code to write...Why don't you test the project once?
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.
Bookmarks