wxglade list tree not showing properly - python-3.x

I am new to wxglade and trying to create a form to show tabs and split window. There are going to be tree lists on the left pane. The issue is that when I open the form, it shows the treelist but the list cannot be collapsed or expanded. When I go to 2nd tab and come back to the first, tree list is shown in small box.
import wx
# Define the tab content as classes:
class TabOne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.SetSize((400, 300))
self.window_1 = wx.SplitterWindow(self, wx.ID_ANY)
self.window_1_pane_1 = wx.ScrolledWindow(self.window_1, wx.ID_ANY, style=wx.BORDER_RAISED | wx.TAB_TRAVERSAL)
#self.button_1 = wx.Button(self.window_1_pane_1, wx.ID_ANY, "button_1")
#t = wx.StaticText(self, -1, "This is the first tab", (100,100)) start list
il = wx.ImageList(16,16)
self.fldridx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16,16)))
self.fldropenidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, (16,16)))
self.fileidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, (16,16)))
self.tree = wx.TreeCtrl(self, style=wx.TR_DEFAULT_STYLE | wx.TR_EDIT_LABELS)
self.tree.AssignImageList(il)
root = self.tree.AddRoot("Server")
self.tree.SetItemData(root, None)
self.tree.SetItemImage(root, self.fldridx,wx.TreeItemIcon_Normal)
self.tree.SetItemImage(root, self.fldropenidx,wx.TreeItemIcon_Expanded)
tree = ["A","B","C","D","E","F","G","H"]
self.AddTreeNodes(root, tree)
self.tree.Expand(root)
def AddTreeNodes(self, parentItem, items):
for item in items:
if type(item) == str:
newItem = self.tree.AppendItem(parentItem, item)
self.tree.SetItemData(newItem, None)
#self.tree.SetItemImage(newItem, self.fileidx,wx.TreeItemIcon_Normal)
else:
newItem = self.tree.AppendItem(parentItem, item[0])
self.tree.SetItemPyData(newItem, None)
#self.tree.SetItemImage(newItem, self.fldridx,wx.TreeItemIcon_Normal)
self.tree.SetItemImage(newItem, self.fldropenidx,wx.TreeItemIcon_Expanded)
self.AddTreeNodes(newItem, item[1])
#end list
self.window_1_pane_2 = wx.Panel(self.window_1, wx.ID_ANY)
self.window_1_pane_1.SetMinSize((50, 256))
self.window_1_pane_1.SetBackgroundColour(wx.Colour(216, 216, 191))
self.window_1_pane_1.SetScrollRate(10, 10)
self.window_1.SetMinimumPaneSize(20)
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
#sizer_2.Add(self.button_1, 0, 0, 0)
sizer1 = wx.BoxSizer(wx.VERTICAL)
sizer1.Add(self.tree, 20, wx.EXPAND)
self.SetSizer(sizer1)
self.window_1_pane_1.SetSizer(sizer_2)
self.window_1.SplitVertically(self.window_1_pane_1, self.window_1_pane_2)
sizer_1.Add(self.window_1, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
class TabTwo(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the second tab", (20,20))
class TabThree(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the third tab", (20,20))
class TabFour(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the last tab", (20,20))
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="wxPython tabs example #pythonspot.com")
# Create a panel and notebook (tabs holder)
p = wx.Panel(self)
nb = wx.Notebook(p)
# Create the tab windows
tab1 = TabOne(nb)
tab2 = TabTwo(nb)
tab3 = TabThree(nb)
tab4 = TabFour(nb)
# Add the windows to tabs and name them.
nb.AddPage(tab1, "Tab 1")
nb.AddPage(tab2, "Tab 2")
nb.AddPage(tab3, "Tab 3")
nb.AddPage(tab4, "Tab 4")
# Set noteboook in a sizer to create the layout
sizer = wx.BoxSizer()
sizer.Add(nb, 1, wx.EXPAND)
p.SetSizer(sizer)
if __name__ == "__main__":
app = wx.App(redirect=True)
MainFrame().Show()
app.MainLoop()

wx.TreeCtrl has built-in horizontal and vertical scroll bars. Therefore, I guess there is no need to use the wx.ScrolledWindow here. I simplify the code for class TabOne to the following:
class TabOne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.SetSize((400, 300))
self.window_1 = wx.SplitterWindow(self, wx.ID_ANY)
il = wx.ImageList(16,16)
self.fldridx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16,16)))
self.fldropenidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, (16,16)))
self.fileidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, (16,16)))
self.tree = wx.TreeCtrl(self.window_1, style=wx.TR_DEFAULT_STYLE | wx.TR_EDIT_LABELS)
self.tree.AssignImageList(il)
root = self.tree.AddRoot("Server")
self.tree.SetItemData(root, None)
self.tree.SetItemImage(root, self.fldridx,wx.TreeItemIcon_Normal)
self.tree.SetItemImage(root, self.fldropenidx,wx.TreeItemIcon_Expanded)
tree = ["A","B","C","D","E","F","G","H"]
self.AddTreeNodes(root, tree)
self.tree.Expand(root)
self.window_1_pane_2 = wx.Panel(self.window_1, wx.ID_ANY)
self.window_1.SetMinimumPaneSize(20)
self.window_1.SplitVertically(self.tree, self.window_1_pane_2)
sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
sizer_1.Add(self.window_1, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
def AddTreeNodes(self, parentItem, items):
for item in items:
if type(item) == str:
newItem = self.tree.AppendItem(parentItem, item)
self.tree.SetItemData(newItem, None)
#self.tree.SetItemImage(newItem, self.fileidx,wx.TreeItemIcon_Normal)
else:
newItem = self.tree.AppendItem(parentItem, item[0])
self.tree.SetItemPyData(newItem, None)
#self.tree.SetItemImage(newItem, self.fldridx,wx.TreeItemIcon_Normal)
self.tree.SetItemImage(newItem, self.fldropenidx,wx.TreeItemIcon_Expanded)
self.AddTreeNodes(newItem, item[1])
and now is working as expected.

Related

Resetting a wxPython app / destroying everything and starting from initial frame

I've read other answers here, but they all seem to deal with just closing an app altogether, making sure all processes and frames and such are destroyed in the process. What I want to do is a little different.
My app consists of three frames (StartFrame, ParaFrame, ResultFrame) as well as a custom class for storing and manipulating data. The basics are: StartFrame is just some text and a "start" button. "Start" creates an instance of ParaFrame, hides the StartFrame, and shows the ParaFrame instance. Paraframe has a bunch of widgets for the user to select a file and how to analyze it. When all the fields are entered, an "Analyze" button pops up, which (when clicked) instantiates the custom DataHandler class, sets its parameters according to the user selections, calls a DataHandler method which analyzes the data, hides itself, and instantiates+shows the ResultsFrame. Not surprisingly, the ResultsFrame shows the results of the analysis.
I want to add a "Start Over" control which will destroy everything (all the frames, panels, the DataHandler instance, etc.) and display a fresh StartFrame instance, or otherwise destroy everything except the already-instantiated-but-hidden StartFrame, showing that frame again, but I'm at a loss.
A simplified example follows:
import wx
class StartFrame(wx.Frame):
"""App start frame"""
FRAME_MIN_SIZE = (900,600)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="LOD Calculator", size=wx.Size(900,600),
style=wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
self.startpnl = wx.Panel(self)
self.startvsizer=wx.BoxSizer(wx.VERTICAL)
self.startbtnsizer=wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.startpnl, wx.ID_ANY, "Start Analysis",\
size = (200,60))
self.btn.Bind(wx.EVT_BUTTON, self._OnStart)
self.startbtnsizer.AddStretchSpacer()
self.startbtnsizer.Add(self.btn, 0, wx.CENTER)
self.startbtnsizer.AddStretchSpacer()
self.startvsizer.AddStretchSpacer()
self.startvsizer.Add(self.startbtnsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.startvsizer.AddStretchSpacer()
self.startpnl.SetSizerAndFit(self.startvsizer)
def _OnStart(self,event):
self.frm2 = ParaFrame(None)
self.Hide()
self.frm2.Show()
class ParaFrame(wx.Frame):
"""Data load frame"""
FRAME_MIN_SIZE = (950,800)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="LOD Calculator", size=wx.Size(950,800),
style=wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.analyzebtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Analyze",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.analyzebtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.analyzebtn.Bind(wx.EVT_BUTTON, self._analyze)
def _analyze(self, event):
dhandler = DataHandler(self)
dhandler.data = "a bunch"
dhandler.data2 = " of data"
dhandler.data3 = " goes here"
dhandler._analyzeData()
self.resfrm = ResultFrame(self, dhandler.data, dhandler.data2)
self.Hide()
self.resfrm.Show()
class DataHandler:
def __init__(self,parent):
self.data = ''
self.data2 = ''
self.data3 = ''
def _analyzeData(self):
anastr = self.data + self.data2 + " gets analyzed"
print(anastr)
class ResultFrame(wx.Frame):
def __init__(self, parent, targets, dftables):
super(ResultFrame, self).__init__(parent, title="results", size=(1535,935))
self.targets = targets
self.dftables = dftables
self.InitUI()
self.Layout()
def InitUI(self):
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.restartbtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Start Over",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.restartbtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.restartbtn.Bind(wx.EVT_BUTTON, self.OnRestart)
### this is where I try to destroy the ParaFrame instance and everything spawned by it, unsuccessfully
def OnRestart(self, event):
frm.frm2.Destroy()
frm.Show()
def main():
import wx.lib.mixins.inspection
app = wx.App()
frm = StartFrame(None)
frm.Show()
wx.lib.inspection.InspectionTool().Show(refreshTree=True)
app.MainLoop()
if __name__ == "__main__":
main()
As you can see, in the ResultFrame I have a "Start Over" button bound to a method in which I try to destroy the ParaFrame instance (and thus the DataHandler and ResultFrame instances spawned from it) by using frm.frm2.Destroy(), but get an error:
Traceback (most recent call last):
File "C:\Python\Scripts\stackexchange code.py", line 102, in OnRestart
frm.frm2.Destroy()
NameError: name 'frm' is not defined
If I change the line to just frm2.Destroy(), I get the same error, but stating name 'frm2' is not defined.
What am I doing wrong here, and how can I accomplish my goal? I'm still newish to OOP and quite new to wxPython, so any help is appreciate it. All I want is for that button to destroy everything and display the/an initial StartFrame again. Thank you :)
As long as you create each class without a parent, you can use self.Destroy() after creating the next frame in the chain, without it destroying any children. (Pass any data required as a parameter other than parent)
So your code, looks something like this:
import wx
class StartFrame(wx.Frame):
"""App start frame"""
FRAME_MIN_SIZE = (900,600)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="Load Calculator", size=wx.Size(900,600))
self.startpnl = wx.Panel(self)
self.startvsizer=wx.BoxSizer(wx.VERTICAL)
self.startbtnsizer=wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.startpnl, wx.ID_ANY, "Start Analysis",\
size = (200,60))
self.btn.Bind(wx.EVT_BUTTON, self._OnStart)
self.startbtnsizer.AddStretchSpacer()
self.startbtnsizer.Add(self.btn, 0, wx.CENTER)
self.startbtnsizer.AddStretchSpacer()
self.startvsizer.AddStretchSpacer()
self.startvsizer.Add(self.startbtnsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.startvsizer.AddStretchSpacer()
self.startpnl.SetSizerAndFit(self.startvsizer)
def _OnStart(self,event):
frm2 = ParaFrame(None)
frm2.Show()
self.Destroy()
class ParaFrame(wx.Frame):
"""Data load frame"""
FRAME_MIN_SIZE = (950,800)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="Load Calculator", size=wx.Size(900,600))
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.analyzebtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Analyze",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.analyzebtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.analyzebtn.Bind(wx.EVT_BUTTON, self._analyze)
def _analyze(self, event):
dhandler = DataHandler(self)
dhandler.data = "a bunch"
dhandler.data2 = " of data"
dhandler.data3 = " goes here"
dhandler._analyzeData()
resfrm = ResultFrame(None, dhandler.data, dhandler.data2)
resfrm.Show()
self.Destroy()
class DataHandler:
def __init__(self,parent):
self.data = ''
self.data2 = ''
self.data3 = ''
def _analyzeData(self):
anastr = self.data + self.data2 + " gets analyzed"
print(anastr)
class ResultFrame(wx.Frame):
def __init__(self, parent, targets, dftables):
super(ResultFrame, self).__init__(parent, title="Results", size=(900,600))
self.targets = targets
self.dftables = dftables
self.InitUI()
self.Layout()
def InitUI(self):
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.restartbtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Start Over",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.restartbtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.restartbtn.Bind(wx.EVT_BUTTON, self.OnRestart)
### this is where I try to destroy the ParaFrame instance and everything spawned by it, unsuccessfully
def OnRestart(self, event):
frm = StartFrame(None)
frm.Show()
self.Destroy()
def main():
app = wx.App()
frm = StartFrame(None)
frm.Show()
app.MainLoop()
if __name__ == "__main__":
main()

