GUI中的功能启动和停止按钮使用pyqt或pyside进行实时数据采集,使用pyqtgraph

时间:2016-03-07 05:19:03

标签: python user-interface pyqtgraph

我正在使用pyqtgraph提供的scrollingplots示例实现我的程序https://github.com/skycaptain/gazetrack/blob/master/gui/pyqtgraph/examples/scrollingPlots.py

import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np

win = pg.GraphicsWindow()
win.setWindowTitle('pyqtgraph example: Scrolling Plots')
win.nextRow()
p3 = win.addPlot()
p4 = win.addPlot()
# Use automatic downsampling and clipping to reduce the drawing load
p3.setDownsampling(mode='peak')
p4.setDownsampling(mode='peak')
p3.setClipToView(True)
p4.setClipToView(True)
p3.setRange(xRange=[-100, 0])
p3.setLimits(xMax=0)
curve3 = p3.plot()
curve4 = p4.plot()

data3 = np.empty(100)
ptr3 = 0

def update2():
    global data3, ptr3
    data3[ptr3] = np.random.normal()
    ptr3 += 1
    if ptr3 >= data3.shape[0]:
        tmp = data3
        data3 = np.empty(data3.shape[0] * 2)
        data3[:tmp.shape[0]] = tmp
    curve3.setData(data3[:ptr3])
    curve3.setPos(-ptr3, 0)
    curve4.setData(data3[:ptr3])

# update all plots

timer = pg.QtCore.QTimer()
timer.timeout.connect(update3)
timer.start(50)

## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

首先,我想使用Ctrl + C作为信号来停止连续数据绘图并将获得的数据保存到文件中。但是,退出程序的唯一方法是关闭图形窗口。在终端中执行Ctrl + C不会执行任何操作。

因此,我想在程序中实现一个启动和停止(并保存数据)的按钮。

作为Python和面向对象编程的新手,我在网上搜索了一些例子。我找到了专门用于GUI中按钮实现的示例:

  • stackoverflow.com/questions/8762870/how-to-implement-a-simple-button-in-pyqt

  • groups.google.com/forum /#!主题/ pyqtgraph / bxvZHtb1KKg

  • www.youtube.com/watch?v=z33vwdHrAFM和youtuber的GUI相关教程

这些例子都没有帮助我实现我想要的东西,因为我不知道如何将它们与滚动图示例结合起来。

来自Qt速成课程网页(pyqtgraph.org/documentation/qtcrashcourse.html):

from PyQt4 import QtGui  # (the example applies equally well to PySide)
import pyqtgraph as pg

## Always start by initializing Qt (only once per application)
app = QtGui.QApplication([])

## Define a top-level widget to hold everything
w = QtGui.QWidget()

## Create some widgets to be placed inside
btn = QtGui.QPushButton('press me')
text = QtGui.QLineEdit('enter text')
listw = QtGui.QListWidget()
plot = pg.PlotWidget()

## Create a grid layout to manage the widgets size and position
layout = QtGui.QGridLayout()
w.setLayout(layout)

## Add widgets to the layout in their proper positions
layout.addWidget(btn, 0, 0)   # button goes in upper-left
layout.addWidget(text, 1, 0)   # text edit goes in middle-left
layout.addWidget(listw, 2, 0)  # list widget goes in bottom-left
layout.addWidget(plot, 0, 1, 3, 1)  # plot goes on right side, spanning 3 rows

## Display the widget as a new window
w.show()

## Start the Qt event loop
app.exec_()

因为在大多数按钮示例代码的末尾会有app.exec_(),并且滚动图示例本身也有更新循环,我对它们如何同时运行感到困惑。

我已经在某处读过关于使用gui进行持续运行的过程,我应该考虑使用定时器或多线程。不过,我目前对线程没有任何了解。

我甚至尝试过Tkinter,因为我找到了一些如何使用Tkinter和matplotlib的指南 - > pythonprogramming.net/how-to-embed-matplotlib-graph-tkinter-gui /

期待收到有关此问题的任何建议。

2 个答案:

答案 0 :(得分:1)

from PyQt4 import QtCore, QtGui
import pyqtgraph as pg

class MainForm(QtGui.QMainWindow):
    def __init__(self):
        super(MainForm, self).__init__()
        self.playTimer = QtCore.QTimer()
        self.playTimer.setInterval(500)
        self.playTimer.timeout.connect(self.playTick)
        self.toolbar = self.addToolBar("Play")
        self.playScansAction = QtGui.QAction(QtGui.QIcon("control_play_blue.png"), "play scans", self)
        self.playScansAction.triggered.connect(self.playScansPressed)
        self.playScansAction.setCheckable(True)
        self.toolbar.addAction(self.playScansAction)

    def playScansPressed(self):
        if self.playScansAction.isChecked():
            self.playTimer.start()
        else:
            self.playTimer.stop()

    def playTick(self):
        pass

def main():
    app = QtGui.QApplication(sys.argv)
    form = MainForm()
    form.initUI("Scan Log Display")
    form.show()
    app.exec_()

if __name__ == "__main__":
    main()

答案 1 :(得分:0)

你可以通过设置 while = True 来暂停循环,你可以使用 break 来停止循环

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import (
    Qt, QObject, pyqtSignal, pyqtSlot, QRunnable, QThreadPool
)
import time
from time import sleep
import threading

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(655, 589)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.run = QtWidgets.QPushButton(self.centralwidget)
        self.run.setGeometry(QtCore.QRect(260, 50, 93, 28))
        self.run.setObjectName("run")
        self.result = QtWidgets.QTextEdit(self.centralwidget)
        self.result.setGeometry(QtCore.QRect(110, 120, 491, 201))
        self.result.setObjectName("result")
        self.stop = QtWidgets.QPushButton(self.centralwidget)
        self.stop.setGeometry(QtCore.QRect(110, 390, 93, 28))
        self.stop.setObjectName("stop")
        self.pause = QtWidgets.QPushButton(self.centralwidget)
        self.pause.setGeometry(QtCore.QRect(300, 390, 93, 28))
        self.pause.setObjectName("pause")
        self.resume = QtWidgets.QPushButton(self.centralwidget)
        self.resume.setGeometry(QtCore.QRect(480, 390, 93, 28))
        self.resume.setObjectName("resume")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 655, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.run.setText(_translate("MainWindow", "Run"))
        self.stop.setText(_translate("MainWindow", "stop"))
        self.pause.setText(_translate("MainWindow", "Pause"))
        self.resume.setText(_translate("MainWindow", "Resume"))
        
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.is_paused = False
        self.is_killed = False
        self.run.clicked.connect(self.send_wala)
        self.stop.clicked.connect(self.kill_g)
        self.pause.clicked.connect(self.pause_g)
        self.resume.clicked.connect(self.resume_g)
        
    @QtCore.pyqtSlot()
    def send_wala(self):
        threading.Thread(target=self.working, daemon=True).start()
        
        
    def working(self):
        for i in range(10):
            sleep(3)
            self.result.append(str(i))
            while self.is_paused:
                time.sleep(0)
                
            if self.is_killed:
                break
            
    def pause_g(self):
        self.is_paused = True
        
    def resume_g(self):
        self.is_paused = False
        
    def kill_g(self):
        self.is_killed = True
        


import sys

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())