0

在我的应用程序中,我有一个带有自定义小部件项目的 QListWidget,其中包含一个进度条,由 QListWidget::setWidget() 设置。我被迫使用 QListWidget 而不是 QListView 和委托,因为视图/委托解决方案不会像通常那样为项目小部件中的进度条设置动画。

我的问题是滚动 QListWidget 时,自定义小部件没有跟随。它们似乎只是简单地“粘”在背景上。只有在手动调整周围小部件的大小时,QListWidget 才会正确重新排列子小部件。

这是我向 QListWidget 添加小部件的方法:

QListWidgetItem* widgetItem = new QListWidgetItem("");
DownloadItemForm* dlItemForm = new DownloadItemForm(el);
widgetItem->setSizeHint(dlItemForm->size());
ui->listWidget->addItem(widgetItem);
ui->listWidget->setItemWidget(widgetItem, dlItemForm);
widgetItems.insert(el, widgetItem);

我在这里错过了什么吗?似乎其他人也有问题(最后一条评论是我的):

https://bugreports.qt-project.org/browse/QTBUG-27043

有谁知道解决方法,还是我只是在这里遗漏了什么?

编辑:

只是为了进一步澄清:我使用的是 Qt 4.8.4。虽然我希望这个问题会在 5.x 中得到解决,但它在 5.0.1 中仍然存在 在 Mac OS 上,进度条是动画的:即使没有进度更新,进度条中也有一个缓慢流动的动画。使用基于视图的小部件和项目委托时,此动画不会运行。在 Mac 上运行 Torrent Qt 示例将支持此声明。进度条动画在使用 QListWidget 时起作用,注入包含带有进度条的表单小部件的小部件项目。

查看 Qt 4.8.4 源代码,QListWidget::setItemWidget() 看起来像这样:

void QListWidget::setItemWidget(QListWidgetItem *item, QWidget *widget)
{
    Q_D(QListWidget);
    QModelIndex index = d->listModel()->index(item);
    QAbstractItemView::setIndexWidget(index, widget);
}

这告诉我问题可能出在 QAbstractItemView 中。我想我将不得不跳入其中并尝试从那里解决问题,并希望创建一个补丁,除非有人提出启示。

4

3 回答 3

3

我找到了一种解决方法,只需将 listWidget 的滚动条的 valueChanged(int) 信号连接到 listWidget 的 updateEditorGeometries() 插槽即可:

connect(_listWidget->verticalScrollBar(),
        SIGNAL(valueChanged(int)),_listWidget,
        SLOT(updateEditorGeometries()));
connect(_listWidget->horizontalScrollBar(),
        SIGNAL(valueChanged(int)),_listWidget,
        SLOT(updateEditorGeometries()));
于 2014-03-31T07:32:35.647 回答
2

截至 2013-08-05 git://gitorious.org/qt/qt.git 修订版 78b4162a352ddac398b8af7f8be33b009c333244 已修复。从该修订版或更高版本构建可解决该问题。

这是该版本的提交消息:

Fix QListWidget item widget scroll bug

This fix applies the patch uploaded in the bug report. The patch was
provided by Qt-Commercial support but seems to have never found it's
way to the sources although the bug was fixed in Qt 5.

如果您使用自制软件,您可以简单地:

brew install qt --build-from-source --HEAD

我已经测试并确认这可以解决问题。

于 2013-11-16T02:57:00.637 回答
1

我应用了 Qt 商业支持提供给我的这个补丁。这解决了我在 Qt 4.8.5 上的 Mac 滚动问题:

--- /Users/irfanomair/dev/qt-src-carbon-4.8.0/src/gui/kernel/qwidget_mac.mm 2011-12-15 10:38:21.000000000 -0800
+++ kernel/qwidget_mac.mm   2012-09-18 17:17:03.000000000 -0700
@@ -1,22 +1,41 @@

@@ -4684,15 +4703,14 @@
     }

     // Scroll the whole widget if qscrollRect is not valid:
-    QRect validScrollRect = qscrollRect.isValid() ? qscrollRect : q->rect();
-    validScrollRect &= clipRect();
+    QRect validScrollRect = qscrollRect.isValid() ? qscrollRect : QRect(0, 0, q->width(), q->height());

     // If q is overlapped by other widgets, we cannot just blit pixels since
     // this will move overlapping widgets as well. In case we just update:
     const bool overlapped = isOverlapped(validScrollRect.translated(data.crect.topLeft()));
     const bool accelerateScroll = accelEnv && isOpaque && !overlapped;
     const bool isAlien = (q->internalWinId() == 0);
-    const QPoint scrollDelta(dx, dy);
+

     // If qscrollRect is valid, we are _not_ supposed to scroll q's children (as documented).
     // But we do scroll children (and the whole of q) if qscrollRect is invalid. This case is
@@ -4714,7 +4732,6 @@
         }else {
             update_sys(qscrollRect);
         }
-        return;
     }

 #ifdef QT_MAC_USE_COCOA
@@ -4731,6 +4748,7 @@
     // moved when the parent is scrolled. All directly or indirectly moved
     // children will receive a move event before the function call returns.
     QWidgetList movedChildren;
+    const QPoint scrollDelta(dx, dy);
     if (scrollChildren) {
         QObjectList children = q->children();
于 2013-03-15T15:08:13.547 回答