@DraksPlay

Почему график в PYQT5 с matploblib обновляется на последней итерации?

График должен обновляться каждую итерацию, но изменения появляются только на последней итерации

Вот код
# importing various libraries
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 random


# main window
# which inherits QDialog
class Window(QDialog):

    # constructor
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        # a figure instance to plot on
        self.figure = plt.figure()

        # this is the Canvas Widget that
        # displays the 'figure'it takes the
        # 'figure' instance as a parameter to __init__
        self.canvas = FigureCanvas(self.figure)

        # this is the Navigation widget
        # it takes the Canvas widget and a parent
        self.toolbar = NavigationToolbar(self.canvas, self)

        # Just some button connected to 'plot' method
        self.button = QPushButton('Plot')

        # adding action to the button
        self.button.clicked.connect(self.plot)

        # creating a Vertical Box layout
        layout = QVBoxLayout()

        # adding tool bar to the layout
        layout.addWidget(self.toolbar)

        # adding canvas to the layout
        layout.addWidget(self.canvas)

        # adding push button to the layout
        layout.addWidget(self.button)

        # setting layout to the main window
        self.setLayout(layout)

    # action called by the push button
    def plot(self):
        # random data
        for _ in range(10):
            data = [random.random() for i in range(10)]

            # clearing old figure
            self.figure.clear()

            # create an axis
            ax = self.figure.add_subplot(111)

            # plot data
            ax.plot(data, '*-')

            # refresh canvas
            self.canvas.draw()


# driver code
if __name__ == '__main__':
    # creating apyqt5 application
    app = QApplication(sys.argv)

    # creating a window object
    main = Window()

    # showing the window
    main.show()

    # loop
    sys.exit(app.exec_())
  • Вопрос задан
  • 204 просмотра
Пригласить эксперта
Ответы на вопрос 1
@5465
Проблема заключается в том, что при каждом нажатии на кнопку график создается заново и перерисовывается, а не обновляется. В данном случае вам нужно создать график только один раз и использовать его для обновления данных.

Для этого вы можете создать экземпляр ax один раз при создании окна, а затем использовать его для обновления графика при каждом нажатии на кнопку. Также вам необходимо сохранять ссылку на список линий графика, чтобы вы могли обновлять их данные в дальнейшем.

Вот обновленный код, который реализует эти изменения:

# importing various libraries
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 random


# main window
# which inherits QDialog
class Window(QDialog):

    # constructor
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        # a figure instance to plot on
        self.figure = plt.figure()

        # create an axis
        self.ax = self.figure.add_subplot(111)

        # create a list of lines
        self.lines = []

        # this is the Canvas Widget that
        # displays the 'figure'it takes the
        # 'figure' instance as a parameter to __init__
        self.canvas = FigureCanvas(self.figure)

        # this is the Navigation widget
        # it takes the Canvas widget and a parent
        self.toolbar = NavigationToolbar(self.canvas, self)

        # Just some button connected to 'plot' method
        self.button = QPushButton('Plot')

        # adding action to the button
        self.button.clicked.connect(self.plot)

        # creating a Vertical Box layout
        layout = QVBoxLayout()

        # adding tool bar to the layout
        layout.addWidget(self.toolbar)

        # adding canvas to the layout
        layout.addWidget(self.canvas)

        # adding push button to the layout
        layout.addWidget(self.button)

        # setting layout to the main window
        self.setLayout(layout)

    # action called by the push button
    def plot(self):
        # random data
        data = [random.random() for i in range(10)]

        # create a line
        line, = self.ax.plot(data, '*-')

        # add line to the list
        self.lines.append(line)

        # set data for each line
        for line in self.lines:
            line.set_ydata(data)

        # set the y limits of the axis to fit the data
        ymin, ymax = min(data), max(data)
        self.ax.set_ylim(ymin - 0.1, ymax + 0.1)

        # refresh canvas
        self.canvas.draw()


# driver code
if __name__ == '__main__':
    # creating apyqt5 application
    app = QApplication(sys.argv)

    # creating a window object
    main = Window()

    # showing the window
    main.show()

    # loop
    sys.exit(app.exec_())


Здесь мы создаем список self.lines для хранения ссылок на линии графика. В методе plot мы создаем новый график, добавляем его в список и устанавливаем данные для линий в соответствии с новыми данными, переданными в метод. Затем мы перерисовываем канву, чтобы отобразить новые данные.

В итоге, весь код класса Window должен выглядеть так:

class Window(QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)

        self.button = QPushButton('Plot')
        self.button.clicked.connect(self.plot)

        layout = QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        layout.addWidget(self.button)

        self.setLayout(layout)

        # список для хранения ссылок на линии графика
        self.lines = []

    def plot(self):
        for _ in range(10):
            data = [random.random() for i in range(10)]

            # если линия графика уже существует, обновляем её данные
            if len(self.lines) > 0:
                line = self.lines.pop(0)
                line.set_data(range(len(data)), data)
            # иначе создаем новую линию графика
            else:
                line, = self.canvas.ax.plot(range(len(data)), data, '*-')
                self.lines.append(line)

        # перерисовываем канву, чтобы отобразить новые данные
        self.canvas.draw()


Теперь при нажатии на кнопку график будет обновляться на каждой итерации.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы