Hi,

Keep in mind that everything is based around Qt, and thus the Qt event 
loop. Once you call app.exec_() (or QtGui.QApplication.instance().exec_() 
in your code), then the code will block here until the Qt app is exited. 
Everything you do should therefore be driven by events in your event loop 
(triggered by menu actions, button presses, or QTimer timeouts etc). For a 
serious GUI, you'll want to build your program around a QWidget or 
QMainWindow etc. Here's an example I've used before, with some notes to 
show how I'd do reading from a serial port.
(You don't want to open the serial port every time you want to read some 
bytes from it etc.)

Patrick

from PyQt5 import QtCore, QtWidgets, uic
from PyQt5.QtCore import pyqtSignal, pyqtSlot
import numpy as np
import pyqtgraph as pg
from threading import Thread, Event
import time

# Routine to acquire and serve data
def generate_data(callback, threadkill):
    # Open serial port
    # ser = serial.Serial(port=....)
    while not threadkill.is_set():
        # Wait for read from serial port...
        # ser.read()
        # Process raw bytes...
        # See python struct module for utilities for interpreting raw data
        # Note, may read a variable amount of data from serial port
        data = np.random.random(np.random.randint(16))
        # Notify Qt thread of new data
        callback(data)
        time.sleep(0.01)
    # Close serial port
    # ser.close()

class PyQtGraphTest(QtWidgets.QMainWindow):

    # Signal to indicate new data acquisition
    # Note: signals need to be defined inside a QObject class/subclass
    data_acquired = pyqtSignal(np.ndarray)

    def __init__(self):
        super().__init__()
        # Load ui layout from file
        uic.loadUi(__file__.split('.py')[0] + '.ui', self, package=
__package__)

        # Build pyqtgraph plot layout
        self.plot = self.graphicsLayoutWidget.addPlot()
        self.spectrum = self.plot.plot()

        # Connect signals
        self.pushButton.clicked.connect(self.start_clicked)
        # Connect the signal for new data acquisition
        self.data_acquired.connect(self.update_data)
        # An Event to indicate other thread should finish up
        self.threadkill = Event()

        # Buffer for data
        self.data = np.zeros(2**11)
        # Will use it as a circlular buffer, so adjust x-axis for correct 
sample numbers
        self.spectrum.setPos(-self.data.shape[0], 0)

    def start_clicked(self, thing):
        if self.pushButton.isChecked():
            # Make and start the background thread to acquire data
            # Pass it the signal.emit as the callback function
            self.thread = Thread(target=generate_data, args=(self.
data_acquired.emit, self.threadkill))
            self.threadkill.clear()
            self.thread.start()
            self.pushButton.setText("&Stop")
        else:
            # Stop background thread
            self.threadkill.set()
            self.pushButton.setText("&Start")

    # Kill our data acquisition thread when shutting down
    def closeEvent(self, close_event):
        self.threadkill.set()

    # Slot to receive acquired data and update plot
    @pyqtSlot(np.ndarray)
    def update_data(self, newdata):
        # Circular roll buffer back to make space for new data
        self.data = np.roll(self.data, newdata.shape[0])
        self.data[newdata.shape[0]:0:-1] = newdata[::-1]
        self.spectrum.setData(self.data[::-1])
        # Adjust x-axis sample numbers
        self.spectrum.translate(newdata.shape[0], 0)
        # See pyqtgraph scrolling plot examples for different/better 
implementations
        # You probably want the one that doubles the buffer size when full, 
but it
        # would need to be modified to handle receiving >1 data point at a 
time.

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = PyQtGraphTest()
    window.show()
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        sys.exit(app.exec_())

...and a .ui file (same name as above, but with .ui file extension):

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout_2">
      <item>
       <widget class="QLineEdit" name="lineEdit"/>
      </item>
      <item>
       <widget class="QPushButton" name="pushButton_2">
        <property name="text">
         <string>PushButton</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="pushButton">
        <property name="text">
         <string>PushButton</string>
        </property>
       </widget>
      </item>
     </layout>
    </item>
    <item>
     <widget class="QGroupBox" name="groupBox">
      <property name="title">
       <string>It's a plot</string>
      </property>
      <layout class="QHBoxLayout" name="horizontalLayout">
       <item>
        <widget class="PlotWidget" name="plotWidget"/>
       </item>
      </layout>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>19</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <customwidgets>
  <customwidget>
   <class>PlotWidget</class>
   <extends>QGraphicsView</extends>
   <header>pyqtgraph</header>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>





On Thursday, 30 January 2020 09:30:54 UTC+10:30, Gustavo Deza wrote:
>
> Hello all, 
> I am new to pyqtgraph, and I can plot data from com port in real time, but 
> I can't exit the window to run the rest of the code. I've tried to 
> implement a while loop += 1 and a set number of "samples" n, to no avail. 
> Any suggestions would be highly appretiated 
>
> # -*- coding: utf-8 -*-
> from pyqtgraph.Qt import QtGui, QtCore
> import numpy as np
> from numpy import arange, sin, cos, pi
> import pyqtgraph as pg
> import sys
> import serial
> import time
>
>
>
> def bytes_to_int(bytes):                        # Bytes to integers
>     result = 0
>     for b in bytes:
>         result = result * 256 + int(b)
>     return result
>
> class Plot2D():
>     def __init__(self):
>         self.traces = dict()
>
>         #QtGui.QApplication.setGraphicsSystem('raster')
>         self.app = QtGui.QApplication([])
>         #mw = QtGui.QMainWindow()
>         #mw.resize(800,800)
>
>         self.win = pg.GraphicsWindow(title="SeƱal")
>         self.win.resize(1000,600)
>         self.win.setWindowTitle('Voltaje')
>
>         # Enable antialiasing for prettier plots
>         pg.setConfigOptions(antialias=True)
>
>         self.canvas = self.win.addPlot(title="Medicion")
>
>     def start(self):
>         if (sys.flags.interactive != 1) or not hasattr(QtCore, 
> 'PYQT_VERSION'):
>             QtGui.QApplication.instance().exec_()
>
>     def trace(self,name,dataset_x,dataset_y):
>         if name in self.traces:
>             self.traces[name].setData(dataset_x,dataset_y)
>         else:
>             self.traces[name] = self.canvas.plot(pen='y')
>
>
> val_vol = []
> val_time = []
> n = 40
> count = 0
> #i = 0
> while (count <= n):
> ## Start Qt event loop unless running in interactive mode or using pyside.
>     if __name__ == '__main__':
>         p = Plot2D()
>         #i = 0
>         count = 0
>
>         def update():
>             global p, count
>             ser = serial.Serial(port='com11', baudrate=9600)
>             rawvol = ser.read()
>             vol = bytes_to_int(rawvol)
>             val_vol.append(vol)
>             val_time.append(time.clock())
>             p.trace("sin",val_time,val_vol)
>             #i += 0.1
>             print(val_vol)
>             count += 1
>
>         timer = QtCore.QTimer()
>         timer.timeout.connect(update)
>         timer.start(50)
>
>         p.start()
>         sys.exit()
>         print(count)
>
>
>  
>

-- 
You received this message because you are subscribed to the Google Groups 
"pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/pyqtgraph/b70bd88e-5ecd-4a89-9f0a-4f71e18513de%40googlegroups.com.

Reply via email to