【问题标题】:Qt, widget refresh, and ui interactabilityQt、小部件刷新和 ui 交互性
【发布时间】:2011-09-08 15:47:54
【问题描述】:

我对 Qt 很陌生,并且发现学习它非常有益。我正在尝试将一些现有的 C++ 代码与新的 Qt GUI 合并。基本上,这个想法是让从 .avi 文件中提取的图像在后端进行处理,然后显示在屏幕上的 QLabel 中。我设法获得以下代码以正确显示帧:

while (frame = cvQueryFrame(capture))
{
    // Some processing code...

    QImage qImageFrame((uchar*) frame->imageData, frame->width, frame->height, frame->widthStep, QImage::Format_RGB888);
    qImageFrame = qImageFrame.rgbSwapped();
    QPixmap qFrame;

    qFrame.convertFromImage(qImageFrame);
    label->setPixmap(qFrame);
    label->repaint();

    cvWaitKey(10);
}

但是,现在,这显然意味着 UI 停止响应用户输入,直到显示电影中的所有帧。这种事情是怎么做到的?

注意:我正在使用 openCV 库执行处理,该库需要特定格式的图像。例如,我认为我不能做的一件事是直接在 Qt 域中使用 .avi 文件。

【问题讨论】:

    标签: c++ qt user-interface opencv


    【解决方案1】:

    我不同意 Tamás 的建议,即他的答案是“最简单”的解决方案。

    解决您的问题的最快、最少侵入性的解决方案是将qApp->processEvents(); 添加到您的循环中。我会把它放在label->repaint(); 之后,看看会发生什么。

    【讨论】:

    • 这依赖于假设处理本身对于所有可能的输入来说是可以忽略不计的时间。这可能是真的,也可能不是。如果是这样的话,那么是的,这个解决方案确实比我的简单。
    • 我已经尝试了你的建议。是的,用户界面再次变得响应,但是如果我退出应用程序,窗口会被破坏,而进程继续在后台工作......我想我会用线程尝试这个。
    【解决方案2】:

    你真的应该看看 Qt Phonon multimedia framework。可能无法让您获得使用 OpenCV 对媒体文件的控制级别,但值得好好研究一下。

    对于您最初的问题:您必须在不同的线程中进行处理。这变得很棘手,因为您只能从 UI 线程调用 GUI 函数,而且您(我想)不想过多地复制图像数据。

    如需了解详细信息(以及指向 Qt 文档的指针),请查看 Qt signaling across threads, one is GUI thread?。请注意,如果您想直接传递QImages,这将需要额外的工作。

    【讨论】:

    • 谢谢 Mat,听起来很有希望。
    【解决方案3】:

    有时最简单的解决方案是最好的。通过子类化 QRunnable 创建一个工作线程,用于解码您的帧并将信号发送回 GUI 以更新帧。当 Qt 信号跨线程发出时,它们会被正确排队和分派。特别是在单个工作线程的情况下,您不会因为并发问题而头疼。复制QImage 不是问题,因为它利用了implicit sharing。要编写自己的隐式共享数据类,请使用QSharedDataPointer(据我所知,Qt 内部也使用它)。

    【讨论】:

      【解决方案4】:

      使用线程并不是唯一的(或者实际上,必然是首选的)方法。

      您的 UI 正在阻塞,因为您正在使用阻塞睡眠 (cvWaitKey)。如果您改用 QTimer 并将其超时信号连接到绘制下一帧的插槽,那么您的 UI 应该保持响应。

      【讨论】:

      • 你确定 cvWaitKey 被阻塞了吗?我不熟悉openCV,但快速搜索表明并非如此。见stackoverflow.com/questions/5217519/opencv-cvwaitkey。另外,即使你移除了阻塞等待,处理本身仍然需要一些时间,所以我认为这里使用工作线程是合理的。
      • “你确定 cvWaitKey 阻塞了吗?我不熟悉openCV,但快速搜索表明并非如此。请参阅 stackoverflow.com/questions/5217519/opencv-cvwaitkey” — Tamás,您似乎弄错了。您发布的链接中的第一个答案是“cvWaitKey() 休眠 X 毫秒,等待按下任何键”。您关于处理需要时间的观点是正确的,但如果之前使用单线程版本,时间似乎可以忽略不计。
      猜你喜欢
      • 2015-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多