Отрегулируйте высоту QListView, чтобы соответствовать содержанию

Я хочу высоту QListView основанный на QAbstractListModel чтобы соответствовать содержанию, если количество предметов меньше заданного числа N. Если есть больше чем N предметов, он должен показывать только N предметов. Я прочитал много любопытных советов в Интернете, но большинство из них выглядят как хаки. Я думаю, это как-то связано с sizeHint() но в подходе представления модели нет ItemWidget, в котором я мог бы переопределить sizeHint(), Как правильно добиться этого поведения?

Кроме того, как это соотносится с политикой размера родительского приложения? Это второе ограничение: содержимое не должно пытаться использовать пространство, которое они имеют в родительском виджете, но родительский виджет должен изменить размер, чтобы соответствовать QListView,

Это не дубликат [этого], так как я не могу использовать QCompleter, 1Высота QListView в соответствии с содержимым

0

Решение

sizeHint () должен быть переопределен в QListView (соответственно вашему подклассу). Упомянутое специальное поведение может быть реализовано там. например, вот так:

QSize ProposalListView::sizeHint() const
{
if (model()->rowCount() == 0) return QSize(width(), 0);
int nToShow = _nItemsToShow < model()->rowCount() ? _nItemsToShow : model()->rowCount();
return QSize(width(), nToShow*sizeHintForRow(0));
}

Это требует разумного указания размера делегата элемента. В моем случае:

inline QSize sizeHint ( const QStyleOptionViewItem&, const QModelIndex& ) const  override { return QSize(200, 48); }

Теперь мне просто нужно вызвать updateGeometry () после изменения модели.

1

Другие решения

Нет хорошего способа сделать это. Я использую следующий код.

Заголовок:

class List_view_auto_height : public QObject {
Q_OBJECT
public:
explicit List_view_auto_height(QListView * target_list);
void set_max_auto_height(int value);
void set_min_height(int value);

private:
QListView* list;
QTimer timer;
int _min_height;
int _max_height;

bool eventFilter(QObject* object, QEvent* event);

private slots:
void update_height();
};

Источник:

List_view_auto_height::List_view_auto_height(QListView *target_list) :
QObject(target_list)
, list(target_list)
{
_min_height = 0;
_max_height = 250;
connect(list->model(), &QAbstractItemModel::rowsInserted,
this, &List_view_auto_height::update_height);
connect(list->model(), &QAbstractItemModel::rowsRemoved,
this, &List_view_auto_height::update_height);
connect(list->model(), &QAbstractItemModel::layoutChanged,
this, &List_view_auto_height::update_height);
list->installEventFilter(this);
update_height();
connect(&timer, &QTimer::timeout, this, &List_view_auto_height::update_height);
timer.start(500);
}

void List_view_auto_height::set_max_auto_height(int value) {
_max_height = value;
update_height();

}

void List_view_auto_height::set_min_height(int value) {
_min_height = value;
update_height();
}

bool List_view_auto_height::eventFilter(QObject *object, QEvent *event) {
if (event->type() == QEvent::Show) {
update_height();
}
return false;
}

void List_view_auto_height::update_height() {
if (!list->isVisible()) { return; }
int height = 0;
if (list->model()->rowCount() > 0) {
height = list->visualRect(list->model()->index(list->model()->rowCount() - 1, 0)).bottom() + 1;
height -= list->visualRect(list->model()->index(0, 0)).top();
}
if (list->horizontalScrollBar()->isVisible()) {
height += list->horizontalScrollBar()->height();
}
bool scrollbar_enabled = false;
if (_max_height != 0 && height > _max_height) {
height = _max_height;
scrollbar_enabled = true;
}
if (height < _min_height) {
height = _min_height;
}
list->setFixedHeight(height + 6);
}

Использование:

new List_widget_auto_height(list);

Он полон хаков и может работать некорректно в некоторых случаях. Не стесняйтесь улучшать это.

Он устанавливает высоту, используя setFixedHeight, Это должно обеспечить правильное поведение для подсказки размера родительского виджета.

0

Для тех, кто использует ListView в QML с элементами управления QtQuick.
Я сделал содержание подходящим с помощью свойства anchors.bottomMargin.

anchors.bottomMargin: 20
0
По вопросам рекламы [email protected]