关闭窗口后方法仍在运行
Posted
技术标签:
【中文标题】关闭窗口后方法仍在运行【英文标题】:Method is still running after closing window 【发布时间】:2021-10-21 00:58:46 【问题描述】:我无法理解窗口对象的工作原理。我通过 matplotlib 在辅助窗口上有一个实时绘图。该图每秒使用新的计算值更新。 我期望的是每当我关闭第二个窗口时停止运行并在我重新打开它时重新启动的方法。当我关闭第二个窗口时,我可以重置数组值,但如所示,这种计算值的方法仍在运行。
这是我的代码(最初使用传感器,我将其修改为生成随机数):
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_())
【问题讨论】:
你永远不会告诉计时器停止,你关闭窗口的事实是无关紧要的。您也没有创建对计时器的任何持久引用(这是您停止它所需要的)。更改为self.timer = ...
,然后在closeEvent()
中使用self.chart.timer.stop()
。或者,在AppDemo
中使用self.setAttribute(Qt.WA_DeleteOnClose)
。
【参考方案1】:
窗口关闭并不意味着定时器停止,你必须使用QTimer的stop方法来实现它。
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_())
【讨论】:
非常感谢@eyllanesc,现在我明白了!并感谢您为我提供原始帖子。尝试放置一个更简单的代码版本有助于我理解其他一些事情。非常感谢!以上是关于关闭窗口后方法仍在运行的主要内容,如果未能解决你的问题,请参考以下文章