How can i load class in notebook when tab is clicked in wxpython?

Here i have a doubt that when notebook tab is clicked at that time only it should load class in that tab. But in wxpython all class loads by default in tab so how can i put conditions to load class when tab is clicked.
Here is a small example.
import wx
class tabclass(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the help tab", (20,20))
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="notebook")
mainPanel = wx.Panel(self,size=(1365, 700), pos=(0, 71), style=wx.DOUBLE_BORDER)
self.nb = wx.Notebook(mainPanel,size=(1365, 700))
tab0 = tabclass(self.nb)
self.nb.AddPage(tab0, "Tab One")
if __name__ == "__main__":
app = wx.App()
MainFrame().Show()
app.MainLoop()
Here I want to display static text when the tab is clicked otherwise class should not load.
You might want a different method of selecting what is and what is not displayed in the notebook.
A menu, for example, seems an appropriate selection tool.
i.e.
import wx
class tabclass(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is the help tab", (20,20))
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="notebook")
mainPanel = wx.Panel(self,size=(1365, 700), pos=(0, 71), style=wx.DOUBLE_BORDER)
self.nb = wx.Notebook(mainPanel,size=(1365, 700))
tabmenu = wx.Menu()
t1 = wx.MenuItem(tabmenu, id = -1, text="Help", kind=wx.ITEM_CHECK)
tabmenu.Append(t1)
t2 = wx.MenuItem(tabmenu, id = -1, text="Other tab", kind=wx.ITEM_CHECK)
tabmenu.Append(t2)
t3 = wx.MenuItem(tabmenu, id = -1, text="Another tab", kind=wx.ITEM_CHECK)
tabmenu.Append(t3)
tabmenu.Append(wx.ID_EXIT, '&Quit')
# Creating the menubar.
menuBar = wx.MenuBar()
# Add menus
menuBar.Append(tabmenu, "&Tabs")
# Adding the MenuBar to the Frame content.
self.SetMenuBar(menuBar)
# Bind menu item to functions
self.Bind(wx.EVT_MENU, self.helptab, t1)
self.Bind(wx.EVT_MENU, self.othertab, t2)
self.Bind(wx.EVT_MENU, self.anothertab, t3)
self.Bind(wx.EVT_MENU, self.OnQuit, id=wx.ID_EXIT)
# Obviously, here you would differentiate your tabs
# I have used the same one for brevity
def helptab(self, event):
if event.IsChecked():
self.tab0 = tabclass(self.nb)
self.nb.AddPage(self.tab0, "Help Tab")
else:
#Delete the "Help Tab"
pass
def othertab(self, event):
if event.IsChecked():
self.tab1 = tabclass(self.nb)
self.nb.AddPage(self.tab1, "Other Tab")
else:
#Delete the "Other Tab"
pass
def anothertab(self, event):
if event.IsChecked():
self.tab2 = tabclass(self.nb)
self.nb.AddPage(self.tab2, "Another Tab")
else:
#Delete the "Another Tab"
pass
def OnQuit(self, event):
self.Destroy()
if __name__ == "__main__":
app = wx.App()
MainFrame().Show()
app.MainLoop()

