简体   繁体   中英

Trying to send image from QThread to main or other thread in PyQt

I am trying to display an image from another thread in the main thread or possibly even a new thread. The problem is I cannot get the image to show anywhere else. I am using the thread _thread to download the image so it won't freeze the gui but I can't seem to get it out of there properly using QImage or QPixmap.
I know how to use strings and such in signals as shown in the example below but I am not sure how to send the image in a signal properly. I have tried using requests to grab an image url and send it to the main which works but I wasn't able to fetch the string in the main and then just download it there real fast either. That also is not a good option due to freezing the GUI momentarily.

This code is an example that shows that I can do all of the work and download the image in the main if I want to but would rather not.

import urllib2
from PyQt4 import QtGui
from PyQt4.QtCore import QThread, pyqtSignal
from PyQt4.QtGui import QApplication, QPixmap
import sys

class MainWindow(QtGui.QWidget):
    def __init__(self):
        super(self.__class__, self).__init__()
        layout = QtGui.QVBoxLayout(self)
        self._Button = QtGui.QPushButton()
        self._Button.setObjectName("_Button")
        self.line_edit = QtGui.QLineEdit()
        self.line_edit.setObjectName("line_edit")
        self.txt_box = QtGui.QTextEdit()
        self.txt_box.setObjectName("txt_Box")
        self.img_label = QtGui.QLabel()
        self.img_label.setObjectName("img_label")
        layout.addWidget(self._Button)
        layout.addWidget(self.line_edit)
        layout.addWidget(self.img_label)
        layout.addWidget(self.txt_box)

        self.pixmap = QPixmap()
        self._thread = test_thread()
        self._Button.clicked.connect(self.start_thread)
        self.get_Text = self._thread.test_Signal.connect(self.line_edit.setText)

        self.urls = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png'
        data = urllib2.urlopen(self.urls).read()
        self.pixmap.loadFromData(data)
        self.img_label.setPixmap(self.pixmap)

    def start_thread(self):
        self._thread.start()
        self._thread.test_Signal.connect(self.txt_box.setText)


class test_thread(QThread):
    test_Signal = pyqtSignal(str)
    def __init__(self):
        super(test_thread, self).__init__()

    def run(self):
        string = 'This is a test string.'
        self.test_Signal.emit(string)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())

And this code shows more of what I am looking to do.

import urllib2
from PyQt4 import QtGui
from PyQt4.QtCore import QThread, pyqtSignal
from PyQt4.QtGui import QApplication, QPixmap
import sys

class MainWindow(QtGui.QWidget):
    def __init__(self):
        super(self.__class__, self).__init__()
        layout = QtGui.QVBoxLayout(self)
        self._Button = QtGui.QPushButton()
        self._Button.setObjectName("_Button")
        self.line_edit = QtGui.QLineEdit()
        self.line_edit.setObjectName("line_edit")
        self.txt_box = QtGui.QTextEdit()
        self.txt_box.setObjectName("txt_Box")
        self.img_label = QtGui.QLabel()
        self.img_label.setObjectName("img_label")
        layout.addWidget(self._Button)
        layout.addWidget(self.line_edit)
        layout.addWidget(self.img_label)
        layout.addWidget(self.txt_box)

        self.pixmap = QPixmap()
        self._thread = test_thread()
        self._Button.clicked.connect(self.start_thread)
        self.get_Text = self._thread.test_Signal.connect(self.line_edit.setText)

    "...Send signal here and show image. EX:"
    "...self._thread.image_Signal.connect(self.img_label.setPixmap)...."
    "...or...."
    def show_image_here(self):
        "....Send image here after downloaded in thread...."

    def start_thread(self):
        self._thread.start()
        self._thread.test_Signal.connect(self.txt_box.setText)

class test_thread(QThread):
    test_Signal = pyqtSignal(str)

    "....Example image signal...."
    "....image_Signal = pyqtSignal()...."

    def __init__(self):
        super(test_thread, self).__init__()
        self.pixmap = QPixmap()

    def run(self):
        string = 'This is a test string.'
        self.test_Signal.emit(string)

        self.urls = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png'
        data = urllib2.urlopen(self.urls).read()
        self.pixmap.loadFromData(data)
        "....Not sure what to do here...."

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())

Can somebody help me out? Thanks.

After looking around some more I came across this thread PySide threading and http downloading

I wish I had found it sooner because I did a lot of searching before my post. The person who answered that thread reclosedev also posted this in the comments:
https://pastebin.com/b4MD5jKh
Which helped me immensely to understand some things better. I used his code and slightly altered it to fit mine and it will work great for what I would like to do.
Here is my full working code using my original example for anyone out there that may find it useful.

import urllib2
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import QThread, pyqtSignal
from PyQt4.QtGui import QApplication
import sys

class MainWindow(QtGui.QWidget):
    def __init__(self):
        super(self.__class__, self).__init__()
        layout = QtGui.QVBoxLayout(self)
        self._Button = QtGui.QPushButton()
        self._Button.setObjectName("_Button")
        self.line_edit = QtGui.QLineEdit()
        self.line_edit.setObjectName("line_edit")
        self.txt_box = QtGui.QTextEdit()
        self.txt_box.setObjectName("txt_Box")
        self.img_label = QtGui.QLabel()
        self.img_label.setObjectName("img_label")
        self.imagepreview = ImagePreview()
        layout.addWidget(self._Button)
        layout.addWidget(self.line_edit)
        layout.addWidget(self.img_label)
        layout.addWidget(self.txt_box)
        layout.addWidget(self.imagepreview)

        self._thread = test_thread()
        self._Button.clicked.connect(self.start_thread)
        self._Button.clicked.connect(self.imagepreview.startDownload)
        self.get_Text = self._thread.test_Signal.connect(self.line_edit.setText)

    def start_thread(self):
        self._thread.start()
        self._thread.test_Signal.connect(self.txt_box.setText)


class test_thread(QThread):
    test_Signal = pyqtSignal(str)

    def __init__(self):
        super(test_thread, self).__init__()

    def run(self):
        string = 'This is a test string.'
        self.test_Signal.emit(string)


class DownloadThread(QtCore.QThread):
    data_downloaded = pyqtSignal()

    def __init__(self, url):
        QtCore.QThread.__init__(self)
        self.url = url
        self._data = None

    def run(self):
        self._data = urllib2.urlopen(self.url).read()
        self.data_downloaded.emit()

    def get_data(self):
        return self._data


class ImagePreview(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ImagePreview, self).__init__(parent)
        self.setMinimumSize(50, 50)
        self.pixmap = None

    def paintEvent(self, paintEvent):
        painter = QtGui.QPainter(self)
        if (self.pixmap):
            painter.drawPixmap(0, 0, self.pixmap)

    def startDownload(self):
        self.download_thread = DownloadThread('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png')
        self.download_thread.start()
        self.download_thread.data_downloaded.connect(self.ondownloadFinished)

    def ondownloadFinished(self):
        self.paintImage()
        print("download finished")

    def paintImage(self):
        print("Painting")
        pixmap = QtGui.QPixmap()
        pixmap.loadFromData(self.download_thread.get_data())
        self.setPixmap(pixmap)

    def setPixmap(self, pixmap):
        self.pixmap = pixmap
        self.setMinimumSize(pixmap.width(), pixmap.height())
        self.update()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM