Thread: Tkinter Help!

    #1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    2
    Rep Power
    0

    Tkinter Help!


    Hey guys, so I'm working on a simple calculator project for Python (using Tkinter) and have encountered a problem which, try as I might, cannot solve. Here's the code so far.

    Code:
    from tkinter import *
    
    root = Tk()
    root.geometry("30x130")
    
    def explain():
        print("This is a simple calculator interface which can add and subtract values \nup to 999.")
    
    def fillDisplay(x):
        EntryBox.insert(0, str(x))
    
    def clearDisplay():
        EntryBox.delete(0, END)
        
    menubar = Menu(root)
    menubar.add_command(label="What is this?", command=explain)
    
    EntryBox = Entry(root, width=7)
    EntryBox.grid(row=0, columnspan=3)
    
    for x in range(7, 10):
        Button(root, text=str(x), command=fillDisplay(x)).grid(row=1, column=(x-7), sticky=W)
    
    for x in range(4, 7):
        Button(root, text=str(x), command=fillDisplay(x)).grid(row=2, column=(x-4), sticky=W)
    
    for x in range(1, 4):
        Button(root, text=str(x), command=fillDisplay(x)).grid(row=3, column=(x-1), sticky=W)
    
    Button(root, text="0", command=fillDisplay(0)).grid(row=4, sticky=W)
    Button(root, text="+").grid(row=4, column=1, sticky=W)
    Button(root, text="-").grid(row=4, column=2, sticky=W)
    
    Button(root, text="=", width=4).grid(row=0, column=5, rowspan=2, columnspan=2, stick=S)
    Button(root, text="Clear", height=2, command=clearDisplay).grid(row=2, column=5, rowspan=2, columnspan=2, stick=N)
    
    root.config(menu=menubar)
    
    mainloop()
    So it's a pretty simple interface, with just the digits 0-9 (as buttons), a plus button, a minus button, an equals button and a clear button. There's also an Entry widget to be used as a display.

    The problem:
    The buttons 0-9 aren't working. Instead of pasting the number they have on them to the display when clicked, they do it at startup (so the Entry box starts out with 321654987 in it). No idea what's happening, it might be something to do with the way I have set up the "fillDisplay" function.
  2. #2
  3. Commie Mutant Traitor
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Jun 2004
    Location
    Norcross, GA (again)
    Posts
    1,804
    Rep Power
    1569
    The primary cause of the problem is that the command option for the Button class c'tor expects a function or method, which would have to be passed without its argument list:

    Code:
        Button(root, text=str(x), command=fillDisplay).grid(row=1, column=(x-7), sticky=W)
    Unfortunately, this presents a different problem, in that the callback cannot take an argument, but the fillDisplay() function expects one. There is no way to pass the value to fillDisplay() as it is now defined.

    The solution - a bit heavyweight, but nonetheless workable - is to define a subclass of the Button class, which should pass one of its methods as the callback.

    Code:
     class NumberButton(Button):
         def __init__(self, parent, number, display):
             Button.__init__(self, parent, text=number, command=self.fillDisplay)
             self.value = number
             self.display = display
         def fillDisplay(self):
            self.display.insert(0, str(self.value))
    Note that, in order to have the declaration of the new class as general as possible, I have both the parent window and the Entry box passed as arguments to the c'tor.

    Now, this is all well and good, except that it inserts the values in the wrong order. A bit of string-shuffling will fix that, however. Below is a complete working version of your code.

    Python Code:
    from tkinter import *
    import tkinter.messagebox as mb
     
    class NumberButton(Button):
        def __init__(self, parent, number, display):
            Button.__init__(self, parent, text=number, command=self.fillDisplay)
            self.value = number
            self.display = display
     
        def fillDisplay(self):
            curr_value = self.display.get()
            if curr_value == '0':
                new_value = str(self.value)
            else:
                new_value = ''.join([curr_value, str(self.value)])
            self.display.delete(0, END)
            self.display.insert(0, new_value)
     
    def explain():
        mb.showinfo("About", "This is a simple calculator interface which can add and subtract values \nup to 999.", icon=mb.INFO)
     
     
    def clearDisplay():
        EntryBox.delete(0, END)
        EntryBox.insert(0, '0')
     
    root = Tk()
    root.geometry("175x140")
    root.title = "Calculator"
     
    menubar = Menu(root)
    menubar.add_command(label="About", command=explain)
     
    EntryBox = Entry(root, justify=RIGHT, width=7)
    EntryBox.grid(row=0, columnspan=3)
    EntryBox.insert(0, '0')
     
    # store a reference to the NumberButtons in a dictionary indexed on the 
    # value of the button
    number = dict()
    number[0] = NumberButton(root, 0, EntryBox).grid(row=4, sticky=W)
    for x in range(7, 10):
        number[x] = NumberButton(root, x, EntryBox).grid(row=1, column=(x-7), sticky=W)
     
    for x in range(4, 7):
        number[x] = NumberButton(root, x, EntryBox).grid(row=2, column=(x-4), sticky=W)
     
    for x in range(1, 4):
        number[x] = NumberButton(root, x, EntryBox).grid(row=3, column=(x-1), sticky=W)
     
     
    Button(root, text="+").grid(row=4, column=1, sticky=W)
    Button(root, text="-").grid(row=4, column=2, sticky=W)
     
    Button(root, text="=", width=4).grid(row=0, column=5, rowspan=2, columnspan=2, stick=S)
    Button(root, text="Clear", height=2, command=clearDisplay).grid(row=2, column=5, rowspan=2, columnspan=2, stick=N)
     
    root.config(menu=menubar)
     
    mainloop()
    Rev First Speaker Schol-R-LEA;2 JAM LCF ELF KoR KCO BiWM TGIF
    #define KINSEY (rand() % 7) λ Scheme is the Red Pill
    Scheme in Short Understanding the C/C++ Preprocessor
    Taming Python A Highly Opinionated Review of Programming Languages for the Novice, v1.1

    FOR SALE: One ShapeSystem 2300 CMD, extensively modified for human use. Includes s/w for anthro, transgender, sex-appeal enhance, & Gillian Anderson and Jason D. Poit clone forms. Some wear. $4500 obo. tverres@et.ins.gov
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    2
    Rep Power
    0
    Wow, that was... amazing. Detailed, informative, just amazing man. You explained everything so that a noob like me could understand. ^^

    Thanks a bunch!

IMN logo majestic logo threadwatch logo seochat tools logo