Problema de posicionamiento consistente de elementos QListWidget

Aug 17 2020

Soy nuevo en el marco Qt. En una nueva aplicación, quiero crear una lista con elementos personalizados. Estos elementos son bastante simples y deben contener una etiqueta de título, una miniatura y una etiqueta de descripción ( imagen aquí )

Por ahora no quiero jugar con dibujos personalizados y todo eso porque creo que es más fácil hacer los elementos que quiero con el widget/diseño adecuado, así que decidí usar QListwidget y subclasificar QAbstractItemModel (KeyframeModel) y QListWidgetItem (TileWidgetItem).

Después de un poco de codificación, se ve como quería, pero sucede algo extraño con QListWidget (modo de cuadrícula) cuando agrego algunos elementos. En mi caso, un QListWidget es redimensionable (debido a cómo está incrustado dentro del diseño principal) y la cantidad de columnas debe depender de la lista y el ancho de los elementos. Los artículos son de tamaño fijo (al menos por ahora). Pero cuando cambio el tamaño de la lista, uno de los elementos en el ancho de alguna lista está desalineado y no sé qué está pasando. A continuación se muestran las capturas de pantalla de la aplicación:

Foto. 1 Estado inicial de la lista (justo después del inicio)

Foto. 2 Lista después de cambiar el tamaño #1

Foto. 3 Lista después de cambiar el tamaño #2

El cambio de tamaño n.º 2 es unos píxeles más ancho que el cambio de tamaño n.º 1 y el cambio de tamaño n.º 1 es difícil de conseguir (marco del borde): unos píxeles menos de ancho y tengo 2 columnas (está bien), pero algunos píxeles más y termino con el caso #2. En todos los casos, el número de columnas está bien.

A veces, también el último elemento está desalineado después de que el programa se inicie de inmediato como aquí (justo después del inicio como en la imagen 1, pero como puede ver un resultado diferente a pesar del mismo ancho de lista). Me pregunto por qué es tan inconsistente después de la puesta en marcha.

¿Me estoy perdiendo algo? ¿Debo hacer algunas partes de manera diferente? ¿O son solo algunas fallas en el modo de depuración?

A continuación publico un código:

Solicitud:

// Source file 

QtGuiApplication1::QtGuiApplication1(QWidget *parent) 
    : QMainWindow(parent)
{
    ui.setupUi(this);

    //--------------------------------------------------------------------------------
    // Add elements to the list

    TileWidgetItem *item = new TileWidgetItem();
    item->setData(TileWidgetItem::TileRole::TitleRole, QVariant("Long title"));
    item->setData(TileWidgetItem::TileRole::DescriptionRole, QVariant("My long info"));
    item->setText("My super text");
    qDebug() << "Widget size hint: " << item->sizeHint();

    ui.listWidget_moves->addItem(item);
    item->updateView();

    TileWidgetItem *item1 = new TileWidgetItem();
    item1->setData(TileWidgetItem::TileRole::TitleRole, QVariant("Item #2"));
    item1->setText("Tile #2");
    ui.listWidget_moves->addItem(item1);
    item1->updateView();

    TileWidgetItem *item2 = new TileWidgetItem();
    ui.listWidget_moves->addItem(item2);
    item2->updateView();

    TileWidgetItem *item3 = new TileWidgetItem();
    ui.listWidget_moves->addItem(item3);
    item3->updateView();

    //--------------------------------------------------------------------------------
    // Adjust cell size

    QSize cellSize;

    for (uint i = 0; i < ui.listWidget_moves->count(); i++)
    {
        int dim = ui.listWidget_moves->item(i)->sizeHint().height();

        if (dim > cellSize.height())
            cellSize.setHeight(dim);

        dim = ui.listWidget_moves->item(i)->sizeHint().width();

        if (dim > cellSize.width())
            cellSize.setWidth(dim);
    }

    ui.listWidget_moves->setGridSize(cellSize);
}

Widget de artículo:

// Source file

constexpr int MAX_THUMB_SIZE = 100;

