I make GUI applications for work a lot. The main idea is to bind a single function to each button, but pass in a different variable with each button.
Here is a full example for Python Gtk:
import pygtk
import gtk
class Example:
def __init__(self):
#Setup window
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_border_width(10)
self.boxSizer = gtk.HBox(False, 0)
#Create widgets
self.button1 = gtk.Button("1")
self.button2 = gtk.Button("2")
self.button3 = gtk.Button("3")
self.buttonPlus = gtk.Button("+")
self.buttonEqual = gtk.Button("=")
self.entry = gtk.Entry(max=0)
#Bind Events to a single function
#You would do this for every button.
#The first parameter in the connect() function is the name,
#the second is the function you are binding,
#and the third is the argument we are passing into the function.
self.button1.connect("clicked", self.button_clicked, 1)
self.button2.connect("clicked", self.button_clicked, 2)
self.button3.connect("clicked", self.button_clicked, 3)
self.buttonPlus.connect("clicked", self.button_clicked, "+")
self.buttonEqual.connect("clicked", self.button_clicked, "=")
#Build Window
self.window.add(self.boxSizer)
self.boxSizer.pack_start(self.button1, True, True, 0)
self.boxSizer.pack_start(self.button2, True, True, 0)
self.boxSizer.pack_start(self.button3, True, True, 0)
self.boxSizer.pack_start(self.buttonPlus, True, True, 0)
self.boxSizer.pack_start(self.buttonEqual, True, True, 0)
self.boxSizer.pack_start(self.entry, True, True, 0)
#Show objects
self.button1.show()
self.button2.show()
self.button3.show()
self.buttonPlus.show()
self.buttonEqual.show()
self.entry.show()
self.boxSizer.show()
self.window.show()
def button_clicked(self, widget, value):
"""Your first function and second function could be combined like this.
What this would do is have a single function that is bound to each button.
The arguments passed into it would be different for each button.
Despite using the 'evil eval' function, I figure this is the route you are going.
This removes the need to (1) have a different function for each button,
and (2) you do not need to store values in variables like this:
self.first_num = 0
self.second_num = 0
self.operation = ""
Your code will be cleaner and easier to modify for future projects.
"""
if (value != None):
if (value != "="):
#Add something to the text
self.entry.set_text(self.entry.get_text() + str(value))
else:
#Evaluate the text
self.result = eval(self.entry.get_text())
self.entry.set_text(str(self.result))
else:
#Clear the text
self.entry.set_text("")
def main(self):
gtk.main()
if __name__ == "__main__":
example = Example()
example.main()
This concept should work for any GUI creation package. Some packages may take a bit more work than others, though.
For example, wxPython does not let you pass arguments into functions. You can get around this limitation by doing what "Florian Bosch" says on Is it possible to pass arguments into event bindings?.
(Note: This method should work for any GUI package that does not allow you to pass arguments into bound functions)
For, wxPython: Bind all of your buttons like this:
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "1"), button1)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "2"), button2)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "3"), button2)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "4"), button2)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "5"), button2)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "6"), button2)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "7"), button2)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "8"), button2)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "9"), button2)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "0"), button2)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "+"), buttonAdd)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "-"), buttonSubtract)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "*"), buttonMultiply)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "/"), buttonDivide)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, "="), buttonEqual)
self.Bind(wx.EVT_BUTTON, lambda event: button_clicked(event, None), buttonClear)
(Use this part: lambda event: button_clicked(event, "1")
in place of where you would normally connect a button to a function.)
The idea here, regardless of the GUI module used, is to bind a single function
to all of your calculator's buttons and just pass in a different value for each button.