带有自定义窗口小部件的QListWidget在Mac OS中无法正确滚动

时间:2013-03-11 04:34:19

标签: macos qt scroll qlistwidget

在我的应用程序中,我有一个带有自定义窗口小部件项的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中。我想我必须跳进去并尝试从那里解决问题,并希望创建一个补丁,除非有人想出一个启示。

3 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:2)

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

connect(_listWidget->verticalScrollBar(),
        SIGNAL(valueChanged(int)),_listWidget,
        SLOT(updateEditorGeometries()));
connect(_listWidget->horizontalScrollBar(),
        SIGNAL(valueChanged(int)),_listWidget,
        SLOT(updateEditorGeometries()));

答案 2 :(得分:1)

我应用了Qt Commercial Support提供给我的这个补丁。这解决了我在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();