Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Running multiple plots with pyside2



  • I am trying to run multiple plot window in threads.

    from PySide2.QtWidgets import QApplication
    import sys
    from pyqtgraph import GraphicsLayoutWidget
    from pyqtgraph.Qt import QtCore
    import numpy as np
    import pyqtgraph as pg
    import threading
    
    
    class AnotherWindow(GraphicsLayoutWidget):
        def __init__(self):
            super().__init__()
            pg.setConfigOptions(antialias=True)
            self.p6 = self.addPlot(title="Updating plot")
            self.curve = self.p6.plot(pen='y')
            self.data = np.random.normal(size=(10, 1000))
            self.ptr = 0
    
            self.timer = QtCore.QTimer()
            self.timer.timeout.connect(self.update)
            self.timer.start(50)
            
    
        def update(self):
            self.curve.setData(self.data[self.ptr % 10])
            if self.ptr == 0:
                self.p6.enableAutoRange('xy', False)
            self.ptr += 1
    
    
    app = QApplication(sys.argv)
    
    
    def th():
        w = AnotherWindow()
        w.show()
    
    
    mythread = threading.Thread(target=th)
    mythread.start()
    mythread.join()
    

    It gives following error:

    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QApplication(0x323e610), parent's thread is QThread(0x3179fd0), current thread is QThread(0x7f6834001640)
    QObject::startTimer: Timers can only be used with threads started with QThread
    QObject::startTimer: Timers can only be used with threads started with QThread
    QBasicTimer::start: QBasicTimer can only be used with threads started with QThread
    QBasicTimer::start: QBasicTimer can only be used with threads started with QThread
    ...
    

    It works when I run it directly.

    app = QApplication(sys.argv)
    w = AnotherWindow()
    w.show()
    app.exec_()
    

    but I want to do something like this:

    mythread = threading.Thread(target=th)
    mythread.start()
    
    mythread1 = threading.Thread(target=th)
    mythread1.start()
    

  • Lifetime Qt Champion

    @anoop1 Your AnotherWindow instance is created in main thread. You should at least change your code, so that this instance is created in the new thread.
    But I doubt this approach will work at all as Qt GUI classes can only be used in main thread (GUI thread).



  • @jsulm thanks for reply.

    I have tried

    app = QApplication(sys.argv)
    
    w = AnotherWindow()
    
    
    def th():
        w.show()
    
    
    mythread = threading.Thread(target=th)
    mythread.start()
    

    but now plot is not updating.

    there is another approach that I am trying:

    from PySide2.QtWidgets import QApplication, QMainWindow
    import sys
    from pyqtgraph import GraphicsLayoutWidget
    from pyqtgraph.Qt import QtCore
    import numpy as np
    import pyqtgraph as pg
    
    
    class AnotherWindow(GraphicsLayoutWidget):
        def __init__(self):
            super().__init__()
            pg.setConfigOptions(antialias=True)
            self.p6 = self.addPlot(title="Updating plot")
            self.curve = self.p6.plot(pen='y')
            self.data = np.random.normal(size=(10, 1000))
            self.ptr = 0
    
            self.timer = QtCore.QTimer()
            self.timer.timeout.connect(self.update)
            self.timer.start(50)
    
        def update(self):
            self.curve.setData(self.data[self.ptr % 10])
            if self.ptr == 0:
                self.p6.enableAutoRange('xy', False)
            self.ptr += 1
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.w = []
            self.show_new_window()
            self.show_new_window()
    
        def show_new_window(self):
            self.w.append(AnotherWindow())
            self.w[-1].show()
    
    
    app = QApplication(sys.argv)
    w = MainWindow()
    app.exec_()
    

    It shows 2 plot window.

    but when I move this code in my cmd module it get stuck

    class CLI(cmd.Cmd):
    
        def __init__(self):
            super().__init__()
            self.app = QApplication(sys.argv)
            self.w = MainWindow()
    
    
    if __name__ == '__main__':
        CLI().cmdloop()
    


  • @anoop1 said in Running multiple plots with pyside2:

    but when I move this code in my cmd module it get stuck

    What does this mean?



  • @JonB means it opens 2 window with black screen, (looks like GUI thread gets stuck).

    this is complete code:

    from PySide2.QtWidgets import QApplication, QMainWindow
    import sys
    from pyqtgraph import GraphicsLayoutWidget
    from pyqtgraph.Qt import QtCore
    import numpy as np
    import pyqtgraph as pg
    import cmd
    
    
    class AnotherWindow(GraphicsLayoutWidget):
        def __init__(self):
            super().__init__()
            pg.setConfigOptions(antialias=True)
            self.p6 = self.addPlot(title="Updating plot")
            self.curve = self.p6.plot(pen='y')
            self.data = np.random.normal(size=(10, 1000))
            self.ptr = 0
    
            self.timer = QtCore.QTimer()
            self.timer.timeout.connect(self.update)
            self.timer.start(50)
    
        def update(self):
            self.curve.setData(self.data[self.ptr % 10])
            if self.ptr == 0:
                self.p6.enableAutoRange('xy', False)
            self.ptr += 1
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.w = []
            self.show_new_window()
            self.show_new_window()
    
        def show_new_window(self):
            self.w.append(AnotherWindow())
            self.w[-1].show()
    
    
    class CLI(cmd.Cmd):
    
        def __init__(self):
            super().__init__()
            self.app = QApplication(sys.argv)
            self.w = MainWindow()
    
    
    if __name__ == '__main__':
        CLI().cmdloop()
    


  • @anoop1

    this is complete code:

    1. Why would you have a MainWindow but never show it?

    2. After CLI().cmdloop() has been executed, CLI and everything else goes out of scope. Your program then exits since it never executes the Qt event loop.

    Since you are choosing to use Python Cmd.cmdloop I suggest you investigate that as a Python question. Goodness knows how it interacts with Qt.



  • @JonB My aim to show plot when user uses plot command so there can be multiple plot window on the screen at a given time, above code I got from https://www.learnpyqt.com/tutorials/creating-multiple-windows/ and trying to adjust it so it will work with CMD module but it is not working.



  • @anoop1
    As I said, how do you expect Python's Cmd.cmdloop to interact with Qt's event-driven system and windows/widgets?