Inner Panel doesnt respond - python-3.x

So my goal is do create a settings Window. On the left side you have the different categories. Which you can switch by clicking on them. On the right side is the panel that will switch the content based on what thing you clicked on.
I implemented it by creating a class for every content panel, instantiate it from the frame and Hide all the panels except the one that was choosen.
My problem is that i cant interact with anything inside the panels that i hide and show. Here is a minimum example that you should be able to run.
# -*- coding: utf-8 -*-
"""
Created on Tue Jul 13 15:54:51 2021
#author: Odatas
"""
import wx
import wx.lib.scrolledpanel as scrolled
#First Panel
class settingsConnection(wx.ScrolledWindow):
def __init__(self,parent,size):
wx.ScrolledWindow.__init__(self,parent=parent,size=size)
self.topLevelSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.topLevelSizer)
self.infoText = wx.StaticText(self
,label="I'm Panel settingsConnection\n\nUnder construction."
,style=wx.ALIGN_CENTRE_HORIZONTAL)
self.topLevelSizer.Add(self.infoText)
#Second Panel
class settingsGeneral(wx.ScrolledWindow):
def __init__(self,parent,size):
wx.ScrolledWindow.__init__(self,parent=parent,size=size)
self.topLevelSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.topLevelSizer)
self.infoText = wx.StaticText(self
,label="I'm Panel settingsGeneral\n\nUnder construction."
,style=wx.ALIGN_CENTRE_HORIZONTAL)
self.topLevelSizer.Add(self.infoText)
#Third Panel
class settingsABC(scrolled.ScrolledPanel):
def __init__(self,parent,size):
scrolled.ScrolledPanel.__init__(self,parent=parent,size=size)
self.topLevelSizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.topLevelSizer)
self.firstSizer = wx.BoxSizer(wx.VERTICAL)
self.secondSizer = wx.BoxSizer(wx.VERTICAL)
self.thridSizer = wx.BoxSizer(wx.VERTICAL)
self.SetupScrolling()
self.SetAutoLayout(1)
self.autoStartCheckBox=wx.CheckBox(self, label="Button")
self.autoStartCheckBox.SetValue(True)
self.testButton = wx.Button(self,label="Test")
self.topLevelSizer.Add(self.autoStartCheckBox)
self.topLevelSizer.Add(self.testButton)
self.topLevelSizer.Layout()
self.Fit()
#The main frame that holds all the panels
class settingsWindow(wx.Frame):
FLAG_KILL_ME = False
def __init__(self,parent):
wx.Frame.__init__(self,parent=parent.frame,size=(1000,800),style= wx.CAPTION | wx.CLOSE_BOX |wx.STAY_ON_TOP|wx.FRAME_NO_TASKBAR)
#Event for Closing window
self.Bind(wx.EVT_CLOSE,self.onQuit)
#Event for changing the focus
self.Bind(wx.EVT_LIST_ITEM_FOCUSED,self.onFocusChange)
self.parent=parent
self.panel = wx.Panel(self)
self.panelSize=(800,700)
self.panel.SetBackgroundColour(wx.Colour(255,255,255))
#Contains Everything Level 0
self.topLevelSizer = wx.BoxSizer(wx.VERTICAL)
#Contains Top Part Level 01
self.windowSizer=wx.BoxSizer(wx.HORIZONTAL)
#Contains Bottom part Level 01
self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
#Contains Widgets for Mainpart
self.widgetSizer = wx.BoxSizer(wx.HORIZONTAL)
self.panel.SetSizer(self.topLevelSizer)
self.topLevelSizer.Add(self.windowSizer)
self.topLevelSizer.Add(self.buttonSizer)
self.settingsChooser=wx.ListCtrl(self.panel, id=wx.ID_ANY,style=wx.LC_LIST|wx.LC_SINGLE_SEL,size=(100,700))
self.settingsChooser.AppendColumn("Test")
self.windowSizer.Add(self.settingsChooser)
self.windowSizer.Add(self.widgetSizer)
self.panelList=[]
self.settingsChooser.InsertItem(0,"Allgemein")
self.generalPanel=settingsGeneral(self,self.panelSize)
self.panelList.append(self.generalPanel)
self.widgetSizer.Add(self.generalPanel)
self.settingsChooser.InsertItem(1,"Connection")
self.connectionPanel=settingsConnection(self,self.panelSize)
self.panelList.append(self.connectionPanel)
self.widgetSizer.Add(self.connectionPanel)
self.connectionPanel.Hide()
self.settingsChooser.InsertItem(2,"DLT")
self.dltPanel=settingsABC(self,self.panelSize)
self.panelList.append(self.dltPanel)
self.widgetSizer.Add(self.dltPanel)
self.dltPanel.Hide()
self.currentID=0
self.panel.Fit()
self.Centre()
self.Show()
#self.mythread = threading.Thread(target=self.downloadEndPackageMethod)
#self.mythread.start()
while self.FLAG_KILL_ME is False:
wx.GetApp().Yield()
try:
self.Destroy()
except Exception as e:
pass
#Shows the Selected Panel and hides the current shown.
def onFocusChange(self,event=None):
self.panelList[self.currentID].Hide()
self.panelList[event.GetIndex()].Show()
self.currentID=event.GetIndex()
self.panel.Fit()
self.panel.Layout()
def onQuit(self,event=None):
self.FLAG_KILL_ME = True
self.Hide()
#Main wx.Python App
class Testapp(wx.App):
def __init__(self,redirect=False,filename=None):
wx.App.__init__(self,redirect,filename)
self.frame=wx.Frame(None,title="Test")
self.panel=wx.Panel(self.frame,size=(1000,1000))
self.TopLevelSizer=wx.BoxSizer(wx.VERTICAL)
self.panel.SetSizer(self.TopLevelSizer)
self.settingsButton = wx.Button(self.panel,label="Settings")
self.TopLevelSizer.Add(self.settingsButton)
self.settingsButton.Bind(wx.EVT_BUTTON, self.openSettings)
self.frame.Show()
def openSettings(self,event=None):
settingsWindow(self)
if __name__=='__main__':
app=Testapp()
app.MainLoop()
Edit: Adjustest class "Settings Window" für use with wx.Listbook
class settingsWindow(wx.Frame):
FLAG_KILL_ME = False
def __init__(self,parent):
wx.Frame.__init__(self,parent=parent.frame,size=(1000,800),style= wx.CAPTION | wx.CLOSE_BOX |wx.STAY_ON_TOP|wx.FRAME_NO_TASKBAR)
self.Bind(wx.EVT_CLOSE,self.onQuit)
# self.Bind(wx.EVT_LIST_ITEM_FOCUSED,self.onFocusChange)
self.parent=parent
self.panel = wx.Panel(self)
self.panelSize=(800,700)
self.panel.SetBackgroundColour(wx.Colour(255,255,255))
#Contains Everything Level 0
self.topLevelSizer = wx.BoxSizer(wx.VERTICAL)
#Contains Top Part Level 01
self.windowSizer=wx.BoxSizer(wx.HORIZONTAL)
#Contains Bottom part Level 01
self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
#Contains Widgets for Mainpart
self.widgetSizer = wx.BoxSizer(wx.HORIZONTAL)
self.panel.SetSizer(self.topLevelSizer)
self.topLevelSizer.Add(self.windowSizer)
self.topLevelSizer.Add(self.buttonSizer)
self.windowSizer.Add(self.widgetSizer)
self.settingsBook = wx.Listbook(self.panel)
self.widgetSizer.Add(self.settingsBook)
self.settingsBook.InsertPage(0, settingsGeneral(self,self.panelSize), "Settins")
self.settingsBook.InsertPage(1, settingsConnection(self,self.panelSize), "Connections")
self.settingsBook.InsertPage(2, settingsABC(self,self.panelSize), "ABC")
self.panel.Fit()
self.Centre()
self.Show()
while self.FLAG_KILL_ME is False:
wx.GetApp().Yield()
try:
self.Destroy()
except Exception as e:
pass
def onQuit(self,event=None):
self.FLAG_KILL_ME = True
self.Hide()

