Making a calculator using Enthought's TraitsUI package
I used the traits and traitsUI packages of Enthought to write this calculator app. As you can see, I adapted it from another code I wrote that was in turn adapted from the TableEditor example code from the traitsUI examples.
Let me briefly explain what is going on in the code.
Button() creates, well, a button, which can then be linked to an action. the _*_button_fired() methods in the Application class are activated when the button is pressed and which do the necessary computation in the background! Similarly @on_trait_change() decorator also does a similar job. The method/function being decorated by such a decorator will be triggered/called when the attribute in the parenthesis changes! Traits takes care of listening to the attributes in the background, making life a lot easier for you!
Coming to how the calculator looks, that is defined in the View. Buttons or Items in general can be organized using the HGroup and VGroup methods, as done with the button layout. The calculated values are shown using a TextEditor object, which we borrowed from traitsUI, and we set it in a readonly mode. Maybe I should change this to let the user type the numbers instead of having to click the relevant buttons!
I guess that's all for now! I don't know if I did a good job at explaining this. If I'm missing anything out or not doing a good job, do point it out to me and I'd be glad to elaborate and do better! And yeah, this code was prettified and highlighted using this awesome website!
As always, any and every comment is appreciated!
Let me briefly explain what is going on in the code.
Button() creates, well, a button, which can then be linked to an action. the _*_button_fired() methods in the Application class are activated when the button is pressed and which do the necessary computation in the background! Similarly @on_trait_change() decorator also does a similar job. The method/function being decorated by such a decorator will be triggered/called when the attribute in the parenthesis changes! Traits takes care of listening to the attributes in the background, making life a lot easier for you!
Coming to how the calculator looks, that is defined in the View. Buttons or Items in general can be organized using the HGroup and VGroup methods, as done with the button layout. The calculated values are shown using a TextEditor object, which we borrowed from traitsUI, and we set it in a readonly mode. Maybe I should change this to let the user type the numbers instead of having to click the relevant buttons!
I guess that's all for now! I don't know if I did a good job at explaining this. If I'm missing anything out or not doing a good job, do point it out to me and I'd be glad to elaborate and do better! And yeah, this code was prettified and highlighted using this awesome website!
As always, any and every comment is appreciated!
# Copyright (c) 2007, Enthought, Inc. # License: BSD Style. """ Implementation of a TableEditor demo plugin for Traits UI demo program This demo shows the full behavior of a straightforward TableEditor. Only one style of TableEditor is implemented, so that is the one shown. """ # Import statements: from traits.api \ import HasTraits, HasStrictTraits, Instance, Int, Str, Button, Float, List, on_trait_change, File, Array from traitsui.api \ import View, Group, VGroup, HGroup, Item, TableEditor, TextEditor, ArrayEditor # The class to be edited with the TableEditor: class Application ( HasStrictTraits ): compute_box = Float(0.0) temp = Float(0.0) count = Int(0) dot = Int(-1) nine_button = Button('9') eight_button = Button('8') seven_button = Button('7') six_button = Button('6') five_button = Button('5') four_button = Button('4') three_button = Button('3') two_button = Button('2') one_button = Button('1') equals_button = Button('=') add_button = Button('+') subtract_button = Button('-') mul_button = Button('*') div_button = Button('/') zero_button = Button('0') dot_button = Button('.') clr_button = Button('clr') def _nine_button_fired(self): if self.dot == -1: self.compute_box = self.compute_box*10 +9.0 else: self.compute_box = (self.compute_box*10**(self.dot) +9.0)/10**(self.dot) self.dot +=1 def _eight_button_fired(self): if self.dot == -1: self.compute_box = self.compute_box*10 +8.0 else: self.compute_box = (self.compute_box*10**(self.dot) +8.0)/10**(self.dot) self.dot +=1 def _seven_button_fired(self): if self.dot == -1: self.compute_box = self.compute_box*10 +7.0 else: self.compute_box = (self.compute_box*10**(self.dot) +7.0)/10**(self.dot) self.dot +=1 def _six_button_fired(self): if self.dot == -1: self.compute_box = self.compute_box*10 +6.0 else: self.compute_box = (self.compute_box*10**(self.dot) +6.0)/10**(self.dot) self.dot +=1 def _five_button_fired(self): if self.dot == -1: self.compute_box = self.compute_box*10 +5.0 else: self.compute_box = (self.compute_box*10**(self.dot) +5.0)/10**(self.dot) self.dot +=1 def _four_button_fired(self): if self.dot == -1: self.compute_box = self.compute_box*10 +4.0 else: self.compute_box = (self.compute_box*10**(self.dot) +4.0)/10**(self.dot) self.dot +=1 def _three_button_fired(self): if self.dot == -1: self.compute_box = self.compute_box*10 +3.0 else: self.compute_box = (self.compute_box*10**(self.dot) +3.0)/10**(self.dot) self.dot +=1 def _two_button_fired(self): if self.dot == -1: self.compute_box = self.compute_box*10 +2.0 else: self.compute_box = (self.compute_box*10**(self.dot) +2.0)/10**(self.dot) self.dot +=1 def _one_button_fired(self): if self.dot == -1: self.compute_box = self.compute_box*10 +1.0 else: self.compute_box = (self.compute_box*10**(self.dot) +1.0)/10**(self.dot) self.dot +=1 def _zero_button_fired(self): # does some weird shit! if self.dot == -1: self.compute_box = self.compute_box*10 # else: # dunno what to do when we want to add # after zero! def _dot_button_fired(self): self.dot = 1 @on_trait_change('equals_button') def eval_expr(self): if self.count == 1: self.compute_box += self.temp elif self.count == -1: self.compute_box -= self.temp elif self.count == 2: self.compute_box = self.compute_box*self.temp elif self.count == -2: self.compute_box = self.temp/self.compute_box def _add_button_fired(self): self.temp = self.compute_box self.compute_box = 0.0 self.count = 1 self.dot = -1 def _subtract_button_fired(self): self.temp = self.compute_box self.compute_box = 0.0 self.count = -1 self.dot = -1 def _mul_button_fired(self): self.temp = self.compute_box self.compute_box = 0.0 self.count = 2 self.dot = -1 def _div_button_fired(self): self.temp = self.compute_box self.compute_box = 0.0 self.count = -2 self.dot = -1 def _clr_button_fired(self): self.temp = 0.0 self.compute_box = 0.0 self.count = 0 self.dot =-1 traits_view = View( VGroup( HGroup(Item('compute_box', label=" ", editor=TextEditor()), Item('temp', label=" ", editor=TextEditor(), style="readonly") ), HGroup( Group( HGroup(Item('nine_button', label=" "), Item('eight_button', label=" "), Item('seven_button', label=" "), ), HGroup(Item('six_button', label=" "), Item('five_button', label=" "), Item('four_button', label=" "), ), HGroup(Item('three_button', label=" "), Item('two_button', label=" "), Item('one_button', label=" "), ) ), VGroup(Item('zero_button', label=" "), Item('clr_button', label=" "), ), ), HGroup(Item('mul_button', label=" "), Item('dot_button', label=" "), Item('div_button', label=" "), ), HGroup(Item('add_button', label=" "), Item('equals_button', label=" "), Item('subtract_button', label=" "), ) ), resizable = True, buttons = [ 'OK' ], kind = 'live', ) # Create the demo: demo = Application() # Run the demo (if invoked from the command line): if __name__ == '__main__': demo.configure_traits()