该死的,这比它需要的更难。这是一个独立的示例。
(我已经创建了一个repository,代码更好)。
import wx
import matplotlib.backends.backend_wxagg
import matplotlib.pyplot
import matplotlib.figure
import numpy
data = [
[
["Arse", 5],
["Genitals", 12],
["Bum", 2]
],
[
["Fart", 3],
["Guff", 2],
["EXPLOSION", 6]
],
[
["Clam", 2],
["Stench trench", 7],
["Axe wound", 3],
["Fourth euphemism", 9]
]
]
class panel_plot(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, style = wx.NO_FULL_REPAINT_ON_RESIZE)
self.figure = matplotlib.figure.Figure()
self.canvas = matplotlib.backends.backend_wxagg.FigureCanvasWxAgg(self, -1, self.figure)
self.set_size()
self.draw()
self._resize_flag = False
self.Bind(wx.EVT_IDLE, self.on_idle)
self.Bind(wx.EVT_SIZE, self.on_size)
def on_idle(self, event):
if self._resize_flag:
self._resize_flag = False
self.set_size()
def on_size(self, event):
self._resize_flag = True
def set_size(self):
pixels = tuple(self.GetSize())
self.SetSize(pixels)
self.canvas.SetSize(pixels)
self.figure.set_size_inches([float(x) / self.figure.get_dpi() for x in pixels])
def draw(self):
self.canvas.draw()
class frame_main ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
sizer_bg = wx.BoxSizer( wx.VERTICAL )
self.panel_bg = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
sizer_main = wx.BoxSizer( wx.VERTICAL )
self.button_change = wx.Button( self.panel_bg, wx.ID_ANY, u"Change data", wx.DefaultPosition, wx.DefaultSize, 0 )
sizer_main.Add( self.button_change, 0, wx.ALL, 5 )
self.panel_matplotlib = panel_plot(self.panel_bg)
sizer_main.Add( self.panel_matplotlib, 1, wx.EXPAND |wx.ALL, 5 )
self.panel_bg.SetSizer( sizer_main )
self.panel_bg.Layout()
sizer_main.Fit( self.panel_bg )
sizer_bg.Add( self.panel_bg, 1, wx.EXPAND, 5 )
self.SetSizer( sizer_bg )
self.Layout()
self.i = 0
self.on_change()
self.setbinds()
def setbinds(self):
self.button_change.Bind(wx.EVT_BUTTON, self.on_change)
def on_change(self, event = None):
self.panel_matplotlib.figure.clf()
axes = self.panel_matplotlib.figure.gca()
self.i += 1
_data = numpy.array(data[self.i%3])
datapoints = numpy.array(range(len(_data)))
values = numpy.array([int(x[1]) for x in _data])
labelpositions = numpy.array([x + 0.4 for x in range(len(_data))])
labeltext = numpy.array([x[0] for x in _data])
axes.barh(datapoints, values)
axes.set_yticks(labelpositions)
axes.set_yticklabels(labeltext)
self.panel_matplotlib.draw()
class App(wx.App):
def __init__(self):
super(App, self).__init__()
self.mainframe = frame_main(None)
self.mainframe.Show()
self.MainLoop()
App()
考虑到我来源的文章没有管理的关键点:
- 一切都必须是
numpy 数组。 matplotlib 习惯于在arraylikes 上使用+ 运算符,而对于python 列表,这只是一个扩展。
- 看起来 matplotlib.pyplot 中的所有 dank 函数也在
axes 上,即 matplotlib.figure.Figure().gca()。
-
axes.set_yticks() 需要在.set_yticklabels 之前完成,以便标签的位置正确。
-
super(panel_plot, self).__init__(...) 似乎不起作用,没有立即明显的原因。
- 在
panel_plot.set_size() 中,第一行需要包含self.GetSize(),不是 self.Parent.GetClientSize()。 GetClientSize() 有点过大;我认为它计算了可绘制区域和边框。
这些是我拼凑的文章: