1

这不是我第一次想要一个行为如下的滚动区域(想象一个日志或聊天窗口,但太复杂而无法使用简单的 QTextBrowser):

  • 我想添加多个小部件,它们出现在另一个下方(例如放置在 QVBoxLayout 中时)
  • 此布局中的每个小部件都应具有固定大小或宽度换高(如简单标签)
  • 滚动区域应自动滚动到最近添加的区域
  • (可选)当有剩余空间时(滚动条尚未启用),内容应底部对齐

使用 QScrollArea:

我过去的尝试是在内部使用 QScrollArea 和 QVBoxLayout。但这似乎并没有我想的那么简单:每当我在布局中添加一个小部件时,布局并不会立即调整滚动区域内容小部件的大小,从而导致内容调整延迟。在短时间内,布局中包含的小部件会调整大小,以使总大小等于添加操作之前的总大小,从而导致每个小部件的大小过小。此外,在布局将其大小更正为小部件的新总大小之前,滚动到新添加的小部件是不可能的,因此即使是 QTimer::singleShot(0, ...) 也无济于事。即使超时时间为 20 左右,在某些情况下布局需要更多时间来调整大小。它不是确定性的,因此远离一个好的解决方案。

为了获得底部对齐行为,我最初在布局中放置了一个间隔项。只要没有剩余空间并启用滚动,它就不需要任何空间。

使用 QListView:

由于我的项目太复杂,它们需要是 QWidgets。他们无法获得焦点,无法选择,因此基于项目的解决方案似乎只是“错误的方式”。此外,这个解决方案听起来太“沉重”了。

我简直不敢相信没有简单的方法,所以我想我还没有看到它!

4

1 回答 1

1

QListView应该没事。您声称您的项目是静态的,与它们没有交互:没有焦点,没有选择。QWidget对于此类物品,似乎 a是一种矫枉过正。您只需要具有固定大小并且可以自行绘制的东西。这正是 Qt 模型视图系统中的委托的用途。只需QAbstractItemDelegate为您的项目实现一个或多个 s,并为它们将呈现的数据提供模型的实现。这QAbstractItemView已经是一个QAbstractScrollArea

如果你想在委托中绘制 HTML,这很容易——同样,QWidget 对静态显示来说太过分了!使用 QWidget 来“很难”是有原因的——API 会引导您找到正确的解决方案。假设您的模型包含每个项目的 html,以下是绘制它的方法。当然,您可以使用 sizeHint,并且应该缓存文本文档,理想情况下将其存储在我认为的模型中。

void MyDelegate::paint(QPainter* p, const QStyleOptionViewItem & opt, const QModelIndex & index) const
{
   QTextDocument doc;
   doc.setHtml(index.data().toString());
   doc.drawContents(p, QRect(QPoint(0,0), sizeHint(opt, index)));
}

QSize MyDelegate::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const
{
   return QSize(100, 200);
}
于 2012-05-08T22:32:12.140 回答