[Tutor] My best GUI app so far.

Jacob S. keridee at jayco.net
Tue Jan 11 06:34:36 CET 2005


Great! I took the improvements you gave me an added support for keys (So you
can type in 1.25+2= instead of having to type the buttons.) As always, I
encourage improvements to my code. Maybe that will be my disclaimer... I
have always liked and wanted to adopt Liam's.

Oh, by the way, I'm not trying to make you go blind, it's just I don't tend
to worry about *my* eyesight and in my subconcious I'm just not considerate
enough to implement healthy eye habits. sorry...

Perhaps mine eyes should better feast on code of thou?
(I'm trying to sound intellegent -- and probably failing.)
(And no, the sentence is not mocking)

Okay, Jacob, reality check -- it's after midnight...
Here's the code.

###Start of Calculator.py###
from __future__ import division
from Tkinter import *

class Application(Frame):
     def ctb(self):
         if self.shouldblank:
             self.distext.set('')
             self.shouldblank = False

     def adddigit(self, digit, *args):
         self.ctb()
         self.distext.set(self.distext.get()+digit)

     def adddigitdot(self,*args):
         if not self.distext.get().count('.'):
             self.ctb()
             self.distext.set(self.distext.get()+'.')

     def equal(self,*args):
         if self.action:
             self.newnum = self.distext.get()
             self.newnum = str(eval(self.oldnum+self.action+self.newnum))
             self.distext.set(self.newnum)
             self.oldnum = '0'
             self.action = ''
             self.shouldblank = True

     def add(self,*args):
         self.handleOperator('+')

     def subtract(self,*args):
         self.handleOperator('-')

     def multiply(self,*args):
         self.handleOperator('*')

     def divide(self,*args):
         self.handleOperator('/')


     def handleOperator(self, oper):
         if self.action:
             self.equal()
             self.oldnum = self.distext.get()
             self.action = oper
         else:
             self.oldnum = self.distext.get()
             self.action = oper
             self.shouldblank = True


     def clear(self):
         self.action = ''
         self.oldnum = '0'
         self.distext.set('0')
         self.shouldblank = True

     def memrecall(self):
         self.distext.set(self.memory)
         self.shouldblank = True

     def memminus(self):
         self.memory = str(eval(self.memory+"-"+self.distext.get()))
         self.shouldblank = True

     def memplus(self):
         self.memory = str(eval(self.memory+"+"+self.distext.get()))
         self.shouldblank = True


     def makeButton(self, text, command, row, column):
         button = Button(self,text=text,command=command,width=4,height=3)
         button.grid(row=row,column=column)


     def createWidgets(self):
         self.distext = StringVar()
         self.display
=Entry(self,textvariable=self.distext,width=22,justify='right')
         self.display.grid(row=0,column=1,columnspan=4)

         self.makeButton(text='0',command=self.bl[0],row=5,column=1)
         self.makeButton(text='1',command=self.bl[1],row=4,column=1)
         self.makeButton(text='2',command=self.bl[2],row=4,column=2)
         self.makeButton(text='3',command=self.bl[3],row=4,column=3)
         self.makeButton(text='4',command=self.bl[4],row=3,column=1)
         self.makeButton(text='5',command=self.bl[5],row=3,column=2)
         self.makeButton(text='6',command=self.bl[6],row=3,column=3)
         self.makeButton(text='7',command=self.bl[7],row=2,column=1)
         self.makeButton(text='8',command=self.bl[8],row=2,column=2)
         self.makeButton(text='9',command=self.bl[9],row=2,column=3)
         self.makeButton(text='.',command=self.adddigitdot,row=5,column=2)
         self.makeButton(text="=",command=self.equal,row=5,column=3)
         self.makeButton(text='+',command=self.add,row=5,column=4)
         self.makeButton(text="-",command=self.subtract,row=4,column=4)
         self.makeButton(text='x',command=self.multiply,row=3,column=4)
         self.makeButton(text='/',command=self.divide,row=2,column=4)
         self.makeButton(text='ON/C',command=self.clear,row=1,column=4)
         self.makeButton(text='MRC',command=self.memrecall,row=1,column=1)
         self.makeButton(text="M-",command=self.memminus,row=1,column=2)
         self.makeButton(text="M+",command=self.memplus,row=1,column=3)


     def __init__(self, master=None):
         Frame.__init__(self,master)
         self.master.title("Calculator by Jacob, Inc.")
         self.pack(expand=True)
         m = lambda x: self.adddigit(x)
         self.bl = [lambda *x: self.adddigit('0',x),
                    lambda *x: self.adddigit('1',x),
                    lambda *x: self.adddigit('2',x),
                    lambda *x: self.adddigit('3',x),
                    lambda *x: self.adddigit('4',x),
                    lambda *x: self.adddigit('5',x),
                    lambda *x: self.adddigit('6',x),
                    lambda *x: self.adddigit('7',x),
                    lambda *x: self.adddigit('8',x),
                    lambda *x: self.adddigit('9',x)]
         for y in range(10):
             self.bind_all(str(y),self.bl[y])
         self.bind_all("+",lambda x: self.add(x))
         self.bind_all("-",lambda x: self.subtract(x))
         self.bind_all("*",lambda x: self.multiply(x))
         self.bind_all("/",lambda x: self.divide(x))
         self.bind_all("=",lambda x: self.equal(x))
         self.bind_all(".",lambda x: self.adddigitdot(x))
         self.oldnum = '0'
         self.memory = '0'
         self.action = ''
         self.shouldblank = True
         self.createWidgets()

app = Application()
app.mainloop()
###End of Calculator.py###




> My suggestions:
>
> - How about some white space! Yikes, you trying to make me go blind?
> - You don't actually need to save all the buttons to attributes.
> - Much of the button creation is common - I made a button creating
function and call that.
>    Copy / paste is not your friend, it is a danger! Refactor instead of
copying!
> - Now you can get rid of all the adddigit functions by making a single
generic adddigit
>    and calling it with a lambda.
> - The four operation functions are identical except the operator; factor
out handleOperation()
>    (Copy / paste is not your friend!)
>
> - I didn't put the button generation in a loop, once you strip out the
repeated arguments what is
> left is pretty readable as is.
>
> Kent
>
>
> from __future__ import division
> from Tkinter import *
>
> class Application(Frame):
>      def ctb(self):
>          if self.shouldblank:
>              self.distext.set('')
>              self.shouldblank = False
>
>      def adddigit(self, digit):
>          self.ctb()
>          self.distext.set(self.distext.get()+digit)
>
>      def adddigitdot(self):
>          if not self.distext.get().count('.'):
>              self.ctb()
>              self.distext.set(self.distext.get()+'.')
>
>      def equal(self):
>          if self.action:
>              self.newnum = self.distext.get()
>              self.newnum = str(eval(self.oldnum+self.action+self.newnum))
>              self.distext.set(self.newnum)
>              self.oldnum = '0'
>              self.action = ''
>              self.shouldblank = True
>
>      def add(self):
>          self.handleOperator('+')
>
>      def subtract(self):
>          self.handleOperator('-')
>
>      def multiply(self):
>          self.handleOperator('*')
>
>      def divide(self):
>          self.handleOperator('/')
>
>
>      def handleOperator(self, oper):
>          if self.action:
>              self.equal()
>              self.oldnum = self.distext.get()
>              self.action = oper
>          else:
>              self.oldnum = self.distext.get()
>              self.action = oper
>              self.shouldblank = True
>
>
>      def clear(self):
>          self.action = ''
>          self.oldnum = '0'
>          self.distext.set('0')
>          self.shouldblank = True
>
>      def memrecall(self):
>          self.distext.set(self.memory)
>          self.shouldblank = True
>
>      def memminus(self):
>          self.memory = str(eval(self.memory+"-"+self.distext.get()))
>          self.shouldblank = True
>
>      def memplus(self):
>          self.memory = str(eval(self.memory+"+"+self.distext.get()))
>          self.shouldblank = True
>
>
>      def makeButton(self, text, command, row, column):
>          button = Button(self,text=text,command=command,width=4,height=3)
>          button.grid(row=row,column=column)
>
>
>      def createWidgets(self):
>          self.distext = StringVar()
>          self.display
=Entry(self,textvariable=self.distext,width=22,justify='right')
>          self.display.grid(row=0,column=1,columnspan=4)
>
>          self.makeButton(text='0',command=lambda:
self.adddigit('0'),row=5,column=1)
>          self.makeButton(text='1',command=lambda:
self.adddigit('1'),row=4,column=1)
>          self.makeButton(text='2',command=lambda:
self.adddigit('2'),row=4,column=2)
>          self.makeButton(text='3',command=lambda:
self.adddigit('3'),row=4,column=3)
>          self.makeButton(text='4',command=lambda:
self.adddigit('4'),row=3,column=1)
>          self.makeButton(text='5',command=lambda:
self.adddigit('5'),row=3,column=2)
>          self.makeButton(text='6',command=lambda:
self.adddigit('6'),row=3,column=3)
>          self.makeButton(text='7',command=lambda:
self.adddigit('7'),row=2,column=1)
>          self.makeButton(text='8',command=lambda:
self.adddigit('8'),row=2,column=2)
>          self.makeButton(text='9',command=lambda:
self.adddigit('9'),row=2,column=3)
>          self.makeButton(text='.',command=self.adddigitdot,row=5,column=2)
>          self.makeButton(text="=",command=self.equal,row=5,column=3)
>          self.makeButton(text='+',command=self.add,row=5,column=4)
>          self.makeButton(text="-",command=self.subtract,row=4,column=4)
>          self.makeButton(text='x',command=self.multiply,row=3,column=4)
>          self.makeButton(text='/',command=self.divide,row=2,column=4)
>          self.makeButton(text='ON/C',command=self.clear,row=1,column=4)
>          self.makeButton(text='MRC',command=self.memrecall,row=1,column=1)
>          self.makeButton(text="M-",command=self.memminus,row=1,column=2)
>          self.makeButton(text="M+",command=self.memplus,row=1,column=3)
>
>
>      def __init__(self, master=None):
>          Frame.__init__(self,master)
>          self.master.title("Calculator by Jacob, Inc.")
>          self.pack(fill='both')
>          self.oldnum = '0'
>          self.memory = '0'
>          self.action = ''
>          self.shouldblank = True
>          self.createWidgets()
>
> app = Application()
> app.mainloop()
> ### End of Calculator.py ###
>
>
>
> Jacob S. wrote:
> > Here's the code. If you have time, look it over and give me suggestions
for
> > improvement!
> > (big toothy grin)
> >
> > ### Start of Calculator.py ###
> > from __future__ import division
> > from Tkinter import *
> >
> > class Application(Frame):
> >     def ctb(self):
> >         if self.shouldblank:
> >             self.distext.set('')
> >             self.shouldblank = False
> >     def adddigit0(self):
> >         self.ctb()
> >         self.distext.set(self.distext.get()+'0')
> >     def adddigit1(self):
> >         self.ctb()
> >         self.distext.set(self.distext.get()+'1')
> >     def adddigit2(self):
> >         self.ctb()
> >         self.distext.set(self.distext.get()+'2')
> >     def adddigit3(self):
> >         self.ctb()
> >         self.distext.set(self.distext.get()+'3')
> >     def adddigit4(self):
> >         self.ctb()
> >         self.distext.set(self.distext.get()+'4')
> >     def adddigit5(self):
> >         self.ctb()
> >         self.distext.set(self.distext.get()+'5')
> >     def adddigit6(self):
> >         self.ctb()
> >         self.distext.set(self.distext.get()+'6')
> >     def adddigit7(self):
> >         self.ctb()
> >         self.distext.set(self.distext.get()+'7')
> >     def adddigit8(self):
> >         self.ctb()
> >         self.distext.set(self.distext.get()+'8')
> >     def adddigit9(self):
> >         self.ctb()
> >         self.distext.set(self.distext.get()+'9')
> >     def adddigitdot(self):
> >         if not self.distext.get().count('.'):
> >             self.ctb()
> >             self.distext.set(self.distext.get()+'.')
> >     def equal(self):
> >         if self.action:
> >             self.newnum = self.distext.get()
> >             self.newnum = str(eval(self.oldnum+self.action+self.newnum))
> >             self.distext.set(self.newnum)
> >             self.oldnum = '0'
> >             self.action = ''
> >             self.shouldblank = True
> >     def add(self):
> >         if self.action:
> >             self.equal()
> >             self.oldnum = self.distext.get()
> >             self.action = '+'
> >         else:
> >             self.oldnum = self.distext.get()
> >             self.action = '+'
> >             self.shouldblank = True
> >     def subtract(self):
> >         if self.action:
> >             self.equal()
> >             self.oldnum = self.distext.get()
> >             self.action = '-'
> >         else:
> >             self.oldnum = self.distext.get()
> >             self.action = '-'
> >             self.shouldblank = True
> >     def multiply(self):
> >         if self.action:
> >             self.equal()
> >             self.oldnum = self.distext.get()
> >             self.action = '*'
> >         else:
> >             self.oldnum = self.distext.get()
> >             self.action = '*'
> >             self.shouldblank = True
> >     def divide(self):
> >         if self.action:
> >             self.equal()
> >             self.oldnum = self.distext.get()
> >             self.action = '/'
> >         else:
> >             self.oldnum = self.distext.get()
> >             self.action = '/'
> >             self.shouldblank = True
> >     def clear(self):
> >         self.action = ''
> >         self.oldnum = '0'
> >         self.distext.set('0')
> >         self.shouldblank = True
> >     def memrecall(self):
> >         self.distext.set(self.memory)
> >         self.shouldblank = True
> >     def memminus(self):
> >         self.memory = str(eval(self.memory+"-"+self.distext.get()))
> >         self.shouldblank = True
> >     def memplus(self):
> >         self.memory = str(eval(self.memory+"+"+self.distext.get()))
> >         self.shouldblank = True
> >
> >
> >
> >     def createWidgets(self):
> >         self.distext = StringVar()
> >         self.display =
> > Entry(self,textvariable=self.distext,width=22,justify='right')
> >         self.display.grid(row=0,column=1,columnspan=4)
> >
> >         self.b0 =
> > Button(self,text='0',command=self.adddigit0,width=4,height=3)
> >         self.b0.grid(row=5,column=1)
> >         self.b1 =
> > Button(self,text='1',command=self.adddigit1,width=4,height=3)
> >         self.b1.grid(row=4,column=1)
> >         self.b2 =
> > Button(self,text='2',command=self.adddigit2,width=4,height=3)
> >         self.b2.grid(row=4,column=2)
> >         self.b3 =
> > Button(self,text='3',command=self.adddigit3,width=4,height=3)
> >         self.b3.grid(row=4,column=3)
> >         self.b4 =
> > Button(self,text='4',command=self.adddigit4,width=4,height=3)
> >         self.b4.grid(row=3,column=1)
> >         self.b5 =
> > Button(self,text='5',command=self.adddigit5,width=4,height=3)
> >         self.b5.grid(row=3,column=2)
> >         self.b6 =
> > Button(self,text='6',command=self.adddigit6,width=4,height=3)
> >         self.b6.grid(row=3,column=3)
> >         self.b7 =
> > Button(self,text='7',command=self.adddigit7,width=4,height=3)
> >         self.b7.grid(row=2,column=1)
> >         self.b8 =
> > Button(self,text='8',command=self.adddigit8,width=4,height=3)
> >         self.b8.grid(row=2,column=2)
> >         self.b9 =
> > Button(self,text='9',command=self.adddigit9,width=4,height=3)
> >         self.b9.grid(row=2,column=3)
> >         self.bdot =
> > Button(self,text='.',command=self.adddigitdot,width=4,height=3)
> >         self.bdot.grid(row=5,column=2)
> >         self.equalsign =
> > Button(self,text="=",command=self.equal,width=4,height=3)
> >         self.equalsign.grid(row=5,column=3)
> >         self.plussign =
> > Button(self,text='+',command=self.add,width=4,height=3)
> >         self.plussign.grid(row=5,column=4)
> >         self.minussign =
> > Button(self,text="-",command=self.subtract,width=4,height=3)
> >         self.minussign.grid(row=4,column=4)
> >         self.timessign =
> > Button(self,text='x',command=self.multiply,width=4,height=3)
> >         self.timessign.grid(row=3,column=4)
> >         self.divsign =
> > Button(self,text='/',command=self.divide,width=4,height=3)
> >         self.divsign.grid(row=2,column=4)
> >         self.clearb =
> > Button(self,text='ON/C',command=self.clear,width=4,height=3)
> >         self.clearb.grid(row=1,column=4)
> >         self.mrc =
> > Button(self,text='MRC',command=self.memrecall,width=4,height=3)
> >         self.mrc.grid(row=1,column=1)
> >         self.mm =
> > Button(self,text="M-",command=self.memminus,width=4,height=3)
> >         self.mm.grid(row=1,column=2)
> >         self.mp =
> > Button(self,text="M+",command=self.memplus,width=4,height=3)
> >         self.mp.grid(row=1,column=3)
> >
> >
> >     def __init__(self, master=None):
> >         Frame.__init__(self,master)
> >         self.master.title("Calculator by Jacob, Inc.")
> >         self.pack(fill='both')
> >         self.oldnum = '0'
> >         self.memory = '0'
> >         self.action = ''
> >         self.shouldblank = True
> >         self.createWidgets()
> >
> > app = Application()
> > app.mainloop()
> > ### End of Calculator.py ###
> >
> > Is there some way that I could loop over those button definitions?
> >
> > proposal - code
> >
> > a = """
> > def adddigit%s(self):
> >     self.ctb()
> >     self.distext.set(self.distext.get()+'%s')
> > """
> > for i in range(10):
> >     exec a % (i,i)
> >
> > Pretty cool, huh? I've got my thinking cap on today!
> >
> > Thanks in advance for suggestions,
> > Jacob
> >
> >
> > _______________________________________________
> > Tutor maillist  -  Tutor at python.org
> > http://mail.python.org/mailman/listinfo/tutor
> >
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
>
>



More information about the Tutor mailing list