Python Forum
Newbie trying to pass text from different thread
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Newbie trying to pass text from different thread
#1
Hi,
I am new to Python and try to write my first program. The main goal of the program is to read data from an OPC UA server and then execute a shell command. I have it working for the most part but I think I have an issue with threading. This is the main code

# ----------------------------------------------------------------------------------------
# import libraries
import subprocess 
import sys
import threading
from datetime import datetime
from window import Ui_MainWindow
import PyQt5
from PyQt5 import QtCore, QtGui, uic, QtWidgets
from opc_client import SubHandler

if hasattr(QtCore.Qt, 'AA_EnableHighDpiScaling'):
    PyQt5.QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)

if hasattr(QtCore.Qt, 'AA_UseHighDpiPixmaps'):
    PyQt5.QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)

# ----------------------------------------------------------------------------------------
# callback for opc ua value change
def opc_value_changed(val, file_path):
    ui.txtStatus.appendPlainText(str(datetime.now().strftime("%d/%m/%Y %H:%M:%S")) + " new command -> " + file_path)
    ui.txtStatus.update()
    try:
        process = subprocess.Popen(file_path, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        retcode = process.returncode
        ui.txtStatus.appendPlainText(str(datetime.now().strftime("%d/%m/%Y %H:%M:%S")) + " command result -> " + str(retcode))
        client.respond(0)
    except Exception as e:
        ui.txtStatus.appendPlainText(str(datetime.now().strftime("%d/%m/%Y %H:%M:%S")) + " command error -> " + str(e))
        client.respond(1)
 
# ----------------------------------------------------------------------------------------
# start ui and opc tasks
if __name__ == '__main__':
    # start ui
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()

    # start opc ua
    client = SubHandler("opc.tcp://" + ui.txtPLC_IP.text() + ":" + ui.txtPLC_Port.text())
    client.data_changed += opc_value_changed
    client.connect()

    sys.exit(app.exec_())
The UI and OPC code is in a different file. The client function at the end has a callback function opc_value_changed that is triggered when an OPC value changes. I then call the shell command and would like to post the result in the GUI. The shell part is working but textbox only updates when I click on the app. I get the following debug warning

Error:
>> QObject::connect: Cannot queue arguments of type 'QTextBlock' (Make sure 'QTextBlock' is registered using qRegisterMetaType().)
I am pretty sure this has something to do with threading and I tried to run the client function in its on thread but beeing new to Python I have not been able to make this work. Can anybody look at the code and give me some pointers? I am pretty sure there are some genrell errors.

Thx

Stephan
Reply
#2
Not sure to understand what you are doing exactly, but here is a threading example in PyQt5.

#!/usr/bin/python3
import time
from PyQt5 import QtWidgets, QtCore


class WorkerThread(QtCore.QObject):
    signalExample = QtCore.pyqtSignal(str, int)

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

    @QtCore.pyqtSlot()
    def run(self):
        while True:  # Long running task ...
            self.signalExample.emit("leet", 1337)
            time.sleep(5)


class Main(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.worker = WorkerThread()
        self.workerThread = QtCore.QThread()  # Move the Worker object to the Thread object
        self.workerThread.started.connect(self.worker.run)  # Init worker run() at startup
        self.worker.moveToThread(self.workerThread)
        self.worker.signalExample.connect(self.signalExample)  # Connect your signals/slots
        self.workerThread.start()

    def signalExample(self, text, number):
        print(text)
        print(number)


if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    gui = Main()
    app.exec()
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020