wxPython: How to make Dialog resize according to the content of the embedded StaticText

This is my small program for testing:
import wx
class Test(wx.Dialog):
def __init__(self, parent, title="", caption='', btnList=['OK']):
wx.Dialog.__init__(self, parent, -1, title=title)
self.btnList = btnList
self.parent = parent
sizer = wx.BoxSizer()
self.panel = wx.Panel(self, -1)
sizer.Add(self.panel)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.panel.SetSizer(self.mainSizer)
self.caption = caption
self.setCaption()
self.setButton()
self.SetSizerAndFit(sizer)
def setCaption(self):
caplb = wx.StaticText(self.panel, -1, self.caption)
self.mainSizer.Add(caplb, 1, wx.EXPAND | wx.ALL, 10)
capFont = caplb.GetFont()
capFont.SetPointSize(10)
capFont.SetWeight(wx.FONTWEIGHT_BOLD)
caplb.SetFont(capFont)
caplb.SetForegroundColour(wx.RED)
def setButton(self):
self.btnBox = wx.BoxSizer(wx.HORIZONTAL)
self.mainSizer.Add(self.btnBox, 0, wx.EXPAND | wx.BOTTOM, 10)
self.btnBox.Add((1, 1), 1, wx.EXPAND)
self.btns = []
for i in range(len(self.btnList)):
self.btns.append(wx.Button(self.panel, -1, self.btnList[i]))
self.btnBox.Add(self.btns[i])
self.btnBox.Add((1, 1), 1, wx.EXPAND)
if __name__ == "__main__":
app = wx.App()
msg = ""
for i in range(8):
msg += "%s: ATTENTION! ATTENTION! ATTENTION! ATTENTION!\n" % i
dlg = Test(None, caption=msg, title="WARNING", btnList=['Yes', 'No'])
dlg.CenterOnParent()
val = dlg.ShowModal()
app.MainLoop()
I want the dialog to spread so that all text in the caplb can be seen. In most of the systems I has worked on this piece of code work well. But when I move to the new system, there is something with the gtk limit to show only half of the caplb. I don't know how to force it to show all of the StaticText. Can you please have a look at that and show me the hint? Thanks ahead!!!

