【问题标题】:Adjust the height of QListView to fit the content调整 QListView 的高度以适应内容
【发布时间】:2020-07-06 00:03:05
【问题描述】:

我希望基于QAbstractListModelQListView 的高度适合内容,如果项目的数量小于给定的数字 N。如果有超过 N 个项目,它应该只显示 N 个项目.我在网上阅读了很多奇怪的提示,但其中大多数看起来像黑客。我想这与sizeHint() 有关,但在模型视图方法中没有可以覆盖sizeHint() 的ItemWidget。实现这种行为的正确方法是什么?

此外,这与父应用的大小政策有何关联?这是第二个约束:内容不应尝试使用它们在父窗口小部件中的空间,但父窗口小部件应调整大小以适应 QListView

这不是this question 的重复,因为我不能使用QCompleter

【问题讨论】:

  • 不要使用QListView,使用小部件和垂直布局。
  • 我试过这个,但实施起来很乱。而且由于UpdatesEnabled() 效果不佳(我在某处读到布局中的更改,例如 addwidget() 被延迟),结合最小尺寸策略,这导致我闪烁,因为我根据用户进行此更新输入。

标签: c++ qt qlistview qsizepolicy


【解决方案1】:

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()。

【讨论】:

  • 还有minimumSizeHint
【解决方案2】:

对于那些在 QML 中使用 ListView 和 QtQuick 控件的人。 我使内容符合属性 anchors.bottomMargin。

anchors.bottomMargin: 20

【讨论】:

    【解决方案3】:

    没有很好的方法来做到这一点。我使用以下代码。

    标题:

    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 设置高度。这应该为父窗口小部件的大小提示提供正确的行为。

    【讨论】:

    • 感谢您的回答。我同时找到了解决方案。也许它对你有用。