我创建了一个GUI,我必须传递来自串行COM端口的字符串数据。一个单独的线程正在处理串行数据,而Qt对象需要获取该数据并通过> setPlainText'来显示它。方法。它给出了一个错误(在评论中标记的第i行)是
" QObject:无法为不同线程中的父级创建子级。 (Parent是QTextDocument(0x3ebaa68),父线程是QThread(0x3dd5c58),当前线程是QThread(0x3fbd6a8)"
继承我的代码;
import sys
from PyQt4 import QtGui
from My_GUI_code import Ui_Dialog
import serial # import Serial Library
import threading
import time
test=""
arduinoData = serial.Serial('COM2', 9600) #
index=0
incoming_data=""
device_0_V=""
class Serial_read(threading.Thread):
"""
Thread to read data coming from Arduino
"""
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global incoming_data
global device_0_V
global test
while 1:
while (arduinoData.inWaiting()==0): #Wait here until there is data
pass #do nothing
incoming_data = arduinoData.readline() #read the line of text from the serial port
if "V0" in incoming_data:
index = incoming_data.index("V0=")
device_0_V=incoming_data[index+3:index+6]
print device_0_V
#print incoming_data,
class Editor(QtGui.QMainWindow, threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
global device_0_V
super(Editor, self).__init__()
self.ui=Ui_Dialog()
#test=self.ui.Dev_1_V
self.ui.setupUi(self)
self.setWindowIcon(QtGui.QIcon('ICON.png'))
self.ui.Dev_1_V.setPlainText("anum")
self.show()
self.ui.Dev_1_ON.clicked.connect(self.handleButton)
def run(self):
global device_0_V
while 1:
self.ui.Dev_1_V.setPlainText(device_0_V) #<<here it gives ERROR
time.sleep(1)
def handleButton(self):
time = self.ui.time_dev_1.value()
self.ui.Dev_1_V.setPlainText(device_0_V)
print time
#print ('Hello World')
def main():
tx_socket_thread2 = Serial_read()
tx_socket_thread2.start()
app = QtGui.QApplication(sys.argv)
ex = Editor()
ex.start()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
我已经在Stackoverflow中看到了一些相关问题,但我仍然无法理解这个概念,因为我是Classes,Qt和OOP的新手。我知道我在这里做了一些基本的错误......任何帮助都将受到高度赞赏。
答案 0 :(得分:1)
所以在对Stack溢出中的相关问题进行了一些阅读后,我已经设法实现了我想要的,继承人的代码;
import sys
from PyQt4 import QtGui, QtCore
from My_GUI_code import Ui_Dialog
import serial # import Serial Library
import threading
import time
test=""
arduinoData = serial.Serial('COM2', 9600) #
index=0
incoming_data=""
device_0_V=""
class Serial_read(threading.Thread):
"""
Thread to read data coming from Arduino
"""
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global incoming_data
global device_0_V
global test
while 1:
while (arduinoData.inWaiting()==0): #Wait here until there is data
pass #do nothing
incoming_data = arduinoData.readline() #read the line of text from the serial port
if "V0" in incoming_data:
index = incoming_data.index("V0=")
device_0_V=incoming_data[index+3:index+6]
print device_0_V
#print incoming_data,
class Editor(QtGui.QMainWindow):
def __init__(self):
#threading.Thread.__init__(self)
global device_0_V
super(Editor, self).__init__()
self.ui=Ui_Dialog()
#test=self.ui.Dev_1_V
self.ui.setupUi(self)
self.setWindowIcon(QtGui.QIcon('ICON.png'))
self.ui.Dev_1_V.setPlainText("anum")
self.show()
self.ui.Dev_1_ON.clicked.connect(self.handleButton)
self.worker = Worker(self) # an independent thread that will listen to a signal 'beep' and trigger a function self.update
self.connect(self.worker, QtCore.SIGNAL('beep'), self.update)
self.worker.start() # start the thread
def update(self, Serial_data):
# here, I am getting the Serial data via signaling
if "V0" in incoming_data:
index = incoming_data.index("V0=")
device_0_V=incoming_data[index+3:index+7]
self.ui.Dev_1_V.setPlainText(device_0_V)
def handleButton(self):
time = self.ui.time_dev_1.value()
self.ui.Dev_1_V.setPlainText(device_0_V)
print time
#print ('Hello World')
class Worker(QtCore.QThread):
def __init__(self, host_window):
super(Worker, self).__init__()
self.running = False
def run(self):
self.running = True
global incoming_data #kept the Serial data global
global device_0_V
while self.running:
#sending 'beep' signal to the main Qt object, with string data 'incoming_data'
self.emit(QtCore.SIGNAL('beep'), incoming_data)
time.sleep(0.1)
def stop(self):
self.running = False
def main():
tx_socket_thread2 = Serial_read()
tx_socket_thread2.start()
app = QtGui.QApplication(sys.argv)
ex = Editor()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
在主Qt对象中,我创建了一个QThread“Worker”,它使用Serial数据向主Qt对象发送信号。每次从工作线程到达信号时都会触发更新功能,然后进一步读取来自工作线程的数据。
从this问题
获得帮助感谢@Andy和@SiHa的参与
答案 1 :(得分:0)
这是一个描述Qt对象是什么并且不是线程安全的页面 - http://doc.qt.io/qt-4.8/threads-reentrancy.html
在大多数情况下,GUI对象不是线程安全的,您应该避免从其他线程修改它们。
从其他线程影响GUI的一种方法是使用信号和插槽系统,只要传递的任何对象都是线程安全的,就可以在线程之间安全使用。这通常意味着在辅助线程中创建一个线程安全的数据结构,并将其与信号一起传递给主线程,然后主线程读取数据结构并更新GUI。
该设计模式的更高级版本是使用双向队列。主线程填充一个队列,该线程创建处理队列中项目的工作线程。完成后,工作线程使用主线程随后处理的线程安全返回值填充另一个队列。当队列中有待处理的项目时,信号和事件仍用于通知主线程和工作线程。
此外,除非绝对想要直接管理线程,否则您可以使用QRunnable和QThreadPool启动线程,而无需直接管理它们。