3
votes

I have the following code but it's complaining that I cannot access the UI data from my thread. In my example code below, What is the best way I can access the userInputString value so my threading can run?

self.nameField is a PyQt QLineEdit.

QObject::setParent: Cannot set parent, new parent is in a different thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QWidget::repaint: Recursive repaint detected

import myUI

class MainUIClass(QtGui.QMainWindow, myUI.Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainUIClass, self).__init__(parent)
        self.setupUi(self)

        self.startbutton.clicked.connect(self.do_work)

        self.workerThread = WorkerThread()
        self.connect(self.workerThread, SIGNAL("myThreading()"), self.myThreading, Qt.DirectConnection)

    def do_work(self):
        self.userInputString = self.nameField.Text()
        self.workerThread.start()

    def myThreading(self):

        if userInputString is not None:
            #Do something

class WorkerThread(QThread):
    def __init__(self, parent=None):
        super(WorkerThread, self).__init__(parent)

    def run(self):
        self.emit(SIGNAL("myThreading()"))

if __name__ == '__main__':
    a = QtGui.QApplication(sys.argv)
    app = MainUIClass()
    app.show()
    a.exec_()
1
You should read " How to use QThread the right way" stackoverflow.com/questions/16879971/… blog.debao.me/2013/08/… You're also using old style signal ... For you problem, you should use Signals and slot...you run your process in a thread then from this thread send a signals to the GUI thread which can access the GUI elements - PyNico
Thanks for pointing that out. All i'm trying to do is to be able to access the "userInputString" value from within my thread class but don't know how to pass that value from the MainUI class to the thread class. Do you think a shared multithreading Array or Value data type would be another way to do it? - joke4me
@joke4me. The code in your question does not produce those error messages. In fact, with minor corrections, it works exactly as expected. Please read the guidance on how to provide a minimal reproducible example. - ekhumoro

1 Answers

5
votes

Not sure if it's what you need but here is a working QThread exemple using Qt5

import time
import sys
from PyQt5 import QtWidgets, QtGui, QtCore

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.worker_thread = WorkerThread()
        self.worker_thread.job_done.connect(self.on_job_done)
        self.create_ui()

    def create_ui(self):
        self.button = QtWidgets.QPushButton('Test', self)
        self.button.clicked.connect(self.start_thread)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.button)

    def start_thread(self):
        self.worker_thread.gui_text = self.button.text()
        self.worker_thread.start()

    def on_job_done(self, generated_str):
        print("Generated string : ", generated_str)
        self.button.setText(generated_str)


class WorkerThread(QtCore.QThread):

    job_done = QtCore.pyqtSignal('QString')

    def __init__(self, parent=None):
        super(WorkerThread, self).__init__(parent)
        self.gui_text = None

    def do_work(self):

        for i in range(0, 1000):
            print(self.gui_text)
            self.job_done.emit(self.gui_text + str(i))
            time.sleep(0.5)

    def run(self):
        self.do_work()


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