QListWidget resize contents when splitter changes size - qt

I have a QListWidget with some widgets inside:
QListWidgetItem* w = new QListWidgetItem(ui->listWidget);
ui->listWidget->addItem(w);
w->setSizeHint(widget->sizeHint());
ui->listWidget->setItemWidget(w, widget);
However, everything seems to work fine until I resize the the QListWidget (it is embedded into a QDockwidget). Do I have to iterate over all items and resize them manually or is there a simple trick?
It is just a list with items having a button on the left and a button on the right. If the list gets resized (QSize changes) than the buttons gets hidden and a scrollbar appears. I want to have the size of the item according to the list width.

Try setting the resizeMode property to Adjust. This will cause your QListWidget to automatically resize all of the items in the view to the size of the QListWidget anytime the widget is resized.
See the documentation here. Your code will be structured like so:
QListWidgetItem* w = new QListWidgetItem(ui->listWidget);
w->setSizeHint(widget->sizeHint());
ui->listWidget->setResizeMode(QListView::Adjust);
ui->listWidget->addItem(w);
ui->listWidget->setItemWidget(w, widget);
EDIT: Depending on the uniformity of your items, you may also benefit from setting the uniformItemSizes property. QListView can optimize the layout of your view if you set this property.

Related

How can I exchange an item and a spacer?

In qt, I have a form that contains among other things, a group with
A combo box
a checkbox
a spacer
a button
Based on some logic, I want sometimes to show another combo box... Where the spacer is, but smaller.
When I add it though, everything resizes automatically
I don't see a way to make it invisible, and yet keep items of the same size when I make it visible again.
I tried making it fixed size... But unless I use fixed sizes and positioning for everything, which I think is a bad idea, the items still move around when I change visibility.
It seems silly... But how can I make my little combo box show up instead of the spacer not next to it ? Spacers don't seem to have a name...
I would do
combo.setVisible(condition);
Spacer.setVisible(!condition);
Very easy... Except how do I access the spacer from code ?
My suggestion is to use a container QWidget instead of the spacer. Here is how it will look:
A combo box
a checkbox
a widget-container
a button
Widget-container is a QWidget with fixed size. Put your combo-box there and it will maintain it's size when you show/hide the combo-box.
Regarding your question (You will not need it but just to know in the future):
how do I access the spacer from code
You can create a spacer from code like this:
QSpacerItem* spacer = new QSpacerItem(0, 15, QSizePolicy::Fixed, QSizePolicy::Fixed);
layout->addItem(spacer);
...
Also you can get it from a layout if you know its index:
QLayoutItem* item = layout->itemAt(index);
But there is no such method as show/hide for layout items.

Qt ScrollArea on widget messes up size and position of widget [Qt 5.1]

I'm new with Qt and I want to implement a scrollable widget which can grow dynamically, e.g. by adding buttons into it when another button is pressed. I try to implement it using the following layout and code:
scrollArea = new QScrollArea(ui->outerWidget);
scrollArea->setWidget(ui->innerWidget);
layout = new QVBoxLayout(ui->outerWidget);
ui->innerWidget->setLayout(layout);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// code for PushButton to add buttons in innerWidget
void MainWindow::on_pushButton_clicked()
{
QPushButton *button = new QPushButton("button"+QString::number( nameCounter ));
nameCounter ++;
ui->innerWidget->layout()->addWidget(button);
}
This implementation has two problems when I run the program, first the innerWidget appears out of place (I define its position in Qt Creator's Design mode) and second after many widgets are added in the layout the scroll bar is doesn't grow, but instead the widgets are become smaller to fit into the layout:
In another thread it was suggested to set widgetResizable to true:
scrollArea->setWidgetResizable(true);
The scroll bar seems to work now but the new problem is that the innerWidget becomes very small so it is barely visible:
So, how can I achieve a scrollable widget that will respect the size and position of the design?
have no environment to verify but good luck.
to place scrollArea the target position,
Manually call SetGeometry, or
Place a QScrollArea in ui form, (suggested if it's static), or
Place a widget in your target position, and set QScrollArea's parent to it, and add QScrollArea to its layout, and Set QScrollArea to be expanding.
manually create a QWidget innerWidget and assign it to scrollArea via QScrollArea::setWidget(*QWidget), try different size policy to innerWidget, such as "Preferred".
Also be aware of Qt's reference mentioned : void QScrollArea::setWidget ( QWidget * widget )
Sets the scroll area's widget.
....
Note that You must add the layout of widget before you call this function; if you add it later, the widget will not be visible - regardless of when you show() the scroll area. In this case, you can also not show() the widget later.
Above list solutions, below are reasons to the problems you mentioned:
scrollArea->setWidget(ui->innerWidget); Setting a widget to ScrollArea will change the parenting and layouting of ui->innerWidget, so the geometry values written in ui form (in Qt Creater) will no longer take effect, this is the reason of innerWidget out of place. ui->innerWidget is no longer a child of outerWidget, it's geometry will follow its new parent (but not scrollArea, there's some tricky layouting inside QScrollArea". To be clear, innerWidget is not helpful to locate scrollArea in such scenario.
In your first clip of code, widget 'scrollArea' is created with parent outerWidget, again no size policy or layout or geometry is specified, so scrollArea will by default be placed at the left top corner of the parent "outerWidget". To place scrollArea to your target geometry, you can " set geometry manually " or " assign innerWidget as scrollArea's parent and expand scrollArea". Obviously the latter method cannot assign ui->innerWiget to scrollArea->setWidget().
scrollArea->setWidgetResizable(true); makes the scrollArea "shrink" at left top corner of outerWidget. This is because, QScrollArea does not increase along with it's contents, it can scroll to display all of it contents so the required size of QScrollArea can be as small as possible. Once the 'Resizable' property is set to "true", QScrollArea decides to shrink to its minimum necessary size, thus the size to display its scroll bar and scroll buttons....

Resize window to fit content

I have a QGLWidget, which I want to resize to a given resolution (bigger than the containing window).
My intention is, that the window expands until the widget fits inside, but can't find a way to do it.
I tried several commands after resizing the QGLWidget to make it work without success.
I will list the results here:
do nothing else: The Widget overlaps the whole window. Eventually it will be resized to fit back into the smaller window
mainWindow.adjustSize(): The widget gets resized to (0, 0)
mainWindow.resize(mainWindow.sizeHint()): see above
mainWindow.resize(mainWindow.minimumSizeHint()): see above
I also read in this thread, that before doing the mainWindow resize I the event loop needs to be run to recalculate the new sizes, so I inserted QCoreApplication::processEvents to do so, without any visible effect.
So how do I resize the window via the widget?
Edit
The GLWidget is not the only widget of the window.
It is embedded in splitter together with a group box.
http://qt-project.org/doc/qt-4.8/qwidget.html#sizePolicy-prop
http://qt-project.org/doc/qt-4.8/qsizepolicy.html#Policy-enum
http://qt-project.org/doc/qt-4.8/qwidget.html#setFixedSize
So assuming that you have your QGLWidget nested inside your QMainWindow as the central widget, you need to set the size policy of your QGLWidget.
For example:
QGLWidget * glw; // in your header for QMainWindow
...
// In your constructor for QMainWindow
glw = new QGLWidget;
this->setCentralWidget(glw);
glw->setFixedSize(500, 500);
this->adjustSize();
Hope that helps.
I have an app that needed to be very similar to your requirements, so I'll post my solution here. An image covering the window which is freely expandable and shrinkable, and can be changed to the original size, and remain expandable / shrinkable after that.
I used a QLabel widget to display the image, but it should work with other widget types too. I created the widget with an initial size and the QSizePolicy::Ignored.
label->resize (w, h); // initial size
label->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Ignored);
The label widget was in a QVBoxLayout with a few buttons in the window, but this may work with other layout types too.
The window and image widget can be resized to the image's original size with this code:
label->resize (w, h); // change to original size
label->setMinimumSize (w, h); // prevent it from collapsing to zero immediately
window->adjustSize (); // resize the window
label->setMinimumSize (0, 0); // allow shrinking afterwards

How do i resize the contents of a QScrollArea as more widgets are placed inside

I have a QScrollArea Widget, which starts empty;
It has a vertical layout, with a QGridLayout, and a vertical spacer to keep it at the top, and prevent it from stretching over the whole scroll area;
Elsewhere in the program, there is a QTextEdit, which when changed, has its contents scanned for "species" elements, and then they are added to the QGridLayout. Any species elements which have been removed are removed too. This bit works;
I have turned the vertical scrollbar on all the time, so that when it appears it does not sit on top of the other stuff in there. Note that the scroll bar is larger than the scroll box already though, despite not needing to be.
This is the problem. The scroll area seems to be preset, and i cannot change it. If i add more rows to the QGridLayout, the scroll area doesn't increase in size.
Instead, it stays the same size, and squeezes the QGridLayout, making it look ugly (at first);
And then after adding even more it becomes unusable;
Note that again, the scroll bar is still the same size as in previous images. The first two images are from Qt Designer, the subsequent 3 are from the program running.
If I resize the window so that the QScrollArea grows, then I see this:
Indicating that there's some layout inside the scroll area that is not resizing properly.
My question is; what do I need to do to make the scrollable area of the widget resize dynamically as I add and remove from the QGridLayout?
If you're coming here from Google and not having luck with the accepted answer, that's because you're missing the other secret invocation: QScrollArea::setWidget. You must create and explicitly identify a single widget which is to be scrolled. It's not enough to just add the item as a child! Adding multiple items directly to the ScrollArea will also not work.
This script demonstrates a simple working example of QScrollArea:
from PySide.QtGui import *
app = QApplication([])
scroll = QScrollArea()
scroll.setWidgetResizable(True) # CRITICAL
inner = QFrame(scroll)
inner.setLayout(QVBoxLayout())
scroll.setWidget(inner) # CRITICAL
for i in range(40):
b = QPushButton(inner)
b.setText(str(i))
inner.layout().addWidget(b)
scroll.show()
app.exec_()
The documentation provide an answer :
widgetResizable : bool
This property holds whether the scroll area should resize the view widget.
If this property is set to false (the default), the scroll area honors the size of its widget.
Set it to true.
Why don't you use a QListView for your rows, it will manage all the issues for you? Just make sure that after you add it you click on the Class (top right window of designer) and assign a layout or it wont expand properly.
I use a QLIstWidget inside a QScrollArea to make a scrollable image list
Try this for adding other objects to the list, this is how I add an image to the list.
QImage& qim = myclass.getQTImage();
QImage iconImage = copyImageToSquareRegion(qim, ui->display_image->palette().color(QWidget::backgroundRole()));
QListWidgetItem* pItem = new QListWidgetItem(QIcon(QPixmap::fromImage(iconImage)), NULL);
pItem->setData(Qt::UserRole, "thumb" + QString::number(ui->ImageThumbList->count())); // probably not necessary for you
QString strTooltip = "a tooltip"
pItem->setToolTip(strTooltip);
ui->ImageThumbList->addItem(pItem);
Update on Artfunkel's answer:
Here's a PySide6 demo that uses a "Populate" button to run the for loop adding items to the scroll area. Each button will also delete itself when clicked.
from PySide6.QtWidgets import *
app = QApplication([])
scroll = QScrollArea()
scroll.setWidgetResizable(True) # CRITICAL
inner = QFrame(scroll)
inner.setLayout(QVBoxLayout())
scroll.setWidget(inner) # CRITICAL
def on_remove_widget(button):
button.deleteLater()
def populate():
for i in range(40):
b = QPushButton(inner)
b.setText(str(i))
b.clicked.connect(b.deleteLater)
inner.layout().addWidget(b)
b = QPushButton(inner)
b.setText("Populate")
b.clicked.connect(populate)
inner.layout().addWidget(b)
scroll.show()
app.exec()

Resizing a QDialog after adding components to a child widget

I'm a bit new to QT but have to work on existing code. Here's the case:
I have a class extending QDialog. the constructor sets a QGridLayout then adding three other widgets to it. One of the widgets is a QScrollArea containing a QGroupBox. this QGroupBox has a QVBoxLayout and there I'm adding a list of widgets at runtime. The size of the scroll area should grow until a given limit is reached before showing the scrollbars so that they are only used when the dialog would grow too high. I've found that the sizeHint of the outer layout doesn't update when the sizeHint of the scroll area updates. How can I refresh this, or is there a better way to resize the parent dialog?
What about using widgetResizable property of QScrollArea? It should try to resize view to avoid using scorllbars.

Resources