我正在尝试创建一个简单的UI来控制我是否可以从串口打印数据并使用PyQT,我创建了一个带有两个按钮的简单UI - 一个开始录制按钮和一个停止录制按钮。
按下“开始录制”按钮时,数据将被打印出来,但是当我按下“停止录制”按钮时,系统将挂起并且while循环继续运行。我想这可能是因为程序试图摆脱while循环,但是无法做到。我非常感谢你的帮助。
主要代码:
import gui_main
import sys
import numpy
from PyQt4 import QtCore, QtGui
import PyQt4.Qwt5 as Qwt
import matplotlib
import serial
import threading
global readervar
def reader():
readervar= True
ser = serial.Serial(7) #insert COM port number from which data is being collected
ser.baudrate = 9600 #insert baud rate
while True:
if readervar:
line= ser.readline()
print (line)
print(readervar)
else if uiplot.btn2.clicked():
break
readervar=False
def shutter():
readervar=False
def main():
global uiplot
app = QtGui.QApplication(sys.argv)
win_plot = gui_main.QtGui.QMainWindow()
uiplot = gui_main.Ui_Form()
uiplot.setupUi(win_plot)
uiplot.btn1.clicked.connect(reader)
uiplot.btn2.clicked.connect(shutter)
# DISPLAY WINDOWS
win_plot.show()
code = app.exec_()
sys.exit(code)
if __name__ == "__main__":
main()
GUI代码:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '.\Form.ui'
#
# Created: Fri Mar 20 15:17:05 2015
# by: PyQt4 UI code generator 4.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(282, 192)
self.centralWidget = QtGui.QWidget(Form)
self.centralWidget.setObjectName(_fromUtf8("centralWidget"))
self.btn1 = QtGui.QPushButton(self.centralWidget)
self.btn1.setGeometry(QtCore.QRect(20, 50, 91, 23))
self.btn1.setObjectName(_fromUtf8("btn1"))
self.btn2 = QtGui.QPushButton(self.centralWidget)
self.btn2.setGeometry(QtCore.QRect(160, 50, 91, 23))
self.btn2.setObjectName(_fromUtf8("btn2"))
self.btn3 = QtGui.QPushButton(self.centralWidget)
self.btn3.setGeometry(QtCore.QRect(110, 90, 75, 23))
self.btn3.setObjectName(_fromUtf8("btn3"))
self.label = QtGui.QLabel(self.centralWidget)
self.label.setGeometry(QtCore.QRect(110, 20, 47, 13))
self.label.setObjectName(_fromUtf8("label"))
Form.setCentralWidget(self.centralWidget)
self.menuBar = QtGui.QMenuBar(Form)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 282, 21))
self.menuBar.setObjectName(_fromUtf8("menuBar"))
Form.setMenuBar(self.menuBar)
self.mainToolBar = QtGui.QToolBar(Form)
self.mainToolBar.setObjectName(_fromUtf8("mainToolBar"))
Form.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
self.statusBar = QtGui.QStatusBar(Form)
self.statusBar.setObjectName(_fromUtf8("statusBar"))
Form.setStatusBar(self.statusBar)
self.retranslateUi(Form)
QtCore.QObject.connect(self.btn1, QtCore.SIGNAL(_fromUtf8("clicked()")), self.label.update)
QtCore.QObject.connect(self.btn2, QtCore.SIGNAL(_fromUtf8("clicked()")), self.label.update)
QtCore.QObject.connect(self.btn3, QtCore.SIGNAL(_fromUtf8("clicked()")), Form.close)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(_translate("Form", "Form", None))
self.btn1.setText(_translate("Form", "Start Recording", None))
self.btn2.setText(_translate("Form", "Stop Recording", None))
self.btn3.setText(_translate("Form", "Exit", None))
self.label.setText(_translate("Form", "TextLabel", None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
Form = QtGui.QMainWindow()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
答案 0 :(得分:1)
我认为你可能会误解你的程序执行情况。
PyQt(和所有GUI)应用程序都运行了一个事件循环。在PyQt的情况下,您使用app.exec_()
开始此循环。直到GUI应用程序停止之前,该行下面的任何代码都不会运行。这是因为Python(故意)陷入exec_()
方法中的循环中。
所以,您可能会问,如果程序卡在事件循环中,您的代码如何运行?事件循环(顾名思义)可以监听按钮点击,鼠标/键盘交互等事件。当您将鼠标移到按钮上时,事件循环甚至负责创建悬停效果。
当您单击第一个按钮时,事件循环将运行您的函数reader()
。但是这个函数有一个无限循环。因此,应用程序的控制永远不会返回到PyQt事件循环。这意味着您无法点击其他按钮。如果将鼠标移动到应用程序中的任何按钮上,即使悬停效果也不会显示。 GUI应用程序依赖于控制被快速返回到事件循环以保持响应。
所以你永远不能点击第二个按钮来停止reader()
中的循环,因为循环阻止所有其他代码运行。
解决方案是将reader()
循环放在另一个线程中。但是,设置线程超出了本答案的范围。但是有很多资源在互联网上使用python线程和(Py)Qt QThreads
(包括在stackoverflow上)。请注意,与GUI应用程序一起使用时,线程会带来一些风险。例如,您必须确保永远不会直接从辅助线程与GUI交互。
如果您遇到使用线程的问题,我会鼓励您发布另一个问题,显示您已经有多远,并说明您遇到的问题。我很乐意提供帮助!