Home > other >  Method is still running after closing window
Method is still running after closing window

Time:10-21

I'm having trouble trying to undersand how the window objects work. I have a real time plot on a secundary window via matplotlib. This plot updates every second with the new calculated values. What I expect is the method to stop running whenever I close this 2nd window and restarts when I reopen it. I'm able to reset the array values when I'm closing the 2nd window but as indicated, this method calculating the values is still running.

This is my code (originally using a sensor, I modified this to generate random numbers instead):

from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
import sys
import random
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure


# The main window 
class Window(QWidget):
    def __init__(self):
        super().__init__()
 
        self.setGeometry(200,200, 400,300)
        self.setWindowTitle('Test')
        self.demo = None
        
        self.create_buttons()
        
    def create_buttons(self):
        btn1 = QPushButton('Open window', self)
        btn1.setGeometry(100,100, 100,100)
        btn1.clicked.connect(self.open_w)
        
    def open_w(self):
        if self.demo is None:
            self.demo = AppDemo()
        self.demo.show()
        
# Second window, where I plot the data
class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(650, 500)
        self.plotwidget = QWidget(self)
        self.chart = Matplotlibwidget()
        self.chart.plot_widget(self.plotwidget, self.chart)
        
    def closeEvent(self, event):
        event.accept()
        func.start_lists()
        print('Window closed')
        
# My widget for my graph        
class Matplotlibwidget(FigureCanvas):
    def __init__(self, parent=None):
        fig = Figure()
        self.axes = fig.add_subplot(111)
        
        FigureCanvas.__init__(self, fig)
        self.setParent(parent)
        FigureCanvas.updateGeometry(self)      
    
    def plot_widget(self, canvasWidget, graph):
        self.layoutvertical = QVBoxLayout(canvasWidget)
        self.layoutvertical.addWidget(graph)        
        timer = QtCore.QTimer(self)
        timer.timeout.connect(self.plotting)
        timer.start(1000)
              
    def plotting(self):
        self.y = func.calculate()
        func.appends(self.y)
        self.axes.cla()
        self.axes.plot(func.x, func.y)
        self.draw()

# This is a generic class I use to calculate the data, originally this is a class for my sensor
class FuncTime ():
    def __init__(self):
        self.start_lists()
         
    def start_lists(self):
        self.x, self.y = [0], [1]
        
    def calculate(self):
        return self.y[-1]   self.y[-1] * random.uniform(-0.1, 0.1)
        
    def appends(self, y):
        print(self.x[-1], ', ', self.y[-1])
        self.x.append(self.x[-1]   1)
        self.y.append(y)

  
app = QApplication(sys.argv)
func = FuncTime()
window = Window()
window.show()
sys.exit(app.exec_())

CodePudding user response:

That the window closes does not imply that the timer stops, you have to implement it using the stop method of the QTimer.

from functools import cached_property
import random
import sys

from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure


class Window(QWidget):
    def __init__(self):
        super().__init__()

        self.setGeometry(200, 200, 400, 300)
        self.setWindowTitle("Test")
        self.create_buttons()

    @cached_property
    def demo(self):
        return AppDemo()

    def create_buttons(self):
        btn1 = QPushButton("Open window", self)
        btn1.setGeometry(100, 100, 100, 100)
        btn1.clicked.connect(self.open_w)

    def open_w(self):
        self.demo.chart.start()
        self.demo.show()


class AppDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(650, 500)

        self.chart = Matplotlibwidget()

        lay = QVBoxLayout(self)
        lay.addWidget(self.chart)

    def closeEvent(self, event):
        super().closeEvent(event)
        self.chart.stop()


class Matplotlibwidget(FigureCanvas):
    def __init__(self, parent=None):
        fig = Figure()
        self.axes = fig.add_subplot(111)
        FigureCanvas.__init__(self, fig)
        self.setParent(parent)
        self.updateGeometry()

    @cached_property
    def timer(self):
        return QTimer(interval=1000, timeout=self.handle_timeout)

    @cached_property
    def func_time(self):
        return FuncTime()

    def start(self):
        self.timer.start()

    def stop(self):
        self.timer.stop()
        self.func_time.reset()

    def handle_timeout(self):
        self.plotting()

    def plotting(self):
        self.y = self.func_time.calculate()
        self.func_time.appends(self.y)
        self.axes.cla()
        self.axes.plot(self.func_time.x, self.func_time.y)
        self.draw()


class FuncTime:
    def __init__(self):
        self.reset()

    def reset(self):
        self.x, self.y = [0], [1]

    def calculate(self):
        return self.y[-1]   self.y[-1] * random.uniform(-0.1, 0.1)

    def appends(self, y):
        print(self.x[-1], ", ", self.y[-1])
        self.x.append(self.x[-1]   1)
        self.y.append(y)


app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
  • Related