添加列表小部件项async Pysid

2024-09-28 22:19:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用gphoto2拍照,我想把它们异步地放到一个列表小部件上,因为某些原因,它没有按预期工作。它在一个QThread上获取照片,但是在所有照片都被拍摄完成之前,它不会将照片添加到列表中(就像批量添加)。我该怎么做?在

以下是相关的源代码(它不会编译,因为有太多的依赖项无法满足问题):

class DownloadThread(QThread):

    data_downloaded = Signal(object)

    def __init__(self, photo_name):
        QThread.__init__(self)
        self.photo_name = photo_name

    def run(self):
        image_location = capture_image.take_photo(self.photo_name)
        image = QImage(image_location)
        to_pixmap = QPixmap.fromImage(image).scaled(200, 200)
        to_qicon = QIcon(to_pixmap)

        self.data_downloaded.emit(QListWidgetItem(to_qicon, image_location))


class MainWindow(QMainWindow, Ui_MainWindow):

    def take_photo(self):
        import time
        for x in range(2):
            photo_name = str(x) +'.jpg'   
            downloader = DownloadThread(photo_name)
            downloader.data_downloaded.connect(self.on_photo_ready)
            downloader.start()
            time.sleep(5)

    def on_photo_ready(self, photo):
        print "WHY"
        self.listWidget.addItem(photo)

我在被调用的函数中有一些简单的print语句,因此终端如下所示:

照片 照片 照片 照片 照片 照片 为什么? 为什么? 为什么? 为什么? 为什么? 为什么

这意味着它等待实际调用emit,直到for循环完成,而不是按预期在它自己的线程上。任何帮助都会很棒!在


Tags: tonameimageself列表datadefdownloader
2条回答

告诉主线程在次线程工作时休眠。这将把你所有的信号排成一列,这样它们就能立刻到达。删除time.sleep(5)并更改

 downloader = ...

^{pr2}$

你应该没事的。在

也就是说,工人模型是件好事。有关详细信息,请参见this questionthis one。在

有几个问题

1。你的线程实际上没有运行

您需要调用QThread.start()来实际运行QThread.run()。也就是说,你可能不想这样设计你的应用程序。没有理由为每个图片下载创建几十个或数百个不同的线程。如果创建一个工作线程来下载队列中的所有映像,效率会高得多。示例见下文。在

2。不能在辅助线程

中创建qpixmap或GUI项

不能在主线程之外创建QPixmap。您既不能创建QListWidgetItem,也不能创建任何GUI元素;它们只能在主线程中创建(并安全地操作)。您可以使用其他类似的元素(比如QImage),但实际上,您只需要将下载的文件路径传递回主线程;主线程可以处理QPixmap和项创建。在

class DownloadWorker(QObject):

    data_downloaded = Signal(object)

    @QtCore.Slot(str)
    def download_image(self, name):
        image_location = capture_image.take_photo(name)
        self.data_downloaded.emit(image_location)


class MainWindow(QMainWindow, Ui_MainWindow):

    request_download = QtCore.Signal(str)

    def __init__(self, ...)
        ...
        self.worker = DownloadWorker()
        self.thread = QThread(self)
        self.request_download.connect(self.worker.download_image)
        self.worker.data_downloaded.connect(self.on_photo_ready)
        self.worker.moveToThread(self.thread)
        self.thread.start()

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.take_photo)
        self.timer.start(5000)

    def take_photo(self):
        import time
        photo_name = str(time.time()) +'.jpg'  
        self.request_download.emit(photo_name) 

    @QtCore.Slot(str)
    def on_photo_ready(self, filepath):
        item = QListWidgetItem(QIcon(filepath))
        self.listWidget.addItem(item)

相关问题 更多 >