PyQT5 实时更新图
PyQT5 live updating plots
我需要帮助为这些图表中的每一个添加实时绘图。我尝试了很多解决方案,但每一个都让我的 window 崩溃。有没有我遗漏的简单修复方法?
下面是没有任何更新方法的代码:
import sys
from PyQt5.QtWidgets import QDialog, QApplication, QPushButton, QVBoxLayout
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import pandas as pd
class Window(QDialog):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.figure = plt.figure(tight_layout=True)
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas, self)
self.button5 = QPushButton('Lane 5')
self.button4 = QPushButton('Lane 4')
self.button3 = QPushButton('Lane 3')
self.button2 = QPushButton('Lane 2')
self.button1 = QPushButton('Lane 1')
self.button1.clicked.connect(self.plot1)
self.button2.clicked.connect(self.plot2)
self.button3.clicked.connect(self.plot3)
self.button4.clicked.connect(self.plot4)
self.button5.clicked.connect(self.plot5)
layout = QVBoxLayout()
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
layout.addWidget(self.button1)
layout.addWidget(self.button2)
layout.addWidget(self.button3)
layout.addWidget(self.button4)
layout.addWidget(self.button5)
self.setLayout(layout)
def plot1(self):
data = pd.read_csv("2021-08-13.csv", parse_dates=['time'], infer_datetime_format=True)
datafilter = data[data.lane == "Lane 1 Op2"]
datafilter['time'] = pd.to_datetime(datafiltr['time'], errors='coerce')
df = datafilter['time'].groupby(datafilter.godzina.dt.to_period("H")).agg('count')
y = [df.index[i].to_timestamp() for i in range(len(df))]
self.figure.clear()
ax = self.figure.add_subplot(111)
ax.bar(y, df, width=0.035)
self.canvas.draw()
if __name__ == '__main__':
app = QApplication(sys.argv)
main = Window()
main.show()
sys.exit(app.exec_())
这里是 csv 文件示例:
lane,detail,time,potentiometer,piece,tooltime
Lane 3 Op3,3584,00:00:03,100%,873,0:00:58
Lane 3 Op2,00:00:20,150,,,
Lane 4 Op3,00:01:40,811,,,
Lane 3 Op1,1584,00:00:20,100%,149,0:01:32
Lane 2 Op2,2508,00:00:40,110%,151,0:01:49
Lane 3 Op1,00:00:34,149,,,
Lane 2 Op3,3508,00:00:56,100%,551,0:01:05
Lane 2 Op2,00:00:25,151,,,
Lane 3 Op3,00:01:07,873,,,
Lane 4 Op2,2858,00:01:31,100%,104,0:02:34
Lane 4 Op3,3858,00:01:32,100%,812,0:01:20
Lane 2 Op1,1508,00:01:33,100%,152,0:01:35
Lane 1 Op1,1141,00:01:38,100%,125,0:01:49
Lane 1 Op2,1141,00:01:38,100%,125,0:01:49
Lane 3 Op2,2584,00:01:51,100%,151,0:01:45
您的代码中存在一些问题。我建议您将此添加到您的代码中:
import traceback
def handle_exception(exc_type, exc_value, exc_traceback):
print("".join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
sys.exit(1)
if __name__ == '__main__':
sys.excepthook = handle_exception
app = QApplication(sys.argv)
main = Window()
main.show()
sys.exit(app.exec_())
这样,每个会导致您的 window 崩溃的错误都会被打印出来,这样您就可以看到发生了什么。
我得到的第一个错误是:
Traceback (most recent call last):
File "C:/Users/main.py", line 60, in <module>
main = Window()
File "C:/Users/main.py", line 26, in __init__
self.button2.clicked.connect(self.plot2)
AttributeError: 'Window' object has no attribute 'plot2'
在 __init__
方法中,您将一些信号连接到未定义的函数 self.plot2
、self.plot3
等等。
如果我评论这些行,那么我得到:
Traceback (most recent call last):
File "C:/Users/main.py", line 44, in plot1
datafilter['time'] = pd.to_datetime(datafiltr['time'], errors='coerce')
NameError: name 'datafiltr' is not defined
这是 datafilter
中的错字。
修正了这个错字,我得到:
Traceback (most recent call last):
File "C:/Users/main.py", line 45, in plot1
df = datafilter['time'].groupby(datafilter.godzina.dt.to_period("H")).agg('count')
File "C:\Users\VENV\stack\lib\site-packages\pandas\core\generic.py", line 5141, in __getattr__
return object.__getattribute__(self, name)
AttributeError: 'DataFrame' object has no attribute 'godzina'
这是为了解决翻译问题,正如您已经指出的那样:godzina
--> time
.
最后,解决了所有这些问题,我开始工作了 window:
工作代码
import sys
from PyQt5.QtWidgets import QDialog, QApplication, QPushButton, QVBoxLayout
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import pandas as pd
import traceback
class Window(QDialog):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.figure = plt.figure(tight_layout=True)
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas, self)
self.button5 = QPushButton('Lane 5')
self.button4 = QPushButton('Lane 4')
self.button3 = QPushButton('Lane 3')
self.button2 = QPushButton('Lane 2')
self.button1 = QPushButton('Lane 1')
self.button1.clicked.connect(self.plot1)
# self.button2.clicked.connect(self.plot2)
# self.button3.clicked.connect(self.plot3)
# self.button4.clicked.connect(self.plot4)
# self.button5.clicked.connect(self.plot5)
layout = QVBoxLayout()
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
layout.addWidget(self.button1)
layout.addWidget(self.button2)
layout.addWidget(self.button3)
layout.addWidget(self.button4)
layout.addWidget(self.button5)
self.setLayout(layout)
def plot1(self):
data = pd.read_csv("2021-08-13.csv", parse_dates=['time'], infer_datetime_format=True)
datafilter = data[data.lane == "Lane 1 Op2"]
datafilter['time'] = pd.to_datetime(datafilter['time'], errors='coerce')
df = datafilter['time'].groupby(datafilter.time.dt.to_period("H")).agg('count')
y = [df.index[i].to_timestamp() for i in range(len(df))]
self.figure.clear()
ax = self.figure.add_subplot(111)
ax.bar(y, df, width=0.035)
self.canvas.draw()
def handle_exception(exc_type, exc_value, exc_traceback):
print("".join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
sys.exit(1)
if __name__ == '__main__':
sys.excepthook = handle_exception
app = QApplication(sys.argv)
main = Window()
main.show()
sys.exit(app.exec_())
但是我收到警告信息:
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
datafilter['time'] = pd.to_datetime(datafilter['time'], errors='coerce')
我需要帮助为这些图表中的每一个添加实时绘图。我尝试了很多解决方案,但每一个都让我的 window 崩溃。有没有我遗漏的简单修复方法?
下面是没有任何更新方法的代码:
import sys
from PyQt5.QtWidgets import QDialog, QApplication, QPushButton, QVBoxLayout
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import pandas as pd
class Window(QDialog):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.figure = plt.figure(tight_layout=True)
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas, self)
self.button5 = QPushButton('Lane 5')
self.button4 = QPushButton('Lane 4')
self.button3 = QPushButton('Lane 3')
self.button2 = QPushButton('Lane 2')
self.button1 = QPushButton('Lane 1')
self.button1.clicked.connect(self.plot1)
self.button2.clicked.connect(self.plot2)
self.button3.clicked.connect(self.plot3)
self.button4.clicked.connect(self.plot4)
self.button5.clicked.connect(self.plot5)
layout = QVBoxLayout()
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
layout.addWidget(self.button1)
layout.addWidget(self.button2)
layout.addWidget(self.button3)
layout.addWidget(self.button4)
layout.addWidget(self.button5)
self.setLayout(layout)
def plot1(self):
data = pd.read_csv("2021-08-13.csv", parse_dates=['time'], infer_datetime_format=True)
datafilter = data[data.lane == "Lane 1 Op2"]
datafilter['time'] = pd.to_datetime(datafiltr['time'], errors='coerce')
df = datafilter['time'].groupby(datafilter.godzina.dt.to_period("H")).agg('count')
y = [df.index[i].to_timestamp() for i in range(len(df))]
self.figure.clear()
ax = self.figure.add_subplot(111)
ax.bar(y, df, width=0.035)
self.canvas.draw()
if __name__ == '__main__':
app = QApplication(sys.argv)
main = Window()
main.show()
sys.exit(app.exec_())
这里是 csv 文件示例:
lane,detail,time,potentiometer,piece,tooltime
Lane 3 Op3,3584,00:00:03,100%,873,0:00:58
Lane 3 Op2,00:00:20,150,,,
Lane 4 Op3,00:01:40,811,,,
Lane 3 Op1,1584,00:00:20,100%,149,0:01:32
Lane 2 Op2,2508,00:00:40,110%,151,0:01:49
Lane 3 Op1,00:00:34,149,,,
Lane 2 Op3,3508,00:00:56,100%,551,0:01:05
Lane 2 Op2,00:00:25,151,,,
Lane 3 Op3,00:01:07,873,,,
Lane 4 Op2,2858,00:01:31,100%,104,0:02:34
Lane 4 Op3,3858,00:01:32,100%,812,0:01:20
Lane 2 Op1,1508,00:01:33,100%,152,0:01:35
Lane 1 Op1,1141,00:01:38,100%,125,0:01:49
Lane 1 Op2,1141,00:01:38,100%,125,0:01:49
Lane 3 Op2,2584,00:01:51,100%,151,0:01:45
您的代码中存在一些问题。我建议您将此添加到您的代码中:
import traceback
def handle_exception(exc_type, exc_value, exc_traceback):
print("".join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
sys.exit(1)
if __name__ == '__main__':
sys.excepthook = handle_exception
app = QApplication(sys.argv)
main = Window()
main.show()
sys.exit(app.exec_())
这样,每个会导致您的 window 崩溃的错误都会被打印出来,这样您就可以看到发生了什么。
我得到的第一个错误是:
Traceback (most recent call last):
File "C:/Users/main.py", line 60, in <module>
main = Window()
File "C:/Users/main.py", line 26, in __init__
self.button2.clicked.connect(self.plot2)
AttributeError: 'Window' object has no attribute 'plot2'
在 __init__
方法中,您将一些信号连接到未定义的函数 self.plot2
、self.plot3
等等。
如果我评论这些行,那么我得到:
Traceback (most recent call last):
File "C:/Users/main.py", line 44, in plot1
datafilter['time'] = pd.to_datetime(datafiltr['time'], errors='coerce')
NameError: name 'datafiltr' is not defined
这是 datafilter
中的错字。
修正了这个错字,我得到:
Traceback (most recent call last):
File "C:/Users/main.py", line 45, in plot1
df = datafilter['time'].groupby(datafilter.godzina.dt.to_period("H")).agg('count')
File "C:\Users\VENV\stack\lib\site-packages\pandas\core\generic.py", line 5141, in __getattr__
return object.__getattribute__(self, name)
AttributeError: 'DataFrame' object has no attribute 'godzina'
这是为了解决翻译问题,正如您已经指出的那样:godzina
--> time
.
最后,解决了所有这些问题,我开始工作了 window:
工作代码
import sys
from PyQt5.QtWidgets import QDialog, QApplication, QPushButton, QVBoxLayout
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import pandas as pd
import traceback
class Window(QDialog):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.figure = plt.figure(tight_layout=True)
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas, self)
self.button5 = QPushButton('Lane 5')
self.button4 = QPushButton('Lane 4')
self.button3 = QPushButton('Lane 3')
self.button2 = QPushButton('Lane 2')
self.button1 = QPushButton('Lane 1')
self.button1.clicked.connect(self.plot1)
# self.button2.clicked.connect(self.plot2)
# self.button3.clicked.connect(self.plot3)
# self.button4.clicked.connect(self.plot4)
# self.button5.clicked.connect(self.plot5)
layout = QVBoxLayout()
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
layout.addWidget(self.button1)
layout.addWidget(self.button2)
layout.addWidget(self.button3)
layout.addWidget(self.button4)
layout.addWidget(self.button5)
self.setLayout(layout)
def plot1(self):
data = pd.read_csv("2021-08-13.csv", parse_dates=['time'], infer_datetime_format=True)
datafilter = data[data.lane == "Lane 1 Op2"]
datafilter['time'] = pd.to_datetime(datafilter['time'], errors='coerce')
df = datafilter['time'].groupby(datafilter.time.dt.to_period("H")).agg('count')
y = [df.index[i].to_timestamp() for i in range(len(df))]
self.figure.clear()
ax = self.figure.add_subplot(111)
ax.bar(y, df, width=0.035)
self.canvas.draw()
def handle_exception(exc_type, exc_value, exc_traceback):
print("".join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
sys.exit(1)
if __name__ == '__main__':
sys.excepthook = handle_exception
app = QApplication(sys.argv)
main = Window()
main.show()
sys.exit(app.exec_())
但是我收到警告信息:
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
datafilter['time'] = pd.to_datetime(datafilter['time'], errors='coerce')