如何在 wx.Notebook 中调整多个画布的大小,浮动大小和重叠问题(WxPython、Matplotlib)
How to size multiple canvases in wx.Notebook, issue with float sizes and overlap (WxPython, Matplotlib)
我正在尝试制作一个 wx.Notebook,每个页面上都有一个 FigureCanvas,并且在这些画布中是独一无二的 figures/axes。问题是,如果图形大小(按 fig.set_size_inches)是小数点后 2 位或更多位的浮点数,不同页面上的图形将稍微重叠 。我一辈子都无法理解为什么会发生这种情况以及如何解决它。
要查看重叠问题,您必须切换到选项卡 2,然后返回选项卡 1,重叠出现在第一个图表的底部。
Picture of what I'm talking about
import wx
# Import Matplotlib
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
class MyFrame ( wx.Frame ):
def __init__( self, parent ):
# FORM BUILDER OUTPUT
#########################
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 600,500 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer9 = wx.BoxSizer( wx.VERTICAL )
self.m_notebook2 = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_panel5 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer10 = wx.BoxSizer( wx.VERTICAL )
self.m_panel5.SetSizer( bSizer10 )
self.m_panel5.Layout()
bSizer10.Fit( self.m_panel5 )
self.m_notebook2.AddPage( self.m_panel5, u"Page1", False )
self.m_panel6 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer11 = wx.BoxSizer( wx.VERTICAL )
self.m_panel6.SetSizer( bSizer11 )
self.m_panel6.Layout()
bSizer11.Fit( self.m_panel6 )
self.m_notebook2.AddPage( self.m_panel6, u"Page2", False )
bSizer9.Add( self.m_notebook2, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer9 )
self.Layout()
self.Centre( wx.BOTH )
#########################
graph1 = self.create_graph( self.m_panel5, size=(3, 2.255252) )
graph2 = self.create_graph( self.m_panel6, size=(5.5556, 3.5) )
####################
def create_canvas( self, panel, size ):
fig = Figure()
ax = fig.add_subplot(111)
ax.set_xlim([0,10])
ax.set_ylim([0,100])
ax.axis('off')
fig.set_size_inches( size ) # If this is a float to 3 decimals is causes problems
canvas = FigureCanvas(panel, -1, fig)
sizer = panel.GetSizer()
sizer.Add(canvas)
return(canvas)
def create_graph( self, panel, size ):
canvas = self.create_canvas(panel,size)
ax = canvas.figure.axes[0]
xdata = range(1,10)
ydata = [x*x for x in xdata]
ax.scatter( xdata, ydata )
ax.bar( xdata, [100]*9, 0.5, 0, color='red' )
ax.plot()
return(ax)
class MyApp(wx.App):
def OnInit(self):
main = MyFrame(None)
main.Show()
return True
app = MyApp(0)
app.MainLoop()
print('Done')
已尝试 Windows (wxPython 2.9.5.1/mpl 1.3.1) 上的代码并得到相同的结果(第一个图底部的红色标记)。
我会以不同的方式解决这个问题,并指定绘图的大小,而不是在 matplotlib 中,而是在 wxPython 中。
修改代码时如下:
def __init__( self, parent ):
...
graph2 = self.create_graph(#...
self.Layout() # put this at the end
def create_canvas( self, panel, size ): # size can be omitted
fig = Figure(dpi=96) # specify the dpi instead of the size
...
# comment this out
# fig.set_size_inches( size )
一切都画得很好,尺寸也更合理。
编辑:问题出现了如何为 mpl canvas 设置固定的宽高比而不具体指定以英寸为单位的尺寸。添加到 sizer 并写入
时,您可以使用 wx.SHAPED
标志而不是 wx.EXPAND
bSizer9.Add( self.m_notebook2, 1, wx.SHAPED |wx.ALL, 5 )
这将保持 __init__
中绘制的纵横比。
一种解决方法是在页面之间切换时调用页面的 Layout() 方法。这是一个对我有用的例子 Windows 7 with wxPython 3 and Python 2.7:
import wx
# Import Matplotlib
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
class MyFrame ( wx.Frame ):
def __init__( self, parent ):
# FORM BUILDER OUTPUT
#########################
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 600,500 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer9 = wx.BoxSizer( wx.VERTICAL )
self.m_notebook2 = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_notebook2.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onPageChanged)
self.m_panel5 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer10 = wx.BoxSizer( wx.VERTICAL )
self.m_panel5.SetSizer( bSizer10 )
self.m_panel5.Layout()
bSizer10.Fit( self.m_panel5 )
self.m_notebook2.AddPage( self.m_panel5, u"Page1", False )
self.m_panel6 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer11 = wx.BoxSizer( wx.VERTICAL )
self.m_panel6.SetSizer( bSizer11 )
self.m_panel6.Layout()
bSizer11.Fit( self.m_panel6 )
self.m_notebook2.AddPage( self.m_panel6, u"Page2", False )
bSizer9.Add( self.m_notebook2, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer9 )
self.Layout()
self.Centre( wx.BOTH )
#########################
graph1 = self.create_graph( self.m_panel5, size=(3, 2.255252) )
graph2 = self.create_graph( self.m_panel6, size=(5.5556, 3.5) )
####################
def create_canvas( self, panel, size ):
fig = Figure()
ax = fig.add_subplot(111)
ax.set_xlim([0,10])
ax.set_ylim([0,100])
ax.axis('off')
fig.set_size_inches( size ) # If this is a float to 3 decimals is causes problems
canvas = FigureCanvas(panel, -1, fig)
sizer = panel.GetSizer()
sizer.Add(canvas)
return(canvas)
def create_graph( self, panel, size ):
canvas = self.create_canvas(panel,size)
ax = canvas.figure.axes[0]
xdata = range(1,10)
ydata = [x*x for x in xdata]
ax.scatter( xdata, ydata )
ax.bar( xdata, [100]*9, 0.5, 0, color='red' )
ax.plot()
return(ax)
def onPageChanged(self, event):
self.m_panel5.Layout()
self.m_panel6.Layout()
class MyApp(wx.App):
def OnInit(self):
main = MyFrame(None)
main.Show()
return True
app = MyApp(0)
app.MainLoop()
我正在尝试制作一个 wx.Notebook,每个页面上都有一个 FigureCanvas,并且在这些画布中是独一无二的 figures/axes。问题是,如果图形大小(按 fig.set_size_inches)是小数点后 2 位或更多位的浮点数,不同页面上的图形将稍微重叠 。我一辈子都无法理解为什么会发生这种情况以及如何解决它。
要查看重叠问题,您必须切换到选项卡 2,然后返回选项卡 1,重叠出现在第一个图表的底部。
Picture of what I'm talking about
import wx
# Import Matplotlib
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
class MyFrame ( wx.Frame ):
def __init__( self, parent ):
# FORM BUILDER OUTPUT
#########################
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 600,500 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer9 = wx.BoxSizer( wx.VERTICAL )
self.m_notebook2 = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_panel5 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer10 = wx.BoxSizer( wx.VERTICAL )
self.m_panel5.SetSizer( bSizer10 )
self.m_panel5.Layout()
bSizer10.Fit( self.m_panel5 )
self.m_notebook2.AddPage( self.m_panel5, u"Page1", False )
self.m_panel6 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer11 = wx.BoxSizer( wx.VERTICAL )
self.m_panel6.SetSizer( bSizer11 )
self.m_panel6.Layout()
bSizer11.Fit( self.m_panel6 )
self.m_notebook2.AddPage( self.m_panel6, u"Page2", False )
bSizer9.Add( self.m_notebook2, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer9 )
self.Layout()
self.Centre( wx.BOTH )
#########################
graph1 = self.create_graph( self.m_panel5, size=(3, 2.255252) )
graph2 = self.create_graph( self.m_panel6, size=(5.5556, 3.5) )
####################
def create_canvas( self, panel, size ):
fig = Figure()
ax = fig.add_subplot(111)
ax.set_xlim([0,10])
ax.set_ylim([0,100])
ax.axis('off')
fig.set_size_inches( size ) # If this is a float to 3 decimals is causes problems
canvas = FigureCanvas(panel, -1, fig)
sizer = panel.GetSizer()
sizer.Add(canvas)
return(canvas)
def create_graph( self, panel, size ):
canvas = self.create_canvas(panel,size)
ax = canvas.figure.axes[0]
xdata = range(1,10)
ydata = [x*x for x in xdata]
ax.scatter( xdata, ydata )
ax.bar( xdata, [100]*9, 0.5, 0, color='red' )
ax.plot()
return(ax)
class MyApp(wx.App):
def OnInit(self):
main = MyFrame(None)
main.Show()
return True
app = MyApp(0)
app.MainLoop()
print('Done')
已尝试 Windows (wxPython 2.9.5.1/mpl 1.3.1) 上的代码并得到相同的结果(第一个图底部的红色标记)。
我会以不同的方式解决这个问题,并指定绘图的大小,而不是在 matplotlib 中,而是在 wxPython 中。
修改代码时如下:
def __init__( self, parent ):
...
graph2 = self.create_graph(#...
self.Layout() # put this at the end
def create_canvas( self, panel, size ): # size can be omitted
fig = Figure(dpi=96) # specify the dpi instead of the size
...
# comment this out
# fig.set_size_inches( size )
一切都画得很好,尺寸也更合理。
编辑:问题出现了如何为 mpl canvas 设置固定的宽高比而不具体指定以英寸为单位的尺寸。添加到 sizer 并写入
时,您可以使用wx.SHAPED
标志而不是 wx.EXPAND
bSizer9.Add( self.m_notebook2, 1, wx.SHAPED |wx.ALL, 5 )
这将保持 __init__
中绘制的纵横比。
一种解决方法是在页面之间切换时调用页面的 Layout() 方法。这是一个对我有用的例子 Windows 7 with wxPython 3 and Python 2.7:
import wx
# Import Matplotlib
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
class MyFrame ( wx.Frame ):
def __init__( self, parent ):
# FORM BUILDER OUTPUT
#########################
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 600,500 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer9 = wx.BoxSizer( wx.VERTICAL )
self.m_notebook2 = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_notebook2.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onPageChanged)
self.m_panel5 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer10 = wx.BoxSizer( wx.VERTICAL )
self.m_panel5.SetSizer( bSizer10 )
self.m_panel5.Layout()
bSizer10.Fit( self.m_panel5 )
self.m_notebook2.AddPage( self.m_panel5, u"Page1", False )
self.m_panel6 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
bSizer11 = wx.BoxSizer( wx.VERTICAL )
self.m_panel6.SetSizer( bSizer11 )
self.m_panel6.Layout()
bSizer11.Fit( self.m_panel6 )
self.m_notebook2.AddPage( self.m_panel6, u"Page2", False )
bSizer9.Add( self.m_notebook2, 1, wx.EXPAND |wx.ALL, 5 )
self.SetSizer( bSizer9 )
self.Layout()
self.Centre( wx.BOTH )
#########################
graph1 = self.create_graph( self.m_panel5, size=(3, 2.255252) )
graph2 = self.create_graph( self.m_panel6, size=(5.5556, 3.5) )
####################
def create_canvas( self, panel, size ):
fig = Figure()
ax = fig.add_subplot(111)
ax.set_xlim([0,10])
ax.set_ylim([0,100])
ax.axis('off')
fig.set_size_inches( size ) # If this is a float to 3 decimals is causes problems
canvas = FigureCanvas(panel, -1, fig)
sizer = panel.GetSizer()
sizer.Add(canvas)
return(canvas)
def create_graph( self, panel, size ):
canvas = self.create_canvas(panel,size)
ax = canvas.figure.axes[0]
xdata = range(1,10)
ydata = [x*x for x in xdata]
ax.scatter( xdata, ydata )
ax.bar( xdata, [100]*9, 0.5, 0, color='red' )
ax.plot()
return(ax)
def onPageChanged(self, event):
self.m_panel5.Layout()
self.m_panel6.Layout()
class MyApp(wx.App):
def OnInit(self):
main = MyFrame(None)
main.Show()
return True
app = MyApp(0)
app.MainLoop()