QListWidget 항목 일관된 위치 문제

Aug 17 2020

Qt 프레임 워크를 처음 사용합니다. 새 응용 프로그램에서 사용자 지정 항목으로 목록을 만들고 싶습니다. 이러한 항목은 매우 간단하며 제목 라벨, 미리보기 이미지 및 설명 라벨을 포함해야합니다 ( 여기에 그림 ).

지금은 적절한 위젯 / 레이아웃으로 원하는 항목을 수행하는 것이 더 쉽기 때문에 사용자 정의 드로잉 및 모든 항목을 사용하고 싶지 않으므로 QListwidget 및 하위 클래스 화 된 QAbstractItemModel (KeyframeModel) 및 QListWidgetItem (TileWidgetItem)을 사용하기로 결정했습니다.

코딩 후 원하는대로 보이지만 일부 항목을 추가하면 QListWidget (그리드 모드)에 이상한 일이 발생합니다. 제 경우에는 QListWidget의 크기를 조정할 수 있으며 (메인 레이아웃에 포함 된 방식으로 인해) 열 수는 목록 및 항목 너비에 따라 달라집니다. 항목은 고정 된 크기입니다 (적어도 지금은). 그러나 목록의 크기를 조정할 때 일부 목록의 너비에있는 항목 중 하나가 잘못 정렬되어 무슨 일이 일어나고 있는지 모르겠습니다. 다음은 앱의 스크린 샷입니다.

그림. 1 초기 상태 나열 (시작 직후)

그림. 2 크기 조정 후 목록 # 1

그림. 3 크기 조정 후 목록 # 2

# 2 크기 조정은 # 1 크기 조정보다 몇 픽셀 더 넓고 # 1 크기 조정은 얻기 어렵습니다 (테두리 케이스)-너비가 몇 픽셀 줄어들고 열이 2 개 있습니다 (괜찮습니다). # 2. 모든 경우에 열 수는 괜찮습니다.

때로는 프로그램 시작 후 마지막 항목이 여기 와 같이 오른쪽으로 정렬되지 않는 경우도 있습니다 (그림 1과 같이 시작 직후이지만 동일한 목록 너비에도 불구하고 다른 결과를 볼 수 있으므로). 시동 후 왜 그렇게 일관성이 없는지 궁금합니다.

내가 뭔가 빠졌나요? 일부 부분을 다른 방식으로해야합니까? 아니면 디버그 모드의 일부 결함입니까?

아래에 몇 가지 코드를 게시합니다.

신청:

// 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);
}

항목 위젯 :

// 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;
};

플랫폼 : Windows 10
Qt 버전 : 5.14.2
IDE : Visual Studio 2019 (Qt VS Tools 포함)

답변

KamilSzepietowski Sep 01 2020 at 18:23

결국 나는 문제를 해결 한 커스텀 델리게이트를 사용했습니다.

나는 시스템을 남용하고 싶었고 패배했습니다 :)