Here is a standalone Listbook example taken from a working project.
I've hacked out the meat and left the potatoes. :)
Edit:
I have added a simple main frame from where you activate the configuration code. The main frame contains a counter, in an attempt to convince you, that the MainLoop is still active, as you seem to believe it gets hijacked in some way.
Hopefully, it will be of use.
import wx
import wx.lib.scrolledpanel as scrolled
#from os.path import expanduser
class Test(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "Main Window", size=(300, 200))
self.cnt = 0
panel = wx.Panel(self)
button = wx.Button(panel, label="Open Config", pos=(10, 10), size=(120, 30))
text = wx.StaticText(panel, wx.ID_ANY, "Is the main loop still active", pos=(10, 50))
self.counter = wx.TextCtrl(panel, wx.ID_ANY, "", pos=(10, 80), size=(120, 30))
self.Bind(wx.EVT_BUTTON, self.OnConfig, button)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
self.Show()
self.timer.Start(1000)
def OnConfig(self, event):
frame = Config(parent=self)
def OnTimer(self, event):
self.cnt += 1
self.counter.SetValue(str(self.cnt))
class Config(wx.Frame):
def __init__(self,parent):
wx.Frame.__init__(self,parent, wx.ID_ANY,"Configuration",size=(600,400))
#self.home_dir = expanduser("~")
#self.conf_dir = expanduser("~/fs2")
#self.config_file = self.conf_dir+"/fs2.cfg"
self.parent = parent
# Create the first tab and add it to the listbook
self.panel = wx.Panel(self)
self.lb = wx.Listbook(self.panel)
self.tab1 = scrolled.ScrolledPanel(self.lb, -1)
self.tab1.SetupScrolling()
self.tab1.SetBackgroundColour("Grey")
self.lb.AddPage(self.tab1, "Foot Pedal")
t1_1 = wx.StaticText(self.tab1, wx.ID_ANY, ("Pedal Device"))
self.fc_hidfile = wx.TextCtrl(self.tab1, wx.ID_ANY, "",size=(150, -1))
t1_2 = wx.StaticText(self.tab1, wx.ID_ANY, ("Pedal 1 *"))
self.fc_pedal_1 = wx.ComboBox(self.tab1, wx.ID_ANY, choices=[("Jump Back"), ("Play/Pause"), ("Jump Forward"),("Timestamp"),("Unclear"),("Comment Time stamp"),("Bookmark Time stamp"),("OSD Time stamp"),("Pedal De-activated")],style=wx.CB_READONLY)
t1_3 = wx.StaticText(self.tab1, wx.ID_ANY, ("Pedal 2 *"))
self.fc_pedal_2 = wx.ComboBox(self.tab1, wx.ID_ANY, choices=[("Jump Back"), ("Play/Pause"), ("Jump Forward"),("Timestamp"),("Unclear"),("Comment Time stamp"),("Bookmark Time stamp"),("OSD Time stamp"),("Pedal De-activated")],style=wx.CB_READONLY)
t1_4 = wx.StaticText(self.tab1, wx.ID_ANY, ("Pedal 3 *"))
self.fc_pedal_3 = wx.ComboBox(self.tab1, wx.ID_ANY, choices=[("Jump Back"), ("Play/Pause"), ("Jump Forward"),("Timestamp"),("Unclear"),("Comment Time stamp"),("Bookmark Time stamp"),("OSD Time stamp"),("Pedal De-activated")],style=wx.CB_READONLY)
t1_5 = wx.StaticText(self.tab1, wx.ID_ANY, ("Classic"))
self.fc_classic = wx.SpinCtrl(self.tab1, wx.ID_ANY,"0", min=0, max=2)#, ("Classic Play/Pause"))
t1sizer = wx.FlexGridSizer(10,2,5,5)
t1sizer.Add(t1_1, 0, wx.ALL, 5)
t1sizer.Add(self.fc_hidfile, 0, wx.ALL, 5)
t1sizer.Add(t1_2, 0, wx.ALL, 5)
t1sizer.Add(self.fc_pedal_1, 0, wx.ALL, 5)
t1sizer.Add(t1_3, 0, wx.ALL, 5)
t1sizer.Add(self.fc_pedal_2, 0, wx.ALL, 5)
t1sizer.Add(t1_4, 0, wx.ALL, 5)
t1sizer.Add(self.fc_pedal_3, 0, wx.ALL, 5)
t1sizer.Add(t1_5, 0, wx.ALL, 5)
t1sizer.Add(self.fc_classic, 0, wx.ALL, 5)
self.tab1.SetSizer(t1sizer)
self.tab2 = scrolled.ScrolledPanel(self.lb, -1)
self.tab2.SetupScrolling()
self.tab2.SetBackgroundColour("Grey")
self.lb.AddPage(self.tab2, "Control")
t2_1 = wx.StaticText(self.tab2, wx.ID_ANY, ("Include Hours in Time display"))
self.fc_time_disp = wx.ComboBox(self.tab2, wx.ID_ANY, choices=[("H"),("M")],style=wx.CB_READONLY)
t2_2 = wx.StaticText(self.tab2, wx.ID_ANY, ("Jump Length (secs) *"))
self.fc_jump_length = wx.SpinCtrl(self.tab2, wx.ID_ANY, "3", min=1, max=15)
t2_3 = wx.StaticText(self.tab2, wx.ID_ANY, ("Long Jump *"))
self.fc_l_jump_length = wx.SpinCtrl(self.tab2, wx.ID_ANY,value="", min=0, max=60)
t2_4 = wx.StaticText(self.tab2, wx.ID_ANY, ("Extra Long Jump *"))
self.fc_xl_jump_length = wx.SpinCtrl(self.tab2, wx.ID_ANY,value="", min=0, max=600)
t2_5 = wx.StaticText(self.tab2, wx.ID_ANY, ("Pause Jump (secs) *"))
self.fc_pause_jump = wx.SpinCtrl(self.tab2, wx.ID_ANY, "0", min=0, max=5)
t2_6 = wx.StaticText(self.tab2, wx.ID_ANY, ("Instant Loop length *"))
self.fc_ill = wx.SpinCtrl(self.tab2, wx.ID_ANY, "10", min=3, max=20)
t2sizer = wx.FlexGridSizer(10,2,5,5)
t2sizer.Add(t2_1, 0, wx.ALL, 5)
t2sizer.Add(self.fc_time_disp, 0, wx.ALL, 5)
t2sizer.Add(t2_2, 0, wx.ALL, 5)
t2sizer.Add(self.fc_jump_length, 0, wx.ALL, 5)
t2sizer.Add(t2_3, 0, wx.ALL, 5)
t2sizer.Add(self.fc_l_jump_length, 0, wx.ALL, 5)
t2sizer.Add(t2_4, 0, wx.ALL, 5)
t2sizer.Add(self.fc_xl_jump_length, 0, wx.ALL, 5)
t2sizer.Add(t2_5, 0, wx.ALL, 5)
t2sizer.Add(self.fc_pause_jump, 0, wx.ALL, 5)
t2sizer.Add(t2_6, 0, wx.ALL, 5)
t2sizer.Add(self.fc_ill, 0, wx.ALL, 5)
self.tab2.SetSizer(t2sizer)
# Create and add more tabs....
# read the config file and load in the data
# cfg = ConfigObj(infile = self.config_file)
# try:
# r_hidfile = cfg["control"]["HID_FILE_ID"]
# except:
# r_hid_file = "/dev/input/eventx"
# self.fc_hidfile.SetValue(r_hid_file)
#
# For demo purposes set fixed values
self.fc_hidfile.SetValue('/dev/input/eventx')
self.fc_time_disp.SetStringSelection('H')
self.fc_jump_length.SetValue(2)
self.fc_l_jump_length.SetValue(10)
self.fc_xl_jump_length.SetValue(15)
self.fc_pause_jump.SetValue(1)
self.fc_classic.SetValue(0)
self.fc_pedal_1.SetSelection(0)
self.fc_pedal_2.SetSelection(1)
self.fc_pedal_3.SetSelection(2)
self.fc_ill.SetValue(5)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.lb, 1, wx.ALL|wx.EXPAND, 5)
self.fc_Save = wx.Button(self.panel, wx.ID_ANY, "Save")
self.fc_Quit = wx.Button(self.panel, wx.ID_ANY, "Quit")
self.help_button = wx.Button(self.panel, wx.ID_ANY, "Help")
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
button_sizer.Add(self.fc_Save)
button_sizer.Add(self.fc_Quit)
button_sizer.Add(self.help_button)
sizer.Add(button_sizer)
self.panel.SetSizer(sizer)
self.fc_Save.Bind(wx.EVT_BUTTON, self.OnSave)
self.fc_Quit.Bind(wx.EVT_BUTTON, self.OnQuit)
self.help_button.Bind(wx.EVT_BUTTON, self.OnHelp)
self.Layout()
self.Show()
def OnQuit(self,event):
self.Destroy()
self.Close()
def OnHelp(self, event):
# ShowHelp(parent=None,section='fs2_Config1.pdf')
return
def OnSave(self,event):
#cfg = ConfigObj(infile = self.config_file, create_empty=True, write_empty_values=True, list_values=False)
# write back new configuartion values here
#cfg["control"]["FOOTPEDAL_VPID_LOCK"] = footpedal_vpid_lock
#cfg.write()
self.Destroy()
if __name__ == "__main__":
app = wx.App()
frame = Test(None)
app.MainLoop()
You'll notice, that despite the Config window being active, the Main windows counter is still active.

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()

