如何告诉 wxpython 将文本控件添加到正确的 sizer
How to tell wxpython to add a text control to the right sizer
在下面的代码中,我尝试将新的文本控件动态添加到 sizer。我有两个 sizer,一个在左边 ("sizer"),一个在右边 ("sizer2")。有一个名为 "add_region" 的函数,它应该将新的文本控件添加到右侧的 sizer (sizer2)。
我已将此功能绑定到按钮 "button_add"。
当我直接从代码主体(行:self.add_region(0)
)调用函数 add_region 时,文本控件会根据需要添加到 sizer2。然而,通过点击按钮调用相同的函数,文本控件被放置在不同的 sizer 中(大概是 "sizer")。
为什么文本控件的位置取决于调用函数的方式?
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#This is a good tutorial: http://wiki.wxpython.org/wxPython%20by%20Example
import wx
import wx.lib.scrolledpanel
class region():
#variables associated with the entire class (not each object)
nreg=0
def __init__(self,Ani=999.0e29,AZ=9.99):
self.Ani=Ani
self.AZ=AZ
# self.text_Ani
region.nreg+=1
class MainWindow(wx.Frame): #A "frame" is what we normally think of as a window, so we have called it MainWindow
def __init__(self, parent, title):
super( MainWindow, self).__init__(parent, title=title, size=(450, 350) )
self.dirname = ''
self.ibox=0
self.iv=0 #the vertical depth on the LHS
self.iw=0 #the vertical depth on the RHS
self.Aregion_objects=[]
self.Ani=[] #array of ion number densities
self.AZ=[]
self.Axmin=[]
self.Axmax=[]
self.Aymin=[]
self.Aymax=[]
self.text_Ani=[]
self.tc_Ani=[]
self.sizer = wx.GridBagSizer(5, 1)
#also declare a sizer that will contain all the regions on the LHS (sizer2)
self.sizer2 = wx.GridBagSizer(1, 1)
#self.SetMinSize(self.GetSize()) #prevents the window from being made arbitrarily small
self.SetClientSize( (900,900) )
self.SetMinSize( (-1,-1) )
self.InitGUI()
self.Centre()
# self.SetupScrolling()
self.Show()
def InitGUI(self):
screenSize = wx.DisplaySize()
screenWidth = screenSize[0]
screenHeight = screenSize[1]
self.panel = wx.lib.scrolledpanel.ScrolledPanel(self)
# self.panel.Layout()
self.panel.SetupScrolling()
font_title = wx.Font(10, wx.DECORATIVE, wx.NORMAL, wx.BOLD)
#self.panel.SetBackgroundColour('#4f5049')
#a sizer is a way of laying out widgets, it is not a window in itself.
# This is why we create widgets in the self.panel (by using "self.panel" as the parent), then afterwards add the widget to the sizer.
sizer = self.sizer #wx.GridBagSizer(5, 1)
#also declare a sizer that will contain all the regions on the LHS (sizer2)
sizer2 = self.sizer2 #wx.GridBagSizer(1, 1)
# sizer = wx.BoxSizer()
#make a horizontal box dividing the page into left and RHS. We will put the gridbagsizer into the
#LHS and the target picture into the RHS of the hbox
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(sizer,2) #add the box to the current window (self)
#make a vertical box that will contain the stuff on the RHS
vbox_RHS = wx.BoxSizer(wx.VERTICAL)
hbox.Add(vbox_RHS,2) #add the vbox into the hbox, so it now takes up the 2nd position in the hbox (the gridbagsizer took the first)
text_view = wx.StaticText(self.panel, label="Target View")
text_view.SetFont(font_title)
vbox_RHS.Add(text_view, flag=wx.TOP|wx.LEFT|wx.BOTTOM,border=15)
self.iw+=1
button_redraw = wx.Button(self.panel, label="Redraw")
self.Bind(wx.EVT_BUTTON, self.redraw_pic, button_redraw)
vbox_RHS.Add(button_redraw)
self.iw+=1
self.pic = wx.StaticBitmap( self.panel, -1, wx.Bitmap("small1.jpg", wx.BITMAP_TYPE_ANY),size=(400,250) )
vbox_RHS.Add(self.pic)
self.iw+=1
vbox_RHS.Add(sizer2)
button_check = wx.Button(self.panel, label="Check")
self.Bind(wx.EVT_BUTTON, self.check_all, button_check)
sizer.Add(button_check, pos=(self.iv, 0))
self.iv+=1
text_PIC = wx.StaticText(self.panel, label="Main PIC Options")
text_PIC.SetFont(font_title)
sizer.Add(text_PIC, pos=(self.iv, 0), flag=wx.TOP|wx.LEFT|wx.BOTTOM,border=15)
self.iv+=1
self.tc_info = wx.TextCtrl(self.panel)
sizer.Add(self.tc_info, pos=(self.iv, 1), span=(1, 3), flag=wx.TOP)
self.iv+=1
self.add_region(0)
button_add = wx.Button(self.panel, label="Add Region")
self.Bind(wx.EVT_BUTTON, self.add_region, button_add)
vbox_RHS.Add(button_add)
self.iw+=1
sizer.AddGrowableCol(2)
self.panel.SetSizer(hbox)
# GUI EVENTS
def checkBtnClick(self, e):
self.tc_info.SetValue("blahh")
def check_all(self, e):
self.read_all()
#----------------------------------------------------------------------
def redraw_pic(self, e):
#blah
print "Redraw called"
def save_all(self, event):
saveFileDialog = wx.FileDialog(self, "Save As", "", "","Python files (*.py)|*.py",wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
saveFileDialog.ShowModal()
saveFileDialog.GetPath()
saveFileDialog.Destroy()
def read_all(self):
# self.ibox=0 #increases each time a new box is added
# self.nbox=0 #number of boxes currently on the page (accounts for fact some may have been deleted)
# self.Aid=[]
# self.Apresent=[]
self.l_hybrid=0
self.l_colls=0
self.l_implicit=0
self.l_damp_bounds=0
self.l_cold=0
self.l_laser_const=0
# self.nppc=self.tc_nppc.GetValue()
self.nx=self.tc_nx.GetValue()
self.nsp=self.tc_nsp.GetValue()
self.xmax=self.tc_xmax.GetValue()
self.nmin=self.tc_nmin.GetValue()
self.inten=self.tc_inten.GetValue()
self.Ti_init0=self.tc_Ti_init0.GetValue()
self.Ti_init1=self.tc_Ti_init1.GetValue()
self.mi=self.tc_mi.GetValue()
self.tout=self.tc_tout.GetValue()
self.gaussian_cutoffs=self.tc_gaussian_cutoffs.GetValue()
self.t_FWHM=self.tc_t_FWHM.GetValue()
print "nppc=",self.nppc
print "t_FWHM=",self.t_FWHM
# def add_region(self,e):
# #blah
# print "add called"
def add_region(self,event):
print "add_region called"
# i=self.ibox
i=region.nreg
sizer=self.sizer2
reg=region(Ani=0.0,AZ=0.0)
self.Aregion_objects.append(reg)
print "add_region:iw=",self.iw
font_title = wx.Font(10, wx.DECORATIVE, wx.NORMAL, wx.BOLD)
text_region = wx.StaticText(self.panel, label="Region "+str(i))
text_region.SetFont(font_title)
sizer.Add(text_region, pos=(self.iw, 0), flag=wx.TOP|wx.LEFT|wx.BOTTOM,border=15)
self.iw+=1
if __name__ == '__main__':
app = wx.App()
MainWindow(None, title="")
app.MainLoop()
我并没有真正深入研究这个问题,但我能够通过添加来修复它:
self.panel.Layout()
event.Skip()
到 add_region
的 结束 。这样做的原因是因为当你向 sizer 添加东西时,你必须告诉它布局已经改变,因此调用 self.panel.Layout
。(注意这是对面板而不是框架本身的调用) class。 event.Skip()
告诉 wx 在启动某个事件类型时检查是否需要做任何其他事情,在这种情况下,它会在按下按钮后检查是否需要做任何其他事情。
我要说的一个简短说明是,最好将 Frame 和 Panel 实例单独分离到 class。这样面板就有可能被重用,更有条理的代码加上最佳实践 :p 如果你只是在摆弄 wx 那么这很好,但只是一个小注意:)
希望对您有所帮助
在下面的代码中,我尝试将新的文本控件动态添加到 sizer。我有两个 sizer,一个在左边 ("sizer"),一个在右边 ("sizer2")。有一个名为 "add_region" 的函数,它应该将新的文本控件添加到右侧的 sizer (sizer2)。
我已将此功能绑定到按钮 "button_add"。
当我直接从代码主体(行:self.add_region(0)
)调用函数 add_region 时,文本控件会根据需要添加到 sizer2。然而,通过点击按钮调用相同的函数,文本控件被放置在不同的 sizer 中(大概是 "sizer")。
为什么文本控件的位置取决于调用函数的方式?
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#This is a good tutorial: http://wiki.wxpython.org/wxPython%20by%20Example
import wx
import wx.lib.scrolledpanel
class region():
#variables associated with the entire class (not each object)
nreg=0
def __init__(self,Ani=999.0e29,AZ=9.99):
self.Ani=Ani
self.AZ=AZ
# self.text_Ani
region.nreg+=1
class MainWindow(wx.Frame): #A "frame" is what we normally think of as a window, so we have called it MainWindow
def __init__(self, parent, title):
super( MainWindow, self).__init__(parent, title=title, size=(450, 350) )
self.dirname = ''
self.ibox=0
self.iv=0 #the vertical depth on the LHS
self.iw=0 #the vertical depth on the RHS
self.Aregion_objects=[]
self.Ani=[] #array of ion number densities
self.AZ=[]
self.Axmin=[]
self.Axmax=[]
self.Aymin=[]
self.Aymax=[]
self.text_Ani=[]
self.tc_Ani=[]
self.sizer = wx.GridBagSizer(5, 1)
#also declare a sizer that will contain all the regions on the LHS (sizer2)
self.sizer2 = wx.GridBagSizer(1, 1)
#self.SetMinSize(self.GetSize()) #prevents the window from being made arbitrarily small
self.SetClientSize( (900,900) )
self.SetMinSize( (-1,-1) )
self.InitGUI()
self.Centre()
# self.SetupScrolling()
self.Show()
def InitGUI(self):
screenSize = wx.DisplaySize()
screenWidth = screenSize[0]
screenHeight = screenSize[1]
self.panel = wx.lib.scrolledpanel.ScrolledPanel(self)
# self.panel.Layout()
self.panel.SetupScrolling()
font_title = wx.Font(10, wx.DECORATIVE, wx.NORMAL, wx.BOLD)
#self.panel.SetBackgroundColour('#4f5049')
#a sizer is a way of laying out widgets, it is not a window in itself.
# This is why we create widgets in the self.panel (by using "self.panel" as the parent), then afterwards add the widget to the sizer.
sizer = self.sizer #wx.GridBagSizer(5, 1)
#also declare a sizer that will contain all the regions on the LHS (sizer2)
sizer2 = self.sizer2 #wx.GridBagSizer(1, 1)
# sizer = wx.BoxSizer()
#make a horizontal box dividing the page into left and RHS. We will put the gridbagsizer into the
#LHS and the target picture into the RHS of the hbox
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(sizer,2) #add the box to the current window (self)
#make a vertical box that will contain the stuff on the RHS
vbox_RHS = wx.BoxSizer(wx.VERTICAL)
hbox.Add(vbox_RHS,2) #add the vbox into the hbox, so it now takes up the 2nd position in the hbox (the gridbagsizer took the first)
text_view = wx.StaticText(self.panel, label="Target View")
text_view.SetFont(font_title)
vbox_RHS.Add(text_view, flag=wx.TOP|wx.LEFT|wx.BOTTOM,border=15)
self.iw+=1
button_redraw = wx.Button(self.panel, label="Redraw")
self.Bind(wx.EVT_BUTTON, self.redraw_pic, button_redraw)
vbox_RHS.Add(button_redraw)
self.iw+=1
self.pic = wx.StaticBitmap( self.panel, -1, wx.Bitmap("small1.jpg", wx.BITMAP_TYPE_ANY),size=(400,250) )
vbox_RHS.Add(self.pic)
self.iw+=1
vbox_RHS.Add(sizer2)
button_check = wx.Button(self.panel, label="Check")
self.Bind(wx.EVT_BUTTON, self.check_all, button_check)
sizer.Add(button_check, pos=(self.iv, 0))
self.iv+=1
text_PIC = wx.StaticText(self.panel, label="Main PIC Options")
text_PIC.SetFont(font_title)
sizer.Add(text_PIC, pos=(self.iv, 0), flag=wx.TOP|wx.LEFT|wx.BOTTOM,border=15)
self.iv+=1
self.tc_info = wx.TextCtrl(self.panel)
sizer.Add(self.tc_info, pos=(self.iv, 1), span=(1, 3), flag=wx.TOP)
self.iv+=1
self.add_region(0)
button_add = wx.Button(self.panel, label="Add Region")
self.Bind(wx.EVT_BUTTON, self.add_region, button_add)
vbox_RHS.Add(button_add)
self.iw+=1
sizer.AddGrowableCol(2)
self.panel.SetSizer(hbox)
# GUI EVENTS
def checkBtnClick(self, e):
self.tc_info.SetValue("blahh")
def check_all(self, e):
self.read_all()
#----------------------------------------------------------------------
def redraw_pic(self, e):
#blah
print "Redraw called"
def save_all(self, event):
saveFileDialog = wx.FileDialog(self, "Save As", "", "","Python files (*.py)|*.py",wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
saveFileDialog.ShowModal()
saveFileDialog.GetPath()
saveFileDialog.Destroy()
def read_all(self):
# self.ibox=0 #increases each time a new box is added
# self.nbox=0 #number of boxes currently on the page (accounts for fact some may have been deleted)
# self.Aid=[]
# self.Apresent=[]
self.l_hybrid=0
self.l_colls=0
self.l_implicit=0
self.l_damp_bounds=0
self.l_cold=0
self.l_laser_const=0
# self.nppc=self.tc_nppc.GetValue()
self.nx=self.tc_nx.GetValue()
self.nsp=self.tc_nsp.GetValue()
self.xmax=self.tc_xmax.GetValue()
self.nmin=self.tc_nmin.GetValue()
self.inten=self.tc_inten.GetValue()
self.Ti_init0=self.tc_Ti_init0.GetValue()
self.Ti_init1=self.tc_Ti_init1.GetValue()
self.mi=self.tc_mi.GetValue()
self.tout=self.tc_tout.GetValue()
self.gaussian_cutoffs=self.tc_gaussian_cutoffs.GetValue()
self.t_FWHM=self.tc_t_FWHM.GetValue()
print "nppc=",self.nppc
print "t_FWHM=",self.t_FWHM
# def add_region(self,e):
# #blah
# print "add called"
def add_region(self,event):
print "add_region called"
# i=self.ibox
i=region.nreg
sizer=self.sizer2
reg=region(Ani=0.0,AZ=0.0)
self.Aregion_objects.append(reg)
print "add_region:iw=",self.iw
font_title = wx.Font(10, wx.DECORATIVE, wx.NORMAL, wx.BOLD)
text_region = wx.StaticText(self.panel, label="Region "+str(i))
text_region.SetFont(font_title)
sizer.Add(text_region, pos=(self.iw, 0), flag=wx.TOP|wx.LEFT|wx.BOTTOM,border=15)
self.iw+=1
if __name__ == '__main__':
app = wx.App()
MainWindow(None, title="")
app.MainLoop()
我并没有真正深入研究这个问题,但我能够通过添加来修复它:
self.panel.Layout()
event.Skip()
到 add_region
的 结束 。这样做的原因是因为当你向 sizer 添加东西时,你必须告诉它布局已经改变,因此调用 self.panel.Layout
。(注意这是对面板而不是框架本身的调用) class。 event.Skip()
告诉 wx 在启动某个事件类型时检查是否需要做任何其他事情,在这种情况下,它会在按下按钮后检查是否需要做任何其他事情。
我要说的一个简短说明是,最好将 Frame 和 Panel 实例单独分离到 class。这样面板就有可能被重用,更有条理的代码加上最佳实践 :p 如果你只是在摆弄 wx 那么这很好,但只是一个小注意:)
希望对您有所帮助