wxpython:动态情节 - 无法在情节中显示第二行

时间:2013-12-17 12:38:34

标签: python python-2.7 numpy matplotlib plot

我发现这篇非常好的文章:

我已成功编辑并将其放入我的代码并且工作正常,但我的问题是我无法在绘图中显示多行数据,我想在我的图表中显示多达10行但我是我尝试添加它们时会遇到很多错误。

我在这里给你eli的示例代码但是我的更改。在这段代码中,我尝试只显示2行,我不知道为什么我会发现这个错误。 (RuntimeError:xdata和ydata的长度必须相同)

import os
import pprint
import random
import sys
import wx

import matplotlib
matplotlib.use('WXAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import \
    FigureCanvasWxAgg as FigCanvas, \
    NavigationToolbar2WxAgg as NavigationToolbar
import numpy as np
import pylab

class DataGen(object):
def __init__(self, init = 50):
    self.data = self.init = init
    self.data2 = self.init = init

def next(self):
    self._recalc_data()
    return self.data , self.data2,

def _recalc_data(self):
    delta = random.uniform(-0.5, 0.5)
    r = random.random()

    if r > 0.9:
        self.data += delta * 15
        self.data2 += delta * 15
    elif r > 0.8: 
        # attraction to the initial value
        delta += (0.5 if self.init > self.data else -0.5)
        self.data += delta
        delta += (0.5 if self.init > self.data2 else -0.5)
        self.data2 += delta
    else:
        self.data += delta
        self.data2 += delta

class BoundControlBox(wx.Panel):
def __init__(self, parent, ID, label, initval):
    wx.Panel.__init__(self, parent, ID)

    self.value = initval

    box = wx.StaticBox(self, -1, label)
    sizer = wx.StaticBoxSizer(box, wx.VERTICAL)

    self.radio_auto = wx.RadioButton(self, -1,
        label="Auto", style=wx.RB_GROUP)
    self.radio_manual = wx.RadioButton(self, -1,
        label="Manual")
    self.manual_text = wx.TextCtrl(self, -1,
        size=(35,-1),
        value=str(initval),
        style=wx.TE_PROCESS_ENTER)

    self.Bind(wx.EVT_UPDATE_UI, self.on_update_manual_text, self.manual_text)
    self.Bind(wx.EVT_TEXT_ENTER, self.on_text_enter, self.manual_text)

    manual_box = wx.BoxSizer(wx.HORIZONTAL)
    manual_box.Add(self.radio_manual, flag=wx.ALIGN_CENTER_VERTICAL)
    manual_box.Add(self.manual_text, flag=wx.ALIGN_CENTER_VERTICAL)

    sizer.Add(self.radio_auto, 0, wx.ALL, 10)
    sizer.Add(manual_box, 0, wx.ALL, 10)

    self.SetSizer(sizer)
    sizer.Fit(self)

def on_update_manual_text(self, event):
    self.manual_text.Enable(self.radio_manual.GetValue())

def on_text_enter(self, event):
    self.value = self.manual_text.GetValue()

def is_auto(self):
    return self.radio_auto.GetValue()

def manual_value(self):
    return self.value


class GraphFrame(wx.Frame):
title = 'Monitor'

def __init__(self):
    wx.Frame.__init__(self, None, -1, self.title)

    self.datagen = DataGen()
    self.data = [self.datagen.next()]
    self.data2 = [self.datagen.next()]
    self.paused = False

    self.create_menu()
    self.create_status_bar()
    self.create_main_panel()

    self.redraw_timer = wx.Timer(self)
    self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer)
    self.redraw_timer.Start(100)

def create_menu(self):
    self.menubar = wx.MenuBar()

    menu_file = wx.Menu()
    m_expt = menu_file.Append(-1, "&Save plot\tCtrl-S", "Save plot to file")
    self.Bind(wx.EVT_MENU, self.on_save_plot, m_expt)
    menu_file.AppendSeparator()
    m_exit = menu_file.Append(-1, "E&xit\tCtrl-X", "Exit")
    self.Bind(wx.EVT_MENU, self.on_exit, m_exit)

    self.menubar.Append(menu_file, "&File")
    self.SetMenuBar(self.menubar)

