Проблема согласованного позиционирования элементов QListWidget
Я новичок в Qt framework. В новом приложении я хочу создать список с настраиваемыми элементами. Эти элементы довольно просты и должны содержать метку заголовка, миниатюру и метку описания ( изображение здесь ).
На данный момент я не хочу играть с пользовательским рисунком и всем этим, потому что я считаю, что проще делать элементы, которые я хочу, с правильным виджетом / макетом, поэтому я решил использовать 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)
Ответы
В конце концов, я просто использовал настраиваемые делегаты, которые решали проблемы.
Я хотел переборщить с системой и проиграл :)