I am working on a wxPython application with quite a lot of user-changeable options. That leads to a lot of checkboxes which need to be handled in some way.
At the time, my code looks something like this:
self.checkbox1=wx.CheckBox(self.panel,label='Do X')
self.checkbox1.Bind(wx.EVT_CHECKBOX,self.DoXCheckboxHandler)
self.checkbox1.SetValue(True)
self.sizer.Add(self.checkbox1,0,wx.ALL|wx.EXPAND,5)
self.checkbox2=wx.CheckBox(self.panel,label='Do Y')
self.checkbox2.Bind(wx.EVT_CHECKBOX,self.DoYCheckboxHandler)
self.checkbox2.SetValue(True)
self.sizer.Add(self.checkbox2,0,wx.ALL|wx.EXPAND,5)
...
def DoXCheckboxHandler(self,event):
self.DoX=self.checkbox1.GetValue()
self.RefreshUserView(self)
def DoYCheckboxHandler(self,event):
self.DoY=self.checkbox2.GetValue()
self.RefreshUserView(self)
...
Is there any more efficient way (in terms of code-length) of handling multiple checkboxes, which all practically change only one variable and then call one and the same function? My approach, although working fine, seems like having a lot of unnecessary(?) repetition.
Certainly one way to do it would be to skip the "extra" variable altogether - however, in practice I need to have those variables separately from the widgets - as I need the values even if the widgets are destroyed (after closing the options frame, for example).
All advice will be appreciated.
You may want to edit the question title, "handle multiple checkboxes that change one variable" as it does not seem to fit with the following text. There appear to be multiple variables.
That being the case, one of the easiest methods is to store the variable names and values in a dictionary and update the value using the event objects GetName()
function.
Here is an example:
import wx
import wx.lib.agw.ultimatelistctrl as ULC
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "Days and Hours Checkbox Grid", size=(600,300))
agwStyle = (ULC.ULC_HAS_VARIABLE_ROW_HEIGHT | wx.LC_REPORT | wx.LC_VRULES | wx.LC_HRULES | wx.LC_SINGLE_SEL)
self.mylist = mylist = ULC.UltimateListCtrl(self, wx.ID_ANY, agwStyle=agwStyle)
# Load headings
mylist.InsertColumn(0,"Weekday", width=100)
for col in range(1,25):
col_num=str(col-1)
mylist.InsertColumn(col,col_num, width=20)
# Dictionary to Store checkbox variable names and values
self.variables = {}
# Load Side headings
days=['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']
for day in range(7):
mylist.InsertStringItem(day, str(days[day]))
# Load checkboxes
for boxes in range(1,25):
for index in range(7):
day = days[index]
hour = boxes-1
name_of_checkbox = "{day}_{hour}".format(day=day, hour=hour)
self.checkBox = wx.CheckBox(mylist, wx.ID_ANY, "", wx.DefaultPosition, wx.DefaultSize, 0,name=name_of_checkbox)
# Store individual checkbox variable names and values in a dictionary
self.variables[name_of_checkbox] = False
mylist.SetItemWindow(index, boxes, self.checkBox)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(mylist, 1, wx.EXPAND)
button = wx.Button(self,-1,"Print Data")
sizer.Add(button)
self.Bind(wx.EVT_CHECKBOX, self.OnChecked)
self.Bind(wx.EVT_BUTTON, self.OnGetData)
self.SetSizer(sizer)
def OnChecked(self,event):
clicked = event.GetEventObject()
variable_name = clicked.GetName()
self.variables[variable_name] = event.IsChecked()
if event.IsChecked():
print(variable_name,"from False to True")
else:
print(variable_name,"from True to False")
def OnGetData(self,event):
for i,v in self.variables.items():
print(i,v)
app = wx.App()
frame = MyFrame(None)
frame.Show()
app.MainLoop()