def create_main_panel(self):
    self.panel = wx.Panel(self)

    self.init_plot()
    self.canvas = FigCanvas(self.panel, -1, self.fig)

    self.xmin_control = BoundControlBox(self.panel, -1, "X min", 0)
    self.xmax_control = BoundControlBox(self.panel, -1, "X max", 50)
    self.ymin_control = BoundControlBox(self.panel, -1, "Y min", 0)
    self.ymax_control = BoundControlBox(self.panel, -1, "Y max", 100)

    self.pause_button = wx.Button(self.panel, -1, "Pause")
    self.Bind(wx.EVT_BUTTON, self.on_pause_button, self.pause_button)
    self.Bind(wx.EVT_UPDATE_UI, self.on_update_pause_button, self.pause_button)

    self.cb_grid = wx.CheckBox(self.panel, -1,
        "Show Grid",
        style=wx.ALIGN_RIGHT)
    self.Bind(wx.EVT_CHECKBOX, self.on_cb_grid, self.cb_grid)
    self.cb_grid.SetValue(True)

    self.cb_xlab = wx.CheckBox(self.panel, -1,
        "Show X labels",
        style=wx.ALIGN_RIGHT)
    self.Bind(wx.EVT_CHECKBOX, self.on_cb_xlab, self.cb_xlab)
    self.cb_xlab.SetValue(True)

    self.hbox1 = wx.BoxSizer(wx.HORIZONTAL)
    self.hbox1.Add(self.pause_button, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)
    self.hbox1.AddSpacer(20)
    self.hbox1.Add(self.cb_grid, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)
    self.hbox1.AddSpacer(10)
    self.hbox1.Add(self.cb_xlab, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)

    self.hbox2 = wx.BoxSizer(wx.HORIZONTAL)
    self.hbox2.Add(self.xmin_control, border=5, flag=wx.ALL)
    self.hbox2.Add(self.xmax_control, border=5, flag=wx.ALL)
    self.hbox2.AddSpacer(24)
    self.hbox2.Add(self.ymin_control, border=5, flag=wx.ALL)
    self.hbox2.Add(self.ymax_control, border=5, flag=wx.ALL)

    self.vbox = wx.BoxSizer(wx.VERTICAL)
    self.vbox.Add(self.canvas, 1, flag=wx.LEFT | wx.TOP | wx.GROW)
    self.vbox.Add(self.hbox1, 0, flag=wx.ALIGN_LEFT | wx.TOP)
    self.vbox.Add(self.hbox2, 0, flag=wx.ALIGN_LEFT | wx.TOP)

    self.panel.SetSizer(self.vbox)
    self.vbox.Fit(self)

def create_status_bar(self):
    self.statusbar = self.CreateStatusBar()

def init_plot(self):
    self.dpi = 100
    self.fig = Figure((3.0, 3.0), dpi=self.dpi)

    self.axes = self.fig.add_subplot(111)
    self.axes.set_axis_bgcolor('black')
    self.axes.set_title('Random Data', size=12)

    pylab.setp(self.axes.get_xticklabels(), fontsize=8)
    pylab.setp(self.axes.get_yticklabels(), fontsize=8)

    self.plot_data = self.axes.plot(self.data, linewidth=1,color = 'red',)[0]
    self.plot_data2 = self.axes.plot(self.data2, linewidth=1,color = 'white',)[0]

    self.axes.legend( (self.data, self.data2),
        (u'Data 1', u'Data 2',),
        'upper right', fontsize=6)