TileWidgetItem::TileWidgetItem(QListWidget *listview)
    : QListWidgetItem(listview, ItemType::UserType)
{
    /* Prepare main widget */

    QWidget *view = new QWidget();
    view->setObjectName("tile");
    view->setStyleSheet(
        "QWidget#tile { margin: 4 8; background-color: #404040; border: 1 solid rgba(0,0,0,30%); border-radius: 4px }\n"
        "QWidget#tile::hover { border: 1 solid #EEE; background-color: #484848 }\n"
        "QWidget#tile[selected=true] { background-color: #00F }"
    );
    
    //-----------------------------------------------------------
    /* Prepare layout */

    QVBoxLayout *layout = new QVBoxLayout();
    layout->setSizeConstraint(QLayout::SizeConstraint::SetFixedSize);

    //-----------------------------------------------------------
    /* Prepare title with icon */

    QHBoxLayout *titleLayout = new QHBoxLayout();

    QLabel *titleIcon = new QLabel();
    titleIcon->setObjectName("titleIcon");
    titleIcon->setStyleSheet("background-color: black");
    titleIcon->setFixedSize(QSize(16, 16));
    titleLayout->addWidget(titleIcon);

    QLabel *title = new QLabel("Title");
    title->setObjectName("title");
    title->setMinimumWidth(60);
    title->setStyleSheet("background-color: #800;");
    titleLayout->addWidget(title);
    
    QWidget *titleWidget = new QWidget();
    titleWidget->setStyleSheet("background-color: #080");
    titleWidget->setLayout(titleLayout);

    layout->addWidget(titleWidget);

    //-----------------------------------------------------------
    /* Prepare thumbnail */
    
    QLabel *thumbnail = new QLabel();
    thumbnail->setObjectName("thumbnail");
    thumbnail->setStyleSheet("background-color: black; border: 1 solid #F00");
    thumbnail->setFixedSize(QSize(MAX_THUMB_SIZE, MAX_THUMB_SIZE * 0.7f));
    thumbnail->setPixmap(QPixmap("Resources/moto.jpg").scaledToWidth(MAX_THUMB_SIZE));
    layout->addWidget(thumbnail);
    
    //-----------------------------------------------------------
    /* Preparing additional info */

    QLabel *description = new QLabel("Description");
    description->setObjectName("description");
    //description->setToolTip("Custom info tip");
    description->setContentsMargins(4, 2, 4, 2);
    layout->addWidget(description);

    //-----------------------------------------------------------

    view->setLayout(layout);

    _customView = view;
    _titleView = title;
    _descriptionView = description;

    setSizeHint(_customView->sizeHint());

    updateView();
}

TileWidgetItem::~TileWidgetItem()
{
}

void TileWidgetItem::setData(int role, const QVariant &value)
{
    QListWidgetItem::setData(role, value);

    if (value.type() == QVariant::Type::String)
    {
        if (role == TileRole::TitleRole)
        {
            this->_titleView->setText(value.toString());
        }
        else if (role == TileRole::DescriptionRole)
        {
            this->_descriptionView->setText(value.toString());
        }

        setSizeHint(_customView->sizeHint());
    }
}

void TileWidgetItem::updateView()
{
    if (listWidget() != nullptr)
    {
        listWidget()->setItemWidget(this, this->_customView);
    }
}
// Header file

class TileWidgetItem : public QListWidgetItem
{
public:
    enum TileRole
    {
        TitleRole = Qt::UserRole + 1,
        DescriptionRole,
        ThumbnailRole
    };

public:
    TileWidgetItem(QListWidget *listview = nullptr);
    ~TileWidgetItem();

    void setData(int role, const QVariant &value) override;
    void updateView();

    QWidget *customView() const { return _customView; };

    QString getTitle() const { return _titleView->text(); };

    QString getInfo() const { return _descriptionView->text(); };

private:
    QWidget *_customView;
    QLabel *_titleView;
    QLabel *_descriptionView;
};

Plataforma: Windows 10
Qt versión: 5.14.2
IDE: Visual Studio 2019 (con Qt VS Tools)

Respuestas

KamilSzepietowski Sep 01 2020 at 18:23

Al final, solo usé delegados personalizados que resolvieron problemas.

Quería abusar del sistema y fui derrotado :)