作为问题的延续,我得到了解决 here几天前,我有一个 PyQt4 GUI,它嵌入了两个 PyQtGraph 的 PlotWidget,每个都从由按钮触发的线程随机附加数组设置/更新数据。它工作得很好,而且 GUI 响应灵敏。但到了某个点,图形不再显示其各自 PlotWidget 内的更新,我必须最小化/最大化才能看到 PlotWidget 内绘制的更新。代码如下:
import random
import sys
import pyqtgraph as pg
import time
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
def __init__(self, curve, parent=None):
super(MyThread, self).__init__(parent=parent)
self.curve = curve
self.data = [0]
app.processEvents()#increases the time the drawings are shown
def run(self):
app.processEvents() #increases the time the drawings are shown
while True:
self.data.append(self.data[-1] + 0.2 * (0.5 - random.random()))
self.curve.setData(self.data, downsample=10) #crashes without
time.sleep(0.1)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.button.clicked.connect(self.plotter)
app.processEvents()
def plotter(self):
self.curve = self.plot.getPlotItem().plot()
myThread = MyThread(self.curve, self)
myThread.start()
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
global app
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
任何关于我可以做什么而不必最大化/最小化以获得 GUI 中的更新的线索或解决方法都会让我非常高兴。
按照下面答案中 @ImportanceOfBeingErnest 的建议,我尝试遵循 Python Wiki使用信号和槽连接 GUI 和线程,如下所示:
import random
import sys
import pyqtgraph as pg
import time
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
def __init__(self, parent=None):
super(MyThread, self).__init__(parent=parent)
self.data = [0]
def run(self):
while True:
self.data.append(self.data[-1] + 0.2 * (0.5 - random.random()))
self.emit(SIGNAL("output(data)"), self.data)
time.sleep(0.1)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
self.myThread = MyThread()
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.button.clicked.connect(self.plotter)
self.connect(self.myThread, SIGNAL("output(data)"), self.plotter)
def plotter(self, data):
self.curve = self.plot.getPlotItem().plot()
self.curve.setData(data, downsample=10)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
但这给了我错误:
"in self.connect(self.myThread, SIGNAL("output(data)"), self.plotter)
NameError: name 'SIGNAL' is not defined"
通过阅读question from 4 years ago ,我用 QtCore.SIGNAL 替换 SIGNAL 得到以下错误:
"in self.connect(self.myThread, QtCore.SIGNAL("output(data)"), self.plotter)
TypeError: C++ type 'data' is not supported as a slot argument type"
然后忽略 TypeError:
try:
self.connect(self.myThread, QtCore.SIGNAL("output(data)"), self.plotter)
except TypeError:
pass
GUI 启动,但当我最终单击按钮并连接到 self.plotter
函数时,出现以下错误:
"in plotter
self.curve.setData(data, downsample=10)
File "C:\Users\iyv\AppData\Local\Programs\Python\Python34_64\lib\site-
packages\pyqtgraph\graphicsItems\PlotDataItem.py", line 381, in setData
raise Exception('Invalid data type %s' % type(data))
Exception: Invalid data type <class 'bool'>"
我很困惑。我应该联系 PyQtGraph 吗?任何帮助都非常感激。
最佳答案
您需要将 GUI 和线程分开。他们不能共享任何 GUI 对象,例如本例中的绘图小部件!
我不确定您是否需要线程,因为您的数据不是很大并且每秒仅更新 10 次。但如果您决定使用它,则仅使用 signals and slots在线程和 GUI 之间进行通信。
下面是程序的修改版本,它使用线程并且工作正常。它使用新样式 signals and slots 。希望这更容易理解,因为您可以仅使用
object
作为数据类型。
在你的程序中没有意义的两件事是:
- 您在绘图槽中重新定义了 self.curve。
- 按下按钮时调用绘图槽。相反,按下按钮应该启动线程。
我已更正它们。
import random
import sys
import pyqtgraph as pg
import time
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
signal = QtCore.pyqtSignal(object)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent=parent)
self.data = [0]
def __del__(self):
self.exiting = True
self.wait()
def run(self):
while True:
self.data.append(random.random())
self.signal.emit(self.data)
time.sleep(0.1)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
self.myThread = MyThread()
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.curve = self.plot.getPlotItem().plot()
self.button.clicked.connect(self.start)
def plotter(self, data):
self.curve.setData(data)
def start(self):
self.myThread.start()
self.myThread.signal.connect(self.plotter)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
关于python - PyQt4 中的 QThreading PyQtGraph PlotWidgets,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41808667/