- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
首先,我是 Python 新手。我是 MatLab 的长期用户(工程师,而不是计算机科学家),我正在开始尝试将 Python、NumPy、SciPy 等应用到我的工作流程中。所以,请原谅我对什么是美妙的编程语言的明显无知!
作为我的第一个尝试,我决定构建一个应用程序来与我正在开发的传感器进行交互。传感器具有微秒分辨率(每 500 微秒来自 512 个高能量和 512 个低能量“像素”的数据),但 I/O 将被阻塞。因为我会不断地轮询设备,所以我知道线程对于保持 GUI 响应很重要(GUI 最终还将集成与另一个设备的串行通信,并具有一个对传感器数据进行操作的图像处理子例程)。我创建了一个 MatPlotLib 的线程实例来绘制来自传感器的这些“实时”数据。虽然我已经构建了独立与传感器通信的模块并验证了我知道如何在 Python 中执行此操作,但我在这里只是通过为低能量生成 8 到 12 之间的 512 个随机数来“模拟”数据“像素”,以及用于高能量“像素”的 90 到 110 之间的 512 个随机数。这就是线程。从这里的许多示例中,我还学会了使用 blitting 来通过 MatPlotLib 获得足够快的屏幕更新——但是,问题是除非我使用 time.sleep(0.02) 让线程进程休眠 20ms
,GUI 没有响应。这可以得到验证,因为来自 MatPlotLib 的交互式 X、Y 数据点反馈不起作用,并且不能使用“停止”按钮来中断该过程。任何比 time.sleep(0.02)
更长的时间都会使 GUI 操作更加流畅,但会以“数据速率”为代价。任何比 time.sleep(0.02)
慢的东西都会使 GUI 无响应。我不确定我明白为什么。我打算离开并尝试改用 GUIqwt,但我想在放弃 MatPlotLib 之前我会在这里问,因为我不确定这甚至是问题所在。我担心让线程休眠 20 毫秒将意味着我会错过至少 40 行来自传感器阵列的潜在数据(40 行 * 500us/行 = 20 毫秒)。
这是当前代码:
import time, random, sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
class ApplicationWindow(QMainWindow):
def __init__(self, parent = None):
QMainWindow.__init__(self, parent)
self.thread = Worker()
self.create_main_frame()
self.create_status_bar()
self.connect(self.thread, SIGNAL("finished()"), self.update_UI)
self.connect(self.thread, SIGNAL("terminated()"), self.update_UI)
self.connect(self.startButton, SIGNAL("clicked()"), self.start_acquisition)
self.connect(self.stopButton, SIGNAL("clicked()"), self.stop_acquisition)
self.thread.pixel_list.connect(self.update_figure)
def create_main_frame(self):
self.main_frame = QWidget()
self.dpi = 100
self.width = 10
self.height = 8
self.fig = Figure(figsize=(self.width, self.height), dpi=self.dpi)
self.axes = self.fig.add_subplot(111)
self.axes.axis((0,512,0,120))
self.canvas = FigureCanvas(self.fig)
self.canvas.setParent(self.main_frame)
self.canvas.updateGeometry()
self.canvas.draw()
self.background = None
self.lE_line, = self.axes.plot(range(512), [0 for i in xrange(512)], animated=True)
self.hE_line, = self.axes.plot(range(512), [0 for i in xrange(512)], animated=True)
self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)
self.startButton = QPushButton(self.tr("&Start"))
self.stopButton = QPushButton(self.tr("&Stop"))
layout = QGridLayout()
layout.addWidget(self.canvas, 0, 0)
layout.addWidget(self.mpl_toolbar, 1, 0)
layout.addWidget(self.startButton, 2, 0)
layout.addWidget(self.stopButton, 2, 1)
self.main_frame.setLayout(layout)
self.setCentralWidget(self.main_frame)
self.setWindowTitle(self.tr("XRTdev Interface"))
def create_status_bar(self):
self.status_text = QLabel("I am a status bar. I need a status to show!")
self.statusBar().addWidget(self.status_text, 1)
def start_acquisition(self):
self.thread.exiting = False
self.startButton.setEnabled(False)
self.stopButton.setEnabled(True)
self.thread.render()
def stop_acquisition(self):
self.thread.exiting = True
self.startButton.setEnabled(True)
self.stopButton.setEnabled(False)
self.cleanup_UI()
def update_figure(self, lE, hE):
if self.background == None:
self.background = self.canvas.copy_from_bbox(self.axes.bbox)
self.canvas.restore_region(self.background)
self.lE_line.set_ydata(lE)
self.hE_line.set_ydata(hE)
self.axes.draw_artist(self.lE_line)
self.axes.draw_artist(self.hE_line)
self.canvas.blit(self.axes.bbox)
def update_UI(self):
self.startButton.setEnabled(True)
self.stopButton.setEnabled(False)
self.cleanup_UI()
def cleanup_UI(self):
self.background = None
self.axes.clear()
self.canvas.draw()
class Worker(QThread):
pixel_list = pyqtSignal(list, list)
def __init__(self, parent = None):
QThread.__init__(self, parent)
self.exiting = False
def __del__(self):
self.exiting = True
self.wait()
def render(self):
self.start()
def run(self):
# simulate I/O
n = random.randrange(100,200)
while not self.exiting and n > 0:
lE = [random.randrange(5,16) for i in xrange(512)]
hE = [random.randrange(80,121) for i in xrange(512)]
self.pixel_list.emit(lE, hE)
time.sleep(0.02)
n -= 1
def main():
app = QApplication(sys.argv)
form = ApplicationWindow()
form.show()
app.exec_()
if __name__ == "__main__":
main()
也许我的问题甚至不在于 MatPlotLib 或 PyQT4,而是我实现线程的方式。正如我所指出的,我对此并不陌生并且正在学习。而且,我什至不确定 GUIqwt 是否会解决这些问题中的任何一个——但我知道我在这里看到了很多建议使用比 MatPlotLib 更快的东西在 GUI 中进行“实时”绘图。感谢您对此的帮助!
最佳答案
[编辑因为 QThread
令人困惑/困惑]
似乎有两种使用它的方法,要么对其进行子类化(如您的示例和文档所述),要么创建一个工作对象,然后将其移动到一个线程(参见 this blog post)。当你混合信号/插槽时,我会变得更加困惑。正如 Avaris 所说,这种变化可能不是你的问题。
我将您的 Worker
类重新设计为 QObject
的子类(因为这是我理解的样式)。
一个问题是,如果你不在你的假数据系统中放置一个 sleep
,那么你会在 < 1 秒内生成对主窗口的所有回调。然后主线程在清除信号队列时基本上被阻塞。如果您将延迟设置为您指定的延迟(0.0005 秒),那么它会以比显示数据快得多的速度生成数据,这似乎表明这可能不适合您的问题(务实,您也可以没那么快,而且似乎在 30 - 40 fps 时还可以)。
import time, random, sys
#from PySide.QtCore import *
#from PySide.QtGui import *
from PyQt4 import QtCore
from PyQt4 import QtGui
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
class ApplicationWindow(QtGui.QMainWindow):
get_data = QtCore.pyqtSignal()
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)
self.thread = QtCore.QThread(parent=self)
self.worker = Worker(parent=None)
self.worker.moveToThread(self.thread)
self.create_main_frame()
self.create_status_bar()
self.startButton.clicked.connect(self.start_acquisition)
self.stopButton.clicked.connect(self.stop_acquisition)
self.worker.pixel_list.connect(self.update_figure)
self.worker.done.connect(self.update_UI)
self.get_data.connect(self.worker.get_data)
self.thread.start()
def create_main_frame(self):
self.main_frame = QtGui.QWidget()
self.dpi = 100
self.width = 10
self.height = 8
self.fig = Figure(figsize=(self.width, self.height), dpi=self.dpi)
self.axes = self.fig.add_subplot(111)
self.axes.axis((0,512,0,120))
self.canvas = FigureCanvas(self.fig)
self.canvas.setParent(self.main_frame)
self.canvas.updateGeometry()
self.canvas.draw()
self.background = None
self.lE_line, = self.axes.plot(range(512), [0 for i in xrange(512)], animated=True)
self.hE_line, = self.axes.plot(range(512), [0 for i in xrange(512)], animated=True)
self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)
self.startButton = QtGui.QPushButton(self.tr("&Start"))
self.stopButton = QtGui.QPushButton(self.tr("&Stop"))
layout = QtGui.QGridLayout()
layout.addWidget(self.canvas, 0, 0)
layout.addWidget(self.mpl_toolbar, 1, 0)
layout.addWidget(self.startButton, 2, 0)
layout.addWidget(self.stopButton, 2, 1)
self.main_frame.setLayout(layout)
self.setCentralWidget(self.main_frame)
self.setWindowTitle(self.tr("XRTdev Interface"))
def create_status_bar(self):
self.status_text = QtGui.QLabel("I am a status bar. I need a status to show!")
self.statusBar().addWidget(self.status_text, 1)
def start_acquisition(self):
self.worker.exiting = False
self.startButton.setEnabled(False)
self.stopButton.setEnabled(True)
self.get_data.emit()
def stop_acquisition(self):
self.worker.exiting = True
self.startButton.setEnabled(True)
self.stopButton.setEnabled(False)
self.cleanup_UI()
def update_figure(self, lE, hE):
if self.background == None:
self.background = self.canvas.copy_from_bbox(self.axes.bbox)
self.canvas.restore_region(self.background)
self.lE_line.set_ydata(lE)
self.hE_line.set_ydata(hE)
self.axes.draw_artist(self.lE_line)
self.axes.draw_artist(self.hE_line)
self.canvas.blit(self.axes.bbox)
def update_UI(self):
self.startButton.setEnabled(True)
self.stopButton.setEnabled(False)
self.cleanup_UI()
def cleanup_UI(self):
self.background = None
self.axes.clear()
self.canvas.draw()
class Worker(QtCore.QObject):
pixel_list = QtCore.pyqtSignal(list, list)
done = QtCore.pyqtSignal()
def __init__(self, parent = None):
QtCore.QObject.__init__(self, parent)
self.exiting = True
@QtCore.pyqtSlot()
def get_data(self):
# simulate I/O
print 'data_start'
n = random.randrange(100,200)
while not self.exiting and n > 0:
lE = [random.randrange(5,16) for i in xrange(512)]
hE = [random.randrange(80,121) for i in xrange(512)]
self.pixel_list.emit(lE, hE)
time.sleep(0.05)
n -= 1
print 'n: ', n
self.done.emit()
关于python - time.sleep() 需要保持 QThread 响应吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14665636/
我想写一些必须在自己的线程中工作的类。我读过这篇文章:http://wiki.qt.io/Threads_Events_QObjects。它建议移动必须在自己的线程中工作的对象,例如: TestCla
在调用所有与 QThread::finished() 信号关联的槽后,QThread::wait() 是否返回(即解除阻塞执行)? 提前致谢。 最佳答案 不,它可能会在与信号 finished() 关
我不是在打电话 exec()在我的代码中,但 timer和 QUdpSocket工作正常。是 exec()用于等待 event接着说? 更新:timer正在工作,因为我没有调用 moveToThrea
如果我创建 QThread 作为局部变量,我发现了一个奇怪的行为。 例如,下面的代码将作为单线程工作,这意味着我需要等待 10 秒,结果才会出来。 但是如果我将线程从局部变量更改为成员变量,它将作为多
I solved my issue by moving the mySubQThread run() into the myQThread run() That said, I still would
一段时间以来,我一直在使用 Qt 开发一个应用程序,在该应用程序中我必须从相机中抓取帧。相机将在与应用程序其余部分不同的线程中运行。我遵循了以下建议: http://mayaposch.wordpre
考虑以下代码片段: class ThreadA::QThread { public: ThreadA() { } void run() { myVariable = n
所以我在构造函数中有以下代码。 m_someObject = new SomeObject(); m_someObject->moveToThread(&m_thread); m_thread.sta
我有 3 个 QThreads 相互调用(全部继承自 QThread。我知道有些人可能建议使用 moveToThread,但暂时忽略这个事实)。简化的代码如下所示: Thread1 类: void T
我想知道 new QThread(this) 和 new QThread() 之间有什么区别,以及这将如何影响我的代码在使用 QThread 时的行为. 最佳答案 QThread 的父级谁执行什么没有
我是 PySide2 的新手。我只是想启动一个示例应用程序并在应用程序启动时启动一个线程,并希望在应用程序关闭时停止该线程。当我关闭应用程序时,我收到以下错误:QThread:在线程仍在运行时销毁。s
关于如何实例化和使用 QThread 的官方文档可以在这里找到: http://doc.qt.io/qt-5/qthread.html 该文档描述了两种基本方法:(1) 工作对象方法和 (2) QTh
我有以下设置: int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // Create the DBM
这是 QTread 的子对象...并在主线程中将其具体化.... 运行时错误如下: ASSERT failure in QCoreApplication::sendEvent: "Cannot sen
在过去的几天里,我一直在尝试使用 QThreads 而不对 QThread 进行子类化的新的首选方法。我遇到的麻烦是当我试图关闭我创建的一组线程时。我经常收到“线程仍在运行时已被销毁”消息(如果我在
我已经创建了这个继承自QThread的类,用于向数据库服务器发送数据,你觉得怎么样?可以改进吗? 谢谢 #ifndef QUERYTHREAD_H#define QUERYTHREAD_H#inclu
我需要在一个线程中进行无限循环。 在 this article作者写道 >you should never ever block the event loop 因为它会阻塞信号槽概念。如何在 QTh
我试图在一个单独的线程中执行一些工作,并在工作完成后停止该线程。 我已经建立了这样的连接 thread.connect( workerClass, SIGNAL( finished() ), SLOT
我有一个快速的问题。我应该创建一个小的多线程程序来从多个传感器获取数据,并且我了解 pthreads 和 qthreads。我可以访问两个图书馆。我个人偏向于使用 Qt,因为它的设计和各种功能。但是,
我需要在主线程上运行 QThread::usleep() (出于各种原因)。 但是,usleep 是受静电保护的。 我想在没有包装器的情况下使用 QThread 的 usleep 函数(我目前正在使用
我是一名优秀的程序员,十分优秀!