def draw_plot(self):
    """ Redraws the plot
    """
    # when xmin is on auto, it "follows" xmax to produce a 
    # sliding window effect. therefore, xmin is assigned after
    # xmax.
    #  
    if self.xmax_control.is_auto():
        xmax = len(self.data) if len(self.data) > 50 else 50
    else:
        xmax = int(self.xmax_control.manual_value())

    if self.xmin_control.is_auto():
        xmin = xmax - 50
    else:
        xmin = int(self.xmin_control.manual_value())
    # for ymin and ymax, find the minimal and maximal values
    # in the data set and add a mininal margin.
    # 
    # note that it's easy to change this scheme to the 
    # minimal/maximal value in the current display, and not
    # the whole data set.
    # 
    if self.ymin_control.is_auto():
        #ymin = round(min(self.data), 0) - 1
        ymin = 0
    else:
        ymin = int(self.ymin_control.manual_value())

    if self.ymax_control.is_auto():
        #ymax = round(max(self.data), 0) + 1
        ymax = 100
    else:
        ymax = int(self.ymax_control.manual_value())

    self.axes.set_xbound(lower=xmin, upper=xmax)
    self.axes.set_ybound(lower=ymin, upper=ymax)

    #
    if self.cb_grid.IsChecked():
        self.axes.grid(True, color='gray')
    else:
        self.axes.grid(False)

    # Using setp here is convenient, because get_xticklabels
    # returns a list over which one needs to explicitly 
    # iterate, and setp already handles this.
    #   
    pylab.setp(self.axes.get_xticklabels(),
        visible=self.cb_xlab.IsChecked())
    pylab.setp(self.axes.get_legend(),
        visible=self.cb_xlab.IsChecked())

    self.plot_data.set_xdata(np.arange(len(self.data)))
    self.plot_data.set_ydata(np.array(self.data))
    self.plot_data.set_xdata(np.arange(len(self.data)))
    self.plot_data.set_ydata(np.array(self.data2))
    self.canvas.draw()

def on_pause_button(self, event):
    self.paused = not self.paused

def on_update_pause_button(self, event):
    label = "Resume" if self.paused else "Pause"
    self.pause_button.SetLabel(label)

def on_cb_grid(self, event):
    self.draw_plot()

def on_cb_xlab(self, event):
    self.draw_plot()

def on_save_plot(self, event):
    file_choices = "PNG (*.png)|*.png"

    dlg = wx.FileDialog(
        self,
        message="Save plot as...",
        defaultDir=os.getcwd(),
        defaultFile="plot.png",
        wildcard=file_choices,
        style=wx.SAVE)

    if dlg.ShowModal() == wx.ID_OK:
        path = dlg.GetPath()
        self.canvas.print_figure(path, dpi=self.dpi)
        self.flash_status_message("Saved to %s" % path)

def on_redraw_timer(self, event):
    # 
    if not self.paused:
        self.data.append(self.datagen.next())
        self.data2.append(self.datagen.next())



    self.draw_plot()

def on_exit(self, event):
    self.Destroy()

def flash_status_message(self, msg, flash_len_ms=1500):
    self.statusbar.SetStatusText(msg)
    self.timeroff = wx.Timer(self)
    self.Bind(
        wx.EVT_TIMER,
        self.on_flash_status_off,
        self.timeroff)
    self.timeroff.Start(flash_len_ms, oneShot=True)

def on_flash_status_off(self, event):
    self.statusbar.SetStatusText('')


if __name__ == '__main__':
app = wx.PySimpleApp()
app.frame = GraphFrame()
app.frame.Show()
app.MainLoop()

如果我删除了我的更改,代码工作正常!

Traceback (most recent call last):
  File "C:\..\..\..\Copy.py", line 285, in on_redraw_timer
    self.draw_plot()
  File "C:\..\..\..\Copy.py", line 246, in draw_plot
    self.canvas.draw()
  File "C:\Python27\lib\site-packages\matplotlib\backends\backend_wxagg.py", line 44, in draw
    FigureCanvasAgg.draw(self)
  File "C:\Python27\lib\site-packages\matplotlib\backends\backend_agg.py", line 451, in draw
    self.figure.draw(self.renderer)
  File "C:\Python27\lib\site-packages\matplotlib\artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Python27\lib\site-packages\matplotlib\figure.py", line 1034, in draw
    func(*args)
  File "C:\Python27\lib\site-packages\matplotlib\artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Python27\lib\site-packages\matplotlib\axes.py", line 2086, in draw
    a.draw(renderer)
  File "C:\Python27\lib\site-packages\matplotlib\artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Python27\lib\site-packages\matplotlib\lines.py", line 512, in draw
    self.recache()
  File "C:\Python27\lib\site-packages\matplotlib\lines.py", line 440, in recache
    raise RuntimeError('xdata and ydata must be the same length')
RuntimeError: xdata and ydata must be the same length

0 个答案:

没有答案