wxglade list tree not showing properly

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.

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()

How to terminate thread using condition returned by wx.CallAfter()?

I am very new to wxPython and also not familiar with thread concept. I would appreciate a lot if anyone could provide info sources or suggestion to my question.
I had created a GUI using wxpython to allow users run my script with inputs. Since one step takes 20 min to run so I plan to create a Progress Dialog to show users progress and allow them to abort it. I had tested this using the sample code below.
However, I couldn't stop WorkThread even though I clicked the Stop Button in Progress Dialog. I tried
1. make if statement using return value from pb.sendMessage()
2. create the ProgressDialog object when WorkThread starts and call ProgressDialog.abort
but none of them work. I wonder if there's conceptual mistakes implementing code like this to achieve what I want to do? Or if this can work with correction? Any hint would be appreciated!!
class WorkThread(Thread):
def __init__(self):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.start() # start the thread
def run(self):
for i in range(10):
time.sleep(1)
val = 100 / 10
wx.CallAfter(pub.sendMessage, "update", step=val)
print 'Finish Run'
class ProgressDialog(wx.Dialog):
def __init__(self):
wx.Dialog.__init__(self, None)
self.abort = False
self.progress = 0
bSizer2 = wx.BoxSizer(wx.VERTICAL)
self.gauge = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.GA_HORIZONTAL)
self.gauge.SetValue(0)
self.m_button1 = wx.Button(self, wx.ID_ANY, u"Stop Training", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer2.Add(self.gauge, 0, 0, 5)
bSizer2.Add(self.m_button1, 0, 0, 5)
self.SetSizer(bSizer2)
self.Layout()
self.Centre(wx.BOTH)
## Connect Events
self.m_button1.Bind(wx.EVT_BUTTON, self.on_cancel)
pub.subscribe(self.updateProgress, "update")
def updateProgress(self, step):
self.progress += step
if self.abort:
self.Update()
self.Close()
elif self.progress >= 100:
self.gauge.SetValue(self.progress)
self.Update()
self.Close()
else:
self.gauge.SetValue(self.progress)
def on_cancel(self, event):
"""Cancels the conversion process"""
self.abort = True
print 'Click'
# pub.unsubscribe(self.if_abort, 'cancel')
def __del__(self):
pass
########################################################################################
class MainFrame(wx.Frame):
# ----------------------------------------------------------------------
def __init__(self,parent):
wx.Frame.__init__(self,parent)
# Add a panel so it looks the correct on all platforms
panel = wx.Panel(self, wx.ID_ANY)
self.btn = btn = wx.Button(panel, label="Start Thread")
btn.Bind(wx.EVT_BUTTON, self.onButton)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(btn, 0, wx.ALL | wx.CENTER, 5)
panel.SetSizer(sizer)
# ----------------------------------------------------------------------
def onButton(self, event):
btn = event.GetEventObject()
btn.Disable()
WorkThread()
self.dlg = ProgressDialog()
self.dlg.ShowModal()
btn.Enable()
app = wx.App()
frame = MainFrame(None)
frame.Show(True)
# start the applications
app.MainLoop()
You need a method within the thread to stop it.
You should also wait for it to stop.
Here is an option using your code:
from threading import Thread
import wx
from wx.lib.pubsub import pub
import time
class WorkThread(Thread):
def __init__(self):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.stop_work_thread = 0
self.start() # start the thread
def run(self):
for i in range(10):
if self.stop_work_thread == 1:
break
time.sleep(1)
val = 100 / 10
wx.CallAfter(pub.sendMessage, "update", step=val)
wx.CallAfter(pub.sendMessage, "finish")
return
def stop(self):
self.stop_work_thread = 1
class ProgressDialog(wx.Dialog):
def __init__(self,parent):
wx.Dialog.__init__(self, parent)
self.parent = parent
self.abort = False
self.progress = 0
bSizer2 = wx.BoxSizer(wx.VERTICAL)
self.gauge = wx.Gauge(self, wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.GA_HORIZONTAL)
self.gauge.SetValue(0)
self.m_button1 = wx.Button(self, wx.ID_ANY, u"Stop Training", wx.DefaultPosition, wx.DefaultSize, 0)
bSizer2.Add(self.gauge, 0, 0, 5)
bSizer2.Add(self.m_button1, 0, 0, 5)
self.SetSizer(bSizer2)
self.Layout()
self.Centre(wx.BOTH)
## Connect Events
self.m_button1.Bind(wx.EVT_BUTTON, self.on_cancel)
pub.subscribe(self.updateProgress, "update")
pub.subscribe(self.on_finish, "finish")
def updateProgress(self, step):
self.progress += step
self.gauge.SetValue(self.progress)
def on_cancel(self, event):
"""Cancels the conversion process"""
self.parent.work.stop()
self.parent.work.join()
pub.unsubscribe(self.updateProgress, "update")
pub.unsubscribe(self.on_finish, "finish")
self.Destroy()
# pub.unsubscribe(self.if_abort, 'cancel')
def on_finish(self):
"""conversion process finished"""
pub.unsubscribe(self.updateProgress, "update")
pub.unsubscribe(self.on_finish, "finish")
self.Close()
def __del__(self):
pass
########################################################################################
class MainFrame(wx.Frame):
# ----------------------------------------------------------------------
def __init__(self,parent):
wx.Frame.__init__(self,parent)
# Add a panel so it looks the correct on all platforms
self.panel = wx.Panel(self, wx.ID_ANY)
self.btn = btn = wx.Button(self.panel, label="Start Thread")
btn.Bind(wx.EVT_BUTTON, self.onButton)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(btn, 0, wx.ALL | wx.CENTER, 5)
self.panel.SetSizer(sizer)
# ----------------------------------------------------------------------
def onButton(self, event):
btn = event.GetEventObject()
btn.Disable()
self.panel.work = WorkThread()
self.dlg = ProgressDialog(self.panel)
self.dlg.ShowModal()
btn.Enable()
app = wx.App()
frame = MainFrame(None)
frame.Show(True)
# start the applications
app.MainLoop()

Resources