Я пишу приложение python, используя pyside и matplotlib. После комбинации this tutorial и this SO post, я создал виджет matplotlib, который я могу успешно добавить к родительскому. Однако, когда я собираюсь фактически добавлять данные к нему, ничего не отображается.Динамический виджет mplotlib pyside не отображается
Если я добавляю статические данные, такие как сообщение SO, оно появляется, но когда я меняю его на обновление «на лету» (в настоящее время каждую секунду на таймере, но в конечном итоге он будет использовать сигнал другого класса) Я никогда не получаю ничего, кроме пустых осей. Я подозреваю, что мне не хватает вызова, чтобы заставить ничью или сделать недействительным или что что-то не так с тем, как я вызываю update_datalim (хотя значения, которые передаются ему, кажутся правильными).
from PySide import QtCore, QtGui
import matplotlib
import random
matplotlib.use('Qt4Agg')
matplotlib.rcParams['backend.qt4']='PySide'
from matplotlib import pyplot as plt
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.patches import Rectangle
from collections import namedtuple
DataModel = namedtuple('DataModel', ['start_x', 'start_y', 'width', 'height'])
class BaseWidget(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
# We want the axes cleared every time plot() is called
self.axes.hold(False)
self.axes.set_xlabel('X Label')
self.axes.set_ylabel('Y Label')
self.axes.set_title('My Data')
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
class DynamicWidget(BaseWidget):
def set_data(self, the_data):
self.axes.clear()
xys = list()
cmap = plt.cm.hot
for datum in the_data:
bottom_left = (datum.start_x, datum.start_y)
top_right = (bottom_left[0] + datum.width, bottom_left[1] + datum.height)
rect = Rectangle(
xy=bottom_left,
width=datum.width, height=datum.height, color=cmap(100)
)
xys.append(bottom_left)
xys.append(top_right)
self.axes.add_artist(rect)
self.axes.update_datalim(xys)
self.axes.figure.canvas.draw_idle()
class RandomDataWidget(DynamicWidget):
def __init__(self, *args, **kwargs):
DynamicWidget.__init__(self, *args, **kwargs)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.generate_and_set_data)
timer.start(1000)
def generate_and_set_data(self):
fake_data = [DataModel(
start_x=random.randint(1, 100),
width=random.randint(20, 40),
start_y=random.randint(80, 160),
height=random.randint(20, 90)
) for i in range(100)]
self.set_data(fake_data)
Edit: Я подозревал, что существует проблема с обновлением пределы участка. При запуске вышеуказанного кода график открывается с пределами 0 и 1 на оси x и y. Поскольку ни один из моих сгенерированных данных не попадает в этот диапазон, я создал другой подкласс DynamicWidget
, который отображает только данные между 0 и 1 (те же данные из связанного сообщения SO). При создании экземпляра класса ниже данные отображаются успешно. Нужно ли мне делать что-то большее, чем позвонить update_datalim
, чтобы получить график, чтобы снова привязать себя?
class StaticWidget(DynamicWidget):
def __init__(self):
DynamicWidget.__init__(self)
static_data = [
DataModel(0.5, 0.05, 0.2, 0.05),
DataModel(0.1, 0.2, 0.7, 0.2),
DataModel(0.3, 0.1, 0.8, 0.1)
]
self.set_data(static_data)
добавить 'self.axes.figure.canvas.draw_idle()' в ваш 'set_data' метод. – tacaswell
@tcaswell Я попытался добавить его в конец функции, но, похоже, ничего не изменил. –
Я пропустил, что вы вызывали 'update_datalim', это внутренняя функция, не делайте этого. Пожалуйста. – tacaswell