信号未从线程传递到 GUI
Posted
技术标签:
【中文标题】信号未从线程传递到 GUI【英文标题】:Signals not passing from thread to GUI 【发布时间】:2017-09-29 07:08:13 【问题描述】:此遥测程序从 USB 端口上的串行字符串中读取数据。 GUI 在 QML 文件中定义,读取串行端口由字符串处理。 GUI 加载并正常工作。 GUI 发送上的按钮有一个事件处理程序,它可以将信号发送回 GUI。这完美无缺。串行读取线程启动并正确运行。它读取并解析数据并将其打印到屏幕上。然而,信号并没有返回到 GUI。
这让我发疯了,谢谢你的帮助。
main.py
import sys
import serial
from io import StringIO
import csv
from openpyxl import Workbook
import datetime
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, QThread
global ser
#define and open the serial port
ser=serial.Serial('COM6')
class Dash(QObject):
def __init__(self):
QObject.__init__(self)
ampHourvalue = pyqtSignal(int, arguments=['amphour'])
@pyqtSlot(int)
def reset(self, value):
value=100 #put amp hour capacity here
self.ampHourvalue.emit(value)
class ThreadClass(QThread):
# Create the signal
auxVoltage = pyqtSignal(str, arguments=['auxvolt'])
mainVoltage = pyqtSignal(int, arguments=['mainvolt'])
arrayCurrent = pyqtSignal(int, arguments=['arraycurrent'])
motorCurrent = pyqtSignal(int, arguments=['motorcurrent'])
def __init__(self, parent=None):
super(ThreadClass, self).__init__(parent)
def run(self):
try:
wb=load_workbook("History.xls") #attemps to open the history excel file
except:
wb=Workbook() #creates and empty excel workbook if histortory is not found
WorkSheetName=datetime.date.today() #get todays date
ws = wb.create_sheet("%s" %WorkSheetName) #create worksheet with the date as tittle
while True:
data=ser.readline(120) #read the stream
print(data)
data=data.decode() #convert stream from bytes to characters
data=StringIO(data)#convert a stream of characters into string
dataset=csv.reader(data, delimiter= ',') #read the CSV string into individual array
dataset=list(dataset) #convert the array to list
ws.append(dataset[0])
wb.save("History.xls")
#extract individual data points
aux=dataset[0][1]
print("Aux ", aux)
mainvolt=dataset[0][2]
print("Main ", mainvolt)
arraycurrent=dataset[0][3]
motorcurrent=dataset[0][4]
# Emit the signals
self.auxVoltage.emit(aux)
self.mainVoltage.emit(mainvolt)
self.arrayCurrent.emit(arraycurrent)
self.motorCurrent.emit(motorcurrent)
pass
def main():
import sys
# Create an instance of the application
app = QGuiApplication(sys.argv)
#start the thread
threadclass=ThreadClass()
threadclass.start()
# Create QML engine
engine = QQmlApplicationEngine()
# Create a Dash object
dashboard = Dash()
# And register it in the context of QML
engine.rootContext().setContextProperty("dashboard", dashboard)
# Load the qml file into the engine
engine.load("take2.qml")
engine.quit.connect(app.quit)
sys.exit(app.exec_())
if __name__ == "__main__":
main()
take2.qml
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
import QtQuick.Extras 1.4
ApplicationWindow
id: applicationWindow
visible: true
width: 1000
height: 500
color: "black"
title: "I like Telemetry"
Text
id: text1
x: 300
y: 6
width: 353
height: 34
text: qsTr("Solar Car Telemetry System")
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignHCenter
font.family: "Times New Roman"
font.pixelSize: 30
color: "grey"
CircularGauge
id: circularGauge
x: 55
y: 111
width: 308
height: 279
anchors.verticalCenter: rowLayout.verticalCenter
Text
id: text2
x: 143
y: 226
text: qsTr("Speed")
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 12
color: "grey"
CircularGauge
id: auxvoltgauge
x: 381
y: 92
width: 151
height: 141
stepSize: .5
maximumValue: 15
value:1
Text
id: text3
x: 445
width: 69
text: qsTr("Aux Battery")
anchors.top: parent.top
anchors.topMargin: -17
horizontalAlignment: Text.AlignHCenter
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 12
color: "grey"
Text
id: text5
x: 64
y: 106
text: qsTr("Volts")
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
font.pixelSize: 12
color: "grey"
CircularGauge
id: circularGauge2
x: 381
y: 288
width: 151
height: 141
visible: true
Text
id: text4
x: 445
y: 259
text: qsTr("Main Battery")
anchors.top: parent.top
anchors.topMargin: -17
fontSizeMode: Text.FixedSize
horizontalAlignment: Text.AlignHCenter
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 12
color: "grey"
Text
id: text6
x: 64
y: 106
text: qsTr("Volts")
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
font.pixelSize: 12
color: "grey"
Gauge
id: amphourgauge
x: 803
y: 103
width: 114
height: 294
anchors.verticalCenterOffset: 0
anchors.verticalCenter: parent.verticalCenter
value: 50
Text
id: text7
x: 30
y: 260
text: qsTr("AMP HOURS")
anchors.bottom: parent.bottom
anchors.bottomMargin: -25
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 18
color: "grey"
Button
id: amphourreset
objectName: amphourreset
x: 795
y: 434
text: qsTr("Reset")
onClicked: dashboard.reset(amphourgauge.value)
Gauge
id: arraycurrent
x: 621
y: 160
Text
id: text10
text: qsTr("Array Current")
font.pixelSize: 12
color: "grey"
anchors.top: parent.top
anchors.topMargin: -17
fontSizeMode: Text.FixedSize
horizontalAlignment: Text.AlignHCenter
anchors.horizontalCenter: parent.horizontalCenter
Gauge
id: motorcurrent
x: 710
y: 160
Text
id: text9
text: qsTr("Motor Current")
font.pixelSize: 12
color: "grey"
anchors.top: parent.top
anchors.topMargin: -17
fontSizeMode: Text.FixedSize
horizontalAlignment: Text.AlignHCenter
anchors.horizontalCenter: parent.horizontalCenter
Connections
target: dashboard
onAmpHourvalue:
// sub was set through arguments=['amphour']
amphourgauge.value = amphour
onAuxVoltage:
// sub was set through arguments=['auxvolt']
auxvoltgauge.value = auxvolt
【问题讨论】:
您认为将其标记为“Java”会有所帮助吗? 嗯,我看到了 python、多线程 qml 和 PyQT5。 @JarrettDunn 我尝试运行你的代码但失败了。但是尝试这样的事情,threadclass.auxVoltage.connect(lambda aux: print(aux))
在main()
中。告诉我它是否有效。
@JarrettDunn 我删除了标签 :)
@daegontaven 创建线程后,我将其添加到 main() 代码中。它有效,但正在打印一个随机数。如果您注释掉 ser=serial.Serial('COM6') 当然没有输入,代码应该运行,这不是您不知道是否有任何变化。 b'7:44:11, 0.0000, 0, 225, 213, 2124.8047N, 15746.0610W, 0.0\r\n' Aux 0.0000 Main 0 174163984 b'7:44:12, 0.0000, 0, 178, 1672, 2124.804 N, 15746.0610W, 0.0\r\n' 辅助 0.0000 主 0 174178688 b'7:44:13, 0.0000, 0, 202, 187, 2124.8047N, 15746.0610W, 0.0\r\n' 辅助 0.06536 主 0
【参考方案1】:
@daegontaven 是正确的。问题是线程没有连接到包含 GUI 的线程。连接两个线程解决了这个问题。我重新排序了一些代码。
class ThreadClass(QThread):
# Create the signal
ampHourvalue = pyqtSignal(float, arguments=['amphour'])
auxVoltage = pyqtSignal(float, arguments=['auxvolt'])
mainVoltage = pyqtSignal(float, arguments=['mainvolt'])
arrayCurrent = pyqtSignal(float, arguments=['arraycurrent'])
motorCurrent = pyqtSignal(float, arguments=['motorcur'])
def __init__(self, parent=None):
super(ThreadClass, self).__init__(parent)
#connects the signals from the thread to the signals in the thread that is running the GUI
self.auxVoltage.connect(dashboard.auxVoltage)
self.mainVoltage.connect(dashboard.mainVoltage)
self.motorCurrent.connect(dashboard.motorCurrent)
self.arrayCurrent.connect(dashboard.arrayCurrent)
self.ampHourvalue.connect(dashboard.ampHourvalue)
【讨论】:
以上是关于信号未从线程传递到 GUI的主要内容,如果未能解决你的问题,请参考以下文章
如何从 non_GUI 类和我们可以在主 GUI 类中检测到的非 GUI 线程发出信号