【发布时间】:2016-03-31 20:08:17
【问题描述】:
我正在使用 pyside 和 matplotlib 编写一个 python 应用程序。在this tutorial 和this SO post 的组合之后,我创建了一个可以成功添加到父级的matplotlib 小部件。但是,当我实际向其中添加数据时,似乎什么都没有显示。
如果我像 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)
编辑:我怀疑更新情节限制存在问题。运行上述代码时,绘图以 x 和 y 轴上的 0 和 1 的限制打开。由于我生成的数据都不属于该范围,因此我创建了另一个 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方法中。 -
@tcaswell 我尝试将它添加到函数的末尾,但它似乎没有改变任何东西。
-
我错过了你打电话给
update_datalim,这是一个内部函数,不要那样做。请。 -
@tcaswell 你确定这是一个内部函数吗? documentation for
add_artist特别提到调用update_datalim
标签: matplotlib pyside