Set a minimal window size so all sizers fit

I have tried to understand how sizer and sizes work but clearly, I am missing something vital. This is what I get:
Clearly, the inside panels (sizers) do not fit the window. What I want is this:
which was created by a manual re-size.
How can I achieve that?
Note that the real code has many more different wx.StaticBox so a generic explanation of what I am doing wrong would be more welcome than just a fix.
Here is the toy example code:
import wx
import wx.lib.agw.floatspin as FS
class GUIControl(wx.Frame):
def __init__(self, parent, id, title, *args, **kwargs):
super(GUIControl, self).__init__(parent, id, title, *args, **kwargs)
self.radio = {}
self.modes = ['Open loop', 'Current control', 'Voltage control']
panel = wx.Panel(self)
panel.SetBackgroundColour('#5968c3')
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self._ui(panel), 1, wx.EXPAND | wx.ALL, 3)
panel.SetSizer(sizer)
print(sizer.ComputeFittingWindowSize(self))
self.SetSize(sizer.ComputeFittingWindowSize(self))
self.Centre()
self.Show(True)
def _ui(self, parent):
panel = wx.Panel(parent)
vbox = wx.BoxSizer(wx.VERTICAL)
flags = wx.EXPAND | wx.SHAPED
vbox.Add(self._ui_prefix(panel), flag=wx.EXPAND)
vbox.Add(self._ui_control_mode(panel), flag=flags)
vbox.Add(self._ui_suffix(panel), flag=wx.EXPAND)
panel.SetSizer(vbox)
return panel
def _ui_prefix(self, parent):
panel = wx.Panel(parent)
panel.SetBackgroundColour('steelblue')
hbox = wx.BoxSizer(wx.HORIZONTAL)
_label = wx.StaticText(panel, label='')
_label.SetLabelMarkup("<b><i><big>Controls</big></i></b>")
hbox.Add(_label, flag=wx.ALIGN_CENTER | wx.ALL)
panel.SetSizer(hbox)
return panel
def _ui_control_mode(self, parent):
box = wx.StaticBox(parent, -1, "Control mode")
_label_modes = wx.StaticText(box, label='')
_label_modes.SetLabelMarkup("<i>Modes</i>")
for item in self.modes:
self.radio[item] = wx.RadioButton(box, -1, item)
_label_duty = wx.StaticText(box, label='')
_label_duty.SetLabelMarkup("<i>Duty cycle</i>")
self.sc1 = wx.SpinCtrl(box, wx.ID_ANY, '0', min=0, max=100)
_units_duty = wx.StaticText(box, label='%')
_label_current = wx.StaticText(box, label='')
_label_current.SetLabelMarkup("<i>Current</i>")
self.sc2 = FS.FloatSpin(box,
wx.ID_ANY,
value=0.0,
min_val=0.0,
max_val=20.0, # FIXME
increment=0.1)
self.sc2.SetFormat("%f")
self.sc2.SetDigits(1)
_units_current = wx.StaticText(box, label='A')
fgs = wx.FlexGridSizer(5, 3, 5, 7)
flags = wx.EXPAND | wx.ALL | wx.SHAPED
fgs.Add(_label_modes, 0, flags)
fgs.Add(self.radio['Open loop'], 0, flags)
fgs.AddStretchSpacer()
fgs.AddStretchSpacer()
fgs.Add(self.radio['Current control'], 0, flags)
fgs.AddStretchSpacer()
fgs.AddStretchSpacer()
fgs.Add(self.radio['Voltage control'], 0, flags)
fgs.AddStretchSpacer()
fgs.Add(_label_duty, 0, flags)
fgs.Add(self.sc1, 0, flags)
fgs.Add(_units_duty, 0, flags)
fgs.Add(_label_current, 0, flags)
fgs.Add(self.sc2, 0, flags)
fgs.Add(_units_current, 0, flags)
fgs.SetSizeHints(box)
fgs.Layout()
box.SetSizer(fgs)
return box
def _ui_suffix(self, parent):
panel = wx.Panel(parent)
panel.SetBackgroundColour('steelblue')
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(wx.BoxSizer(wx.VERTICAL),
flag=wx.RESERVE_SPACE_EVEN_IF_HIDDEN)
_quit = wx.Button(panel, -1, label=" Quit ")
_quit.SetBackgroundColour('#5968c3')
_quit.Bind(wx.EVT_BUTTON, self.OnQuit)
hbox.AddStretchSpacer()
hbox.Add(_quit, flag=wx.ALIGN_CENTER | wx.SHAPED | wx.ALL, border=3)
hbox.AddStretchSpacer()
panel.SetSizer(hbox)
return panel
def OnQuit(self, e):
self.Close()
if __name__ == '__main__':
app = wx.App()
GUIControl(None, -1, title='Control UI test')
app.MainLoop()
The easiest thing to do in this case is to also give the frame a sizer, add the main panel to it, and then call the frame's Fit method. For example, you can replace the call to self.SetSize in GUIControl.__init__ with this:
frameSizer = wx.BoxSizer()
frameSizer.Add(panel, 1, wx.EXPAND)
self.SetSizer(frameSizer)
self.Fit()

