Проблема с построением matplotlib - PullRequest
0 голосов
/ 12 февраля 2020

В настоящее время я сталкиваюсь с проблемой с matplotlib в сочетании с PyQt5, которую я совсем не понимаю. По сути, я просто хочу построить разные кривые на одном и том же рисунке, вызванные QPushButton. Я воссоздал проблему в минимальном рабочем примере ниже.

Ожидание:

Каждый раз, когда я нажимаю кнопку "сюжет", текущая фигура обновляется новой строкой

Результат:

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

fig = plt.figure()

, то есть каждый раз, когда создается новая фигура, она работает, как и ожидалось. Это ошибка или я как-то ошибся?

Для минимального рабочего примера используются следующие пакеты:

matplotlib==3.1.3
PyQt5==5.14.1
pyqt5-tools==5.13.0.1.5

Пример кода:

import matplotlib.pyplot as plt
import numpy as np
import sys
from PyQt5 import QtWidgets

class MaterialBrowser(QtWidgets.QMainWindow):

    def __init__(self):
        super(MaterialBrowser, self).__init__()
        self.setEnabled(True)
        self.setGeometry(0, 0, 543, 700)
        self.setMinimumSize(543, 400)
        self.save_button = QtWidgets.QPushButton(self)
        self.save_button.setGeometry(100, 100, 110, 32)
        self.save_button.setObjectName("plot_button")
        self.save_button.setText("Plot")
        self.save_button.clicked.connect(self.plot_bhcurve) 
        self.show()

    def plot_bhcurve(self):
        t = np.arange(0.0, 2.0, 0.01)
        omega = np.random.randint(2, 50)
        s = 1 + np.sin(2 * np.pi * omega* t)
        fig = plt.figure(num='MYFIGURE')
        ax = fig.gca()
        ax.plot(t, s, '.-', label=f'mycurve{omega}')
        ax.grid(True, which="both")
        ax.set_xlabel('Field Strength (A/m)')
        ax.set_ylabel('Flux Density (T)')
        ax.set_xlim(left=0)
        ax.set_ylim(bottom=0)
        plt.legend()
        plt.show()

app = QtWidgets.QApplication(sys.argv)
materialbrowser = MaterialBrowser()
sys.exit(app.exec_())

1 Ответ

0 голосов
/ 12 февраля 2020

При интеграции Matplotlib в PyQt вы никогда не должны использовать модуль matplotlib.pyplot, поскольку он создает свое собственное событие и поддерживает список фигур и осей. Он конфликтует с Qt.

. Есть хороший пример того, как встроить Matplotlib в PyQt здесь . Я адаптировал ваш пример на основе этого.

import numpy as np
import sys
from PyQt5 import QtWidgets

from matplotlib.backends.backend_qt5agg import (
    FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure


class MaterialBrowser(QtWidgets.QMainWindow):

    def __init__(self):
        super(MaterialBrowser, self).__init__()
        self.setEnabled(True)
        self.setGeometry(0, 0, 543, 700)
        self.setMinimumSize(543, 400)

        self.main_widget = QtWidgets.QWidget()
        self.setCentralWidget(self.main_widget)

        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_widget.setLayout(self.main_layout)

        self.save_button = QtWidgets.QPushButton(self)
        self.save_button.setGeometry(100, 100, 110, 32)
        self.save_button.setObjectName("plot_button")
        self.save_button.setText("Plot")
        self.save_button.clicked.connect(self.plot_bhcurve) 
        self.main_layout.addWidget(self.save_button)

        self._fig = Figure(figsize=(5, 3))
        self._canvas = FigureCanvas(self._fig)
        self.main_layout.addWidget(self._canvas)

        self._axes = self._fig.subplots()
        self._axes.grid(True, which="both")
        self._axes.set_xlabel('Field Strength (A/m)')
        self._axes.set_ylabel('Flux Density (T)')
        self._axes.set_xlim(left=0)
        self._axes.set_ylim(bottom=0)
        self._axes.legend()

        self.addToolBar(NavigationToolbar(self._canvas, self))

        self.show()



    def plot_bhcurve(self):
        print("plotting")
        t = np.arange(0.0, 2.0, 0.01)
        omega = np.random.randint(2, 50)
        s = 1 + np.sin(2 * np.pi * omega* t)

        self._axes.plot(t, s, '.-', label=f'mycurve{omega}')
        self._canvas.draw()


app = QtWidgets.QApplication(sys.argv)
materialbrowser = MaterialBrowser()
sys.exit(app.exec_())

Кстати, я настоятельно рекомендую использовать макеты Qt для компоновки ваших виджетов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...