Search code examples
c++qtqt5qwidgetqlistwidget

How to scale a custom widget within a QListWidget?


I have created a custom widget that includes a vertical layout with a qlabel(that holds an icon) and a qcombobox and I use them as listwidget items. They are created based on a file that have 100s of icons. I am trying to create a slider that scales the pixmap sizes when the app is running in real time. I can't figure out how to code this properly so I can access this property. This is the code in the mainwindow.cpp

/*load icons*/
QDir dir (....);
QFileInfoList list = dir.entryInfoList(QDir::AllEntries | 
QDir::Dirs|QDir::NoDotAndDotDot);

for(int i=0 ; i < list.length() ; i++)
{
QIcon icon;
icon.addFile(list.at(i).absoluteFilePath(), QSize(), QIcon::Normal, 
            QIcon::Off);
mypix = icon.pixmap(QSize(128,128));

/*Custom Widget*/
widget.push_back(new QWidget(ui->listWidget));
widget[i]->setMinimumSize(QSize(0, 150));

/*the VB with of label-combo*/
layout.push_back(new QVBoxLayout(widget[i]));

/*Qlabel that holds the icon*/
pic.push_back(new QLabel (widget[i]));
pic[i]->setPixmap(mypix);
layout[i]->addWidget(pic[i]);
box.push_back(new QComboBox(widget[i]));
box[i]->addItem(list.at(i).baseName());
layout[i]->addWidget(box[i]);

QListWidgetItem * qlistwidgetitem = new QListWidgetItem;
ui->listWidget->addItem(qlistwidgetitem);
ui->listWidget->setItemWidget(ui->listWidget->item(i),widget[i]);
  }
}

Solution

  • QListWidgetItem has a default size that does not take into account the size of the widget, the solution is to pass the sizeHint() of the widget to QListWidgetItem, also you must not set a height of 0 to the widget, only the minimum width.

    QDir dir (...);
    const QFileInfoList &infolist = dir.entryInfoList(QDir::AllEntries| QDir::Dirs| QDir::NoDotAndDotDot);
    for(const QFileInfo &info: infolist){
        QIcon icon;
        icon.addFile(info.absoluteFilePath(), QSize(), QIcon::Normal, QIcon::Off);
        QPixmap pix = icon.pixmap(QSize(128,128));
        QWidget *w = new QWidget(ui->listWidget);
        w->setMinimumWidth(150);
        QVBoxLayout *lay = new QVBoxLayout(w);
        QLabel *lbl = new QLabel(w);
        lbl->setPixmap(pix);
        QComboBox *combo = new QComboBox(w);
        combo->addItem(info.baseName());
    
        lay->addWidget(lbl);
        lay->addWidget(combo);
    
        widget << w;
        layout << lay;
        box << combo;
        pic << lbl;
    
        QListWidgetItem *qlistwidgetitem = new QListWidgetItem;
        qlistwidgetitem->setSizeHint(w->sizeHint());
        ui->listWidget->addItem(qlistwidgetitem);
        ui->listWidget->setItemWidget(qlistwidgetitem, w);
    }
    

    enter image description here


    Update:

    If you want to change the size of the icon with a QSlider it is advisable to save the icon so we can use the setData() method, then we associate a slot with the slider and in that slot we insert a new size to the icon and set it to the QLabel

    for(const QFileInfo &info: infolist){
        [...]
        qlistwidgetitem->setData(Qt::UserRole, QVariant::fromValue(icon));
        [...]
    }
    
    void Widget::on_horizontalSlider_valueChanged(int value)
    {
        for(int i=0; i< ui->listWidget->count(); i++){
            QListWidgetItem *it = ui->listWidget->item(i);
            QIcon icon = it->data(Qt::UserRole).value<QIcon>();
            pic[i]->setPixmap(icon.pixmap(value, value));
            QWidget *w = ui->listWidget->itemWidget(it);
            it->setSizeHint(w->sizeHint());
        }
    }
    

    enter image description here

    enter image description here

    The complete example can be found in the following link.