wXPython: Unable to get widget to enlarge/expand in size

I can't get the listctrl widget to expand.
example picture: http://img109.imageshack.us/img109/3171/22488459.jpg
This code simply creates a dialog box and creates a CheckListCtrlMixin which is a ListCtrl with check boxes.
import wx
import re, os, sys
from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin
class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
def __init__(self, parent):
wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT | wx.SUNKEN_BORDER)
CheckListCtrlMixin.__init__(self)
ListCtrlAutoWidthMixin.__init__(self)
class QueueDialog(wx.Dialog):
def __init__(self, parent, title):
super(QueueDialog, self).__init__(parent=parent,
title=title, size=(400, 500))
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
sb = wx.StaticBox(panel, label='Queue')
sbs = wx.StaticBoxSizer(sb, orient=wx.VERTICAL)
panel2 = wx.Panel(panel)
hbox3 = wx.BoxSizer(wx.VERTICAL)
hbox3.Add(panel2, proportion=1, flag=wx.EXPAND|wx.ALL)
listB = CheckListCtrl(panel2)
listB.InsertColumn(0, "Test", width=100)
listB.InsertColumn(1, "Status", wx.LIST_FORMAT_RIGHT)
dalist = ["heh", "ha", "hello"]
for name in dalist[0:3]:
index = listB.InsertStringItem(sys.maxint, name[0:-1])
sbs.Add(hbox3, proportion=1,flag=wx.EXPAND|wx.ALL)
panel.SetSizer(sbs)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
okButton = wx.Button(self, label='OK')
closeButton = wx.Button(self, label='Cancel')
hbox2.Add(okButton)
hbox2.Add(closeButton, flag=wx.LEFT, border=5)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(panel, proportion=1, flag=wx.EXPAND|wx.ALL, border=10)
vbox.Add(hbox2, flag= wx.ALIGN_CENTER|wx.BOTTOM, border=10)
self.SetSizer(vbox)
def OnClose(self, e):
self.Destroy()
class window(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600, 400))
e = QueueDialog(None, title='Queue')
e.ShowModal()
e.Destroy()
self.Centre()
self.Show(True)
app = wx.App(0)
window(None, -1, 'e')
app.MainLoop()
I don't know why you have the second panel, but it's really not needed and makes things more complex. Here's one version that works on my machine:
import wx
import re, os, sys
from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin
class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
def __init__(self, parent):
wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT | wx.SUNKEN_BORDER)
CheckListCtrlMixin.__init__(self)
ListCtrlAutoWidthMixin.__init__(self)
class QueueDialog(wx.Dialog):
def __init__(self, parent, title):
super(QueueDialog, self).__init__(parent=parent,
title=title, size=(400, 500))
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
sb = wx.StaticBox(panel, label='Queue')
sbs = wx.StaticBoxSizer(sb, orient=wx.VERTICAL)
hbox3 = wx.BoxSizer(wx.VERTICAL)
listB = CheckListCtrl(panel)
listB.InsertColumn(0, "Test", width=100)
listB.InsertColumn(1, "Status", wx.LIST_FORMAT_RIGHT)
hbox3.Add(listB, 1, wx.EXPAND)
dalist = ["heh", "ha", "hello"]
for name in dalist[0:3]:
index = listB.InsertStringItem(sys.maxint, name[0:-1])
sbs.Add(hbox3, proportion=1,flag=wx.EXPAND|wx.ALL)
panel.SetSizer(sbs)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
okButton = wx.Button(self, label='OK')
closeButton = wx.Button(self, label='Cancel')
hbox2.Add(okButton)
hbox2.Add(closeButton, flag=wx.LEFT, border=5)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(panel, proportion=1, flag=wx.EXPAND|wx.ALL, border=10)
vbox.Add(hbox2, flag= wx.ALIGN_CENTER|wx.BOTTOM, border=10)
self.SetSizer(vbox)
def OnClose(self, e):
self.Destroy()
class window(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600, 400))
e = QueueDialog(None, title='Queue')
e.ShowModal()
e.Destroy()
self.Centre()
self.Show(True)
app = wx.App(0)
window(None, -1, 'e')
app.MainLoop()

Resources