I have a lot more code than I'm going to post here, but I am posting the relevant parts.
What I have is a Calculator program. Here's the code:

num1 = None
num2 = None
oper = None

def calculate(num1, num2, oper):
    print("calculate() called")
    if(oper=="+"):
        answ = Decimal(num1) + Decimal(num2)
        return answ
    elif(oper=="-"):
        pass
    elif(oper=="*"):
        pass
    elif(oper=="/"):
        pass
    elif(oper=="^"):
        pass
    elif(oper=="%"):
        pass
    else:
        pass

def addPressedF():
    print("addPressedF() called")
    num1 = dfSV.get()
    print(num1)
    oper = "+"
    root.title("Calculator - '+'")
    dfSV.set("")

def equPressedF(num1, num2):
    print("equPressedF() called")
    num2 = dfSV.get()
    print(num1)
    print(num2)
    dfSV.set(calculate(num1, num2, oper))

When someone presses a number button (say, '1') it takes the numbers in the Entry and
adds the number to the end of it (so, entry holds '432', after button pressed, '4321').

After I type three numbers (125) and press '+' it says num1 = 125.
After a couple more numbers (75) and press '=' it says that num1 = None, num2 = 75.
And the Calculate function displays 'None' in the Entry.

I've defined the 'oper' variable in functions the same way as these work.

If I remove the 'var = None' lines then it says that "global name 'num1' is not defined."

So, what am I doing wrong? I looked into functions (online, daniweb) and haven't found
it yet.

- WolfShield

Recommended Answers

All 10 Replies

you should pass it as parameter or read from stringvar

WolfShield: You've omitted some crucial details here, starting with, what GUI library you're using (I'd normally assume TkInter, since that's bundled with Python, but this doesn't seem like Python/Tk code). While it is not exactly relevant to the code section in question, it does make it harder to judge where the error is occurring.

Tonyjv: If you look, WS is in fact passing the values as parameters when calling calculate() in the equPressedF() event handler. The problem is, the function doesn't seem to be using the passed values, for some reason.

Or perhaps not... I suspect that the error is coming up in equPressedF() rather than in calculate() . WolfShield, could you please post the traceback that you get when you omit the globals?

Where are the values being passed to equPressedF() meant to be coming from? I am guessing that you intend for them to be read from a pair of textboxes, correct? so where are you reading the values in those?

You might want to decompose the code a bit more, separating the implementation of the calculate() function from the GUI code. This should make testing the parts easier. I tried the following successfully:

def calculate(num1, num2, oper):
    """ Function to act as a simple six-function calculator.
    
    arguments:
        num1 -- first argument of the operation
        num2 -- second argument of the operation
        oper -- string representing the operation to perform
    """
    print("calculate() called")
    if(oper=="+"):
        answ = num1 + num2
        return answ
    elif(oper=="-"):
        pass
    elif(oper=="*"):
        pass
    elif(oper=="/"):
        pass
    elif(oper=="^"):
        pass
    elif(oper=="%"):
        pass
    else:
        pass


if __name__ == "__main__":
    print calculate(2, 2, '+')

This should be easy to import into your GUI code without tying to the sections together quite so deeply.

To illustrate that the function is correct:

from decimal import Decimal
def calculate(num1, num2, oper):
    if(oper=="+"):
        answ = Decimal(num1) + Decimal(num2)
        return answ
    return 0
        
ret_ans = 0
for x in range(1, 6):
    print "%d + %d =" % (ret_ans, x),
    ret_ans = calculate(ret_ans, x, "+")
    print ret_ans

It will be easier to give you guys all of the code.

I am using Tk / tkinter library (8.5), Python 3.2.0.0 (ActivePython):

from tkinter import *
from tkinter import ttk
from decimal import *

# Set Up Decimal Formating
getcontext().prec = 30

# Functions
# =================================================================================================
# Button and Key Functions
def oneBPressed():
    print("oneBPressed() called")
    onePressedF()

def twoBPressed():
    print("twoBPressed() called")
    twoPressedF()

def threeBPressed():
    print("threeBPressed() called")
    threePressedF()

def fourBPressed():
    print("fourBPressed() called")
    fourPressedF()

def fiveBPressed():
    print("fiveBPressed() called")
    fivePressedF()

def sixBPressed():
    print("sixBPressed() called")
    sixPressedF()

def sevenBPressed():
    print("sevenBPressed() called")
    sevenPressedF()

def eightBPressed():
    print("eightBPressed() called")
    eightPressedF()

def nineBPressed():
    print("nineBPressed() called")
    ninePressedF()

def zeroBPressed():
    print("zeroBPressed() called")
    zeroPressedF()

def decBPressed():
    print("decBPressed() called")
    decPressedF()

def addBPressed():
    print("addBPressed() called")
    addPressedF()

def subBPressed():
    print("subBPressed() called")
    subPressedF()

def mulBPressed():
    print("mulBPressed() called")
    mulPressedF()

def divBPressed():
    print("divBPressed() called")
    divPressedF()

def bckspBPressed():
    print("bckspBPressed() called")
    bckspPressedF()

def cBPressed():
    print("cBPressed() called")
    cPressedF()

def ceBPressed():
    print("ceBPressed() called")
    cePressedF()

def rndBPressed():
    print("rndBPressed() called")
    rndPressedF()

def modBPressed():
    print("modBPressed() called")
    modPressedF()

def posnegBPressed():
    print("posnegBPressed() called")
    posnegPressedF()

def powBPressed():
    print("powBPressed() called")
    powPressedF()

def sqrtBPressed():
    print("sqrtBPressed() called")
    sqrtPressedF()

def piBPressed():
    print("piBPressed() called")
    piPressedF()

def equBPressed():
    print("equBPressed() called")
    equPressedF(num1, num2)


# Create Window
root = Tk()
root.title("Calculator")
root.resizable(0,0)

# Calculator TextField
dfSV = StringVar()
dsplyF = Entry(root, textvariable=dfSV)
dsplyF['state'] = 'readonly'
dsplyF['readonlybackground']='white'
dsplyF['foreground']='purple'
dfSV.set("")

# Calculator ScrollBar
calcSB = ttk.Scrollbar(root, orient=HORIZONTAL, command=dsplyF.xview)
dsplyF['xscrollcommand'] = calcSB.set

# Button Styles
style1 = ttk.Style().configure("TButton", foreground="blue")
style = ttk.Style()
style.map("C.TButton", foreground=[('pressed', 'red'), ('active', 'black')], background=[('pressed', '!disabled', 'black'), ('active', 'white')])


# Create Buttons
# - Number Buttons -
oneB = ttk.Button(root, text="1", command=oneBPressed, width=7, style="C.TButton") # cmd: oneBPressed
twoB = ttk.Button(root, text="2", command=twoBPressed, width=7, style="C.TButton") # cmd: twoBPressed
threeB = ttk.Button(root, text="3", command=threeBPressed, width=7, style="C.TButton") # cmd: threeBPressed
fourB = ttk.Button(root, text="4", command=fourBPressed, width=7, style="C.TButton") # cmd: fourBPressed
fiveB = ttk.Button(root, text="5", command=fiveBPressed, width=7, style="C.TButton") # cmd: fiveBPressed
sixB = ttk.Button(root, text="6", command=sixBPressed, width=7, style="C.TButton") # cmd: sixBPressed
sevenB = ttk.Button(root, text="7", command=sevenBPressed, width=7, style="C.TButton") # cmd: sevenBPressed
eightB = ttk.Button(root, text="8", command=eightBPressed, width=7, style="C.TButton") # cmd: eightBPressed
nineB = ttk.Button(root, text="9", command=nineBPressed, width=7, style="C.TButton") # cmd: nineBPressed
zeroB = ttk.Button(root, text="0", command=zeroBPressed, style="C.TButton") # cmd: zeroBPressed
# - Operator Buttons -
addB = ttk.Button(root, text="+", command=addBPressed, width=7, style="C.TButton") # cmd: addBPressed
subB = ttk.Button(root, text="-", command=subBPressed, width=7, style="C.TButton") # cmd: subBPressed
mulB = ttk.Button(root, text="*", command=mulBPressed, width=7, style="C.TButton") # cmd: mulBPressed
divB = ttk.Button(root, text="/", command=divBPressed, width=7, style="C.TButton") # cmd: divBPressed
modB = ttk.Button(root, text="%", command=modBPressed, width=7, style="C.TButton") # cmd: modBPressed
powB = ttk.Button(root, text="^", command=powBPressed, width=7, style="C.TButton") # cmd: powBPressed
sqrtB = ttk.Button(root, text="sqrt", command=sqrtBPressed, width=7, style="C.TButton") # cmd: sqrtBPressed
piB = ttk.Button(root, text="pi", command=piBPressed, width=7, style="C.TButton") # cmd: piBPressed
posnegB = ttk.Button(root, text="+/-", command=posnegBPressed, style="C.TButton") # cmd: posnegBPressed
equB = ttk.Button(root, text="=", command=equBPressed, width=7, style="C.TButton") # cmd: equBPressed
# - Other Buttons
bckspB = ttk.Button(root, text="<- Backspace", command=bckspBPressed, style="C.TButton") # cmd: bckspBPressed
rndB = ttk.Button(root, text="Round", command=rndBPressed, width=7, style="C.TButton") # cmd: rndBPressed
cB = ttk.Button(root, text="C", command=cBPressed, width=7, style="C.TButton") # cmd: cBPressed
ceB = ttk.Button(root, text="CE", command=ceBPressed, width=7, style="C.TButton") # cmd: ceBPressed
decB = ttk.Button(root, text=".", command=decBPressed, width=7, style="C.TButton") # cmd: decBPressed

# Grid Objects
dsplyF.grid(column=0, row=0, columnspan=7, sticky=(W,E))
calcSB.grid(column=0, row=1, pady=(0,10), columnspan=7, sticky=(W,E))
oneB.grid(column=0, row=2)
twoB.grid(column=1, row=2)
threeB.grid(column=2, row=2)
fourB.grid(column=0, row=3)
fiveB.grid(column=1, row=3)
sixB.grid(column=2, row=3)
sevenB.grid(column=0, row=4)
eightB.grid(column=1, row=4)
nineB.grid(column=2, row=4)
zeroB.grid(column=0, row=5, columnspan=2, sticky=(W,E))
decB.grid(column=2, row=5)
addB.grid(column=3, row=2, padx=(15,15))
subB.grid(column=3, row=3, padx=(15,15))
mulB.grid(column=3, row=4, padx=(15,15))
divB.grid(column=3, row=5, padx=(15,15))
bckspB.grid(column=4, row=2, columnspan=2, sticky=(W,E))
cB.grid(column=4, row=3)
rndB.grid(column=5, row=3)
ceB.grid(column=4, row=4)
modB.grid(column=5, row=4)
posnegB.grid(column=4, row=5, columnspan=2, sticky=(W,E))
powB.grid(column=6, row=2, padx=(15,0))
sqrtB.grid(column=6, row=3, padx=(15,0))
piB.grid(column=6, row=4, padx=(15,0))
equB.grid(column=6, row=5, padx=(15,0))


num1 = None
num2 = None
oper = None

# ====================================================================================================
# Main Functions
def calculate(num1, num2, oper):
    print("calculate() called")
    if(oper=="+"):
        answ = Decimal(num1) + Decimal(num2)
        return answ
    elif(oper=="-"):
        pass
    elif(oper=="*"):
        pass
    elif(oper=="/"):
        pass
    elif(oper=="^"):
        pass
    elif(oper=="%"):
        pass
    else:
        pass


# Button Functions
def onePressedF():
    print("onePressedF() called")
    dfSV.set(dfSV.get()+"1")

def twoPressedF():
    print("twoPressedF() called")
    dfSV.set(dfSV.get()+"2")

def threePressedF():
    print("threePressedF() called")
    dfSV.set(dfSV.get()+"3")

def fourPressedF():
    print("fourPressedF() called")
    dfSV.set(dfSV.get()+"4")

def fivePressedF():
    print("fivePressedF() called")
    dfSV.set(dfSV.get()+"5")

def sixPressedF():
    print("sixPressedF() called")
    dfSV.set(dfSV.get()+"6")

def sevenPressedF():
    print("sevenPressedF() called")
    dfSV.set(dfSV.get()+"7")

def eightPressedF():
    print("eightPressedF() called")
    dfSV.set(dfSV.get()+"8")

def ninePressedF():
    print("ninePressedF() called")
    dfSV.set(dfSV.get()+"9")

def zeroPressedF():
    print("zeroPressedF() called")
    dfSV.set(dfSV.get()+"0")

def decPressedF():
    print("decPressedF() called")
    tempV = dfSV.get()
    if(tempV.find(".")==-1):
        if(tempV==""):
            tempV += "0."
        else:
            tempV += "."
    else:
        pass
    dfSV.set(tempV)

def addPressedF():
    print("addPressedF() called")
    num1 = dfSV.get()
    print(num1)
    oper = "+"
    root.title("Calculator - '+'")
    dfSV.set("")

def subPressedF():
    print("subPressedF() called")
    num1 = dfSV.get()
    oper = "-"
    root.title("Calculator - '-'")
    dfSV.set("")

def mulPressedF():
    print("mulPressedF() called")
    num1 = dfSV.get()
    oper = "*"
    root.title("Calculator - '*'")
    dfSV.set("")

def divPressedF():
    print("divPressedF() called")
    num1 = dfSV.get()
    oper = "/"
    root.title("Calculator - '/'")
    dfSV.set("")

def bckspPressedF():
    print("bckspPressedF() called")
    dfSV.set(dfSV.get()[0:-1])

def cPressedF():
    print("cPressedF() called")
    num1 = None
    oper = None
    num2 = None
    answ = None
    dfSV.set("")

def cePressedF():
    print("cePressedF() called")
    dfSV.set("")

def rndPressedF():
    print("rndPressedF() called")
    dfSV.set(Decimal(dfSV.get()).quantize(Decimal('.01')))

def modPressedF():
    print("modPressedF() called")
    num1 = dfSV.get()
    oper = "%"
    root.title("Calculator - '%'")

def posnegPressedF():
    print("posnegPressedF() called")
    if(dfSV.get().find("-")==-1):
        dfSV.set("-"+dfSV.get())
    else:
        dfSV.set(dfSV.get().replace('-',''))

def powPressedF():
    print("powPressedF() called")
    num1 = dfSV.get()
    oper = "^"
    root.title("Calculator - '^'")
    dfSV.set("")

def sqrtPressedF():
    print("sqrtPressedF() called")
    dfSV.set(Decimal(dfSV.get()).sqrt())

def piPressedF():
    print("piPressedF() called")
    dfSV.set("3.1415926535897932384626433")

def equPressedF(num1, num2):
    print("equPressedF() called")
    num2 = dfSV.get()
    print(num1)
    print(num2)
    dfSV.set(calculate(num1, num2, oper))

# Mainloop for root window
root.mainloop()

When I run it like I said above (first post: 125 + 75 = ), it gives me this output (in
console):

oneBPressed() called
onePressedF() called
twoBPressed() called
twoPressedF() called
fiveBPressed() called
fivePressedF() called
addBPressed() called
addPressedF() called
125
sevenBPressed() called
sevenPressedF() called
fiveBPressed() called
fivePressedF() called
equBPressed() called
equPressedF() called
None
75
calculate() called

And displays 'None' in the Entry.

When I remove the global variables the output is:

oneBPressed() called
onePressedF() called
twoBPressed() called
twoPressedF() called
fiveBPressed() called
fivePressedF() called
addBPressed() called
addPressedF() called
125
sevenBPressed() called
sevenPressedF() called
fiveBPressed() called
fivePressedF() called
equBPressed() called
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python32\lib\tkinter\__init__.py", line 1399, in __call__
    return self.func(*args)
  File "C:\Users\===Blank===\Calculator\MaxCalc.py", line 111, in equBPressed
    equPressedF(num1, num2)
NameError: global name 'num1' is not defined

I know that is a REALLY long post, but only giving some information would not of helped.

So, now that your eyes are spinning and my terrible code, think you know how to fix it? :)

Thanks,

- WolfShield

I have no time right now, but the error message is correct, equBPressed() has no knowledge of num1 or num2 because they were not passed to the function. You should be using a class for this as it solves a lot of those problems with self.var which is visible to all functions in the class; self.X_O_dict in the following program for example, For now, take a look at how this program uses "partial" to pass the button number to a common function.

from Tkinter import *
from functools import partial

class TicTacToe:
   def __init__(self, top):
      self.top = top
      self.button_dic = {}     ## pointer to buttons and StringVar()
      self.X_O_dict = {"X":[], "O":[]}  ## list of "X" and "O" moves
      self.top.title('Buttons TicTacToe Test')
      self.top_frame = Frame(self.top, width =500, height=500)
      self.buttons()
      self.top_frame.grid(row=0, column=1)

      exit = Button(self.top_frame, text='Exit', \
             command=self.top.quit).grid(row=10,column=0, columnspan=5)

      self.player = True   ## True = "X", False = "O"

   ##-------------------------------------------------------------------         
   def buttons(self):
      """ create 9 buttons, a 3x3 grid
      """
      b_row=1
      b_col=0
      for j in range(1, 10):
         self.button_dic[j] = StringVar()
         self.button_dic[j].set(str(j))
         b = Button(self.top_frame, textvariable = self.button_dic[j], \
                    command=partial(self.cb_handler, j))
         b.grid(row=b_row, column=b_col)

         b_col += 1
         if b_col > 2:
            b_col = 0
            b_row += 1

   ##----------------------------------------------------------------
   def cb_handler( self, square_number ):
      if self.player:                       ## True = "X", False = "O"
         player = "X"
      else:
         player = "O"

      ##--- square not already occupied
      if square_number not in self.X_O_dict["X"] and \
         square_number not in self.X_O_dict["O"]:

         self.button_dic[square_number].set(player)
         self.X_O_dict[player].append(square_number)
         self.check_for_winner(self.X_O_dict[player])
         self.check_for_tie()
         self.player = not self.player
      else:
         print "Occupied, pick another"

   ##----------------------------------------------------------------
   def check_for_tie(self):
      if 9 == len(self.X_O_dict["X"]) + len(self.X_O_dict["O"]):
         print "It's A Tie"
         self.top.quit()

   ##----------------------------------------------------------------
   def check_for_winner( self, list_in ):

      winner_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9], \
                     [1, 4, 7], [2, 5, 8], [3, 6, 9], \
                     [1, 5, 9], [3, 5, 7]]
      for winner in winner_list:
         if set(winner).issubset(set(list_in)):
            print 'Is A Winner *****'
            self.top.quit()


##===================================================================
root = Tk()
BT=TicTacToe(root)
root.mainloop()
print BT.X_O_dict

You would then append the button number to a string and set a common StringVar() as is done in this Entry() example and how above, the square is changed from a number to "x" or "O". Note how the label above the Entry box in the program below mirrors what is in the entry box. You would use a label and StringVar.set() to do the same thing. Sorry, but as I said earlier, I have no time to do more right now.

import Tkinter

class EntryTest:
   """ shows using the same StringVar in the second list box
       and in the entry box
   """
   def __init__(self):
      self.top = Tkinter.Tk()
      self.top.title("Test of Entry")
      self.top.geometry("200x150+10+10")

      self.str_1 = Tkinter.StringVar()
      label_lit = Tkinter.StringVar()
      self.int_lit = Tkinter.IntVar()
      self.int_ctr = 0

      label_1 = Tkinter.Label(self.top, textvariable = label_lit )
      label_1.pack()
      label_lit.set( "Test of Label")

      label_2 = Tkinter.Label(self.top, textvariable = self.str_1 )
      label_2.pack()

      label_3 = Tkinter.Label(self.top, textvariable = self.int_lit )
      label_3.pack()
      self.int_lit.set(self.int_ctr)

      entry_1 = Tkinter.Entry(self.top, textvariable=self.str_1)
      entry_1.pack()
      self.str_1.set( "Entry Initial Value" )

      print_button = Tkinter.Button(self.top, text='PRINT CONTENTS',
                     command=self.getit, bg='blue', fg='white' )
      print_button.pack(fill=Tkinter.X, expand=1)

      exit_button= Tkinter.Button(self.top, text='EXIT',
                   command=self.top.quit, bg='red', fg='white' )
      exit_button.pack(fill=Tkinter.X, expand=1)

      entry_1.focus_set()

      self.top.mainloop()

   ##-----------------------------------------------------------------
   def getit(self) :
      print "getit: variable passed =", self.str_1.get()
      self.int_ctr += 1
      self.int_lit.set(self.int_ctr)

##===============================================================
if "__main__" == __name__  :
   ET=EntryTest()

I did slight refactoring for your code, continue. The solution is little unconvetional, putting the variables as attributes function-object calculate, but it was easier to refactor so. If you want test prints from some funcitions you can use logging decorator.

from tkinter import *
from tkinter import ttk
from decimal import *

from functools import partial

from operator import *

# chapter 9.3.1 Mapping of Operators to Functions in Help
# one argument
oper_dict1 = {'+/-':neg,}
# two arguments
oper_dict2 = {'+':add, '-':sub,'*':mul, '/':truediv,  '%':mod, '^':pow}

# Set Up Decimal Formating
getcontext().prec = 30

# ====================================================================================================
# Main Functions
def equPressedF():
    print("equPressedF() called")
    calculate.num2 = dfSV.get()
    print(calculate.num1)
    print(calculate.num2)
    dfSV.set(calculate())

def calculate():
    print("calculate() called")
    print("class variables are: %s, %s, operator %s" % (calculate.num1, calculate.num2, calculate.oper))
    calculate.answ = (oper_dict2[calculate.oper](Decimal(calculate.num1),
                                                Decimal(calculate.num2)) if  calculate.oper in oper_dict2
                      else oper_dict1[calculate.oper](Decimal(calculate.num1))
                      )
    return calculate.answ

# Button Functions
def numberPressed(num):
    print('Got', num)
    dfSV.set(dfSV.get() + num)
    print('Now',dfSV.get())

def decPressedF():
    print("decPressedF() called")
    tempV = dfSV.get()
    if(tempV.find(".")==-1):
        if(tempV==""):
            tempV += "0."
        else:
            tempV += "."
    else:
        pass
    dfSV.set(tempV)

def addPressedF():
    print("addPressedF() called")
    calculate.num1 = dfSV.get()
    print(calculate.num1)
    calculate.oper = "+"
    root.title("Calculator - '+'")
    dfSV.set("")

def subPressedF():
    print("suPressedF() called")
    calculate.num1 = dfSV.get()
    calculate.oper = "-"
    root.title("Calculator - '-'")
    dfSV.set("")

def mulPressedF():
    print("mulPressedF() called")
    calculate.num1 = dfSV.get()
    calculate.oper = "*"
    root.title("Calculator - '*'")
    dfSV.set("")

def divPressedF():
    print("divPressedF() called")
    calculate.num1 = dfSV.get()
    calculate.oper = "/"
    root.title("Calculator - '/'")
    dfSV.set("")

def bckspPressedF():
    print("bckspPressedF() called")
    dfSV.set(dfSV.get()[0:-1])

def cPressedF():
    print("cPressedF() called")
    calculate.num1 = None
    calculate.oper = None
    calculate.num2 = None
    calculate.answ = None
    dfSV.set("")

def cePressedF():
    print("cePressedF() called")
    dfSV.set("")

def rndPressedF():
    print("rndPressedF() called")
    dfSV.set(Decimal(dfSV.get()).quantize(Decimal('.01')))

def modPressedF():
    print("modPressedF() called")
    calculate.num1 = dfSV.get()
    calculate.oper = "%"
    root.title("Calculator - '%'")
    dfSV.set("")

def posnegPressedF():
    print("posnegPressedF() called")
    if(dfSV.get().find("-")==-1):
        dfSV.set("-"+dfSV.get())
    else:
        dfSV.set(dfSV.get().replace('-',''))

def powPressedF():
    print("powPressedF() called")
    calculate.num1 = dfSV.get()
    calculate.oper = "^"
    root.title("Calculator - '^'")
    dfSV.set("")

def sqrtPressedF():
    print("sqrtPressedF() called")
    dfSV.set(Decimal(dfSV.get()).sqrt())

def piPressedF():
    print("piPressedF() called")
    dfSV.set("3.1415926535897932384626433")

# Functions
# ====================================================
# Button and Key Functions
# Create Window
root = Tk()
root.title("Calculator")
root.resizable(0,0)

# Calculator TextField
dfSV = StringVar()
dsplyF = Entry(root, textvariable=dfSV)
dsplyF['state'] = 'readonly'
dsplyF['readonlybackground']='white'
dsplyF['foreground']='purple'
dfSV.set("")

# Calculator ScrollBar
calcSB = ttk.Scrollbar(root, orient=HORIZONTAL, command=dsplyF.xview)
dsplyF['xscrollcommand'] = calcSB.set

# Button Styles
style1 = ttk.Style().configure("TButton", foreground="blue")
style = ttk.Style()
style.map("C.TButton", foreground=[('pressed', 'red'), ('active', 'black')], background=[('pressed', '!disabled', 'black'), ('active', 'white')])


# Create Buttons
# - Number Buttons -
oneB = ttk.Button(root, text="1", command=partial(numberPressed, '1'), width=7, style="C.TButton") 
twoB = ttk.Button(root, text="2", command=partial(numberPressed, '2'), width=7, style="C.TButton") 
threeB = ttk.Button(root, text="3", command=partial(numberPressed, '3'), width=7, style="C.TButton") 
fourB = ttk.Button(root, text="4", command=partial(numberPressed, '4'), width=7, style="C.TButton") 
fiveB = ttk.Button(root, text="5", command=partial(numberPressed, '5'), width=7, style="C.TButton") 
sixB = ttk.Button(root, text="6", command=partial(numberPressed, '6'), width=7, style="C.TButton") 
sevenB = ttk.Button(root, text="7", command=partial(numberPressed, '7'), width=7, style="C.TButton") 
eightB = ttk.Button(root, text="8", command=partial(numberPressed, '8'), width=7, style="C.TButton") 
nineB = ttk.Button(root, text="9", command=partial(numberPressed, '9'), width=7, style="C.TButton") 
zeroB = ttk.Button(root, text="0", command=partial(numberPressed, '0'), style="C.TButton") 
# - calculate.operator Buttons -
addB = ttk.Button(root, text="+", command=addPressedF, width=7, style="C.TButton") 
subB = ttk.Button(root, text="-", command=subPressedF, width=7, style="C.TButton") 
mulB = ttk.Button(root, text="*", command=mulPressedF, width=7, style="C.TButton") 
divB = ttk.Button(root, text="/", command=divPressedF, width=7, style="C.TButton") 
modB = ttk.Button(root, text="%", command=modPressedF, width=7, style="C.TButton") 
powB = ttk.Button(root, text="^", command=powPressedF, width=7, style="C.TButton") 
sqrtB = ttk.Button(root, text="sqrt", command=sqrtPressedF, width=7, style="C.TButton") 
piB = ttk.Button(root, text="pi", command=piPressedF, width=7, style="C.TButton") 
posnegB = ttk.Button(root, text="+/-", command=posnegPressedF, style="C.TButton") 
equB = ttk.Button(root, text="=", command=equPressedF, width=7, style="C.TButton") 
# - Other Buttons
bckspB = ttk.Button(root, text="<- Backspace", command=bckspPressedF, style="C.TButton") 
rndB = ttk.Button(root, text="Round", command=rndPressedF, width=7, style="C.TButton") 
cB = ttk.Button(root, text="C", command=cPressedF, width=7, style="C.TButton") 
ceB = ttk.Button(root, text="CE", command=cePressedF, width=7, style="C.TButton") 
decB = ttk.Button(root, text=".", command=decPressedF, width=7, style="C.TButton") 

# Grid Objects
dsplyF.grid(column=0, row=0, columnspan=7, sticky=(W,E))
calcSB.grid(column=0, row=1, pady=(0,10), columnspan=7, sticky=(W,E))
oneB.grid(column=0, row=2)
twoB.grid(column=1, row=2)
threeB.grid(column=2, row=2)
fourB.grid(column=0, row=3)
fiveB.grid(column=1, row=3)
sixB.grid(column=2, row=3)
sevenB.grid(column=0, row=4)
eightB.grid(column=1, row=4)
nineB.grid(column=2, row=4)
zeroB.grid(column=0, row=5, columnspan=2, sticky=(W,E))
decB.grid(column=2, row=5)
addB.grid(column=3, row=2, padx=(15,15))
subB.grid(column=3, row=3, padx=(15,15))
mulB.grid(column=3, row=4, padx=(15,15))
divB.grid(column=3, row=5, padx=(15,15))
bckspB.grid(column=4, row=2, columnspan=2, sticky=(W,E))
cB.grid(column=4, row=3)
rndB.grid(column=5, row=3)
ceB.grid(column=4, row=4)
modB.grid(column=5, row=4)
posnegB.grid(column=4, row=5, columnspan=2, sticky=(W,E))
powB.grid(column=6, row=2, padx=(15,0))
sqrtB.grid(column=6, row=3, padx=(15,0))
piB.grid(column=6, row=4, padx=(15,0))
equB.grid(column=6, row=5, padx=(15,0))


calculate.num1 = None
calculate.num2 = None
calculate.oper = None


# Mainloop for root window
root.mainloop()
commented: An incredible help! +3

Alright,
thank you. I'll look into adding class(es). Thanks everyone for the help.

- WolfShield

You have much refactoring left for statement is your friend. I would use list or tuple for widgets, not individual variables. Look my Tkinter examples using functions to define widgets in snippets.

I found nice decorator for developing programs, check it out: http://wiki.python.org/moin/PythonDecoratorLibrary#Controllable_DIY_debug.

Not necessary to yet understand it deeply, just use it! Easier than those print statements.

Here is Python3fied version of it:

from __future__ import print_function
import sys

WHAT_TO_DEBUG = set(['io', 'core'])  # change to what you need

class debug:
    """ Decorator which helps to control what aspects of a program to debug
    on per-function basis. Aspects are provided as list of arguments.
    It DOESN'T slowdown functions which aren't supposed to be debugged.
    """
    def __init__(self, aspects=None):
        self.aspects = set(aspects)

    def __call__(self, f):
        if self.aspects & WHAT_TO_DEBUG:
            def newf(*args, **kwds):
                print(f.__name__, args, kwds, file=sys.stderr)
                f_result = f(*args, **kwds)
                print(f.__name__, "returned", f_result, file = sys.stderr)
                return f_result
            newf.__doc__ = f.__doc__
            return newf
        else:
            return f

@debug(['io'])
def prn(x):
    print(x)

@debug(['core'])
def mult(x, y):
    return x * y

prn(mult(2, 2))

Thank you everyone!
You guys have helped me complete my first real Python program! And I have a few more references
and tools to use as well!

Thanks everyone for your time and understanding.

- WolfShield

This is a quick program to get you started with a little less pain, but note that the only symbol that actually does anything is the "+" key, and it possibly doesn't do things in the order you want, but is intended as a starter only.

from tkinter import *
from tkinter import ttk
from decimal import *
from functools import partial

class Calculator():
    def __init__(self, master):
        self.master = master
        self.num_entered = ""
        self.total = Decimal("0")

        self.entry_label()
        self.number_buttons()
        self.symbol_buttons()

    def add_it(self):
        self.total += Decimal(self.num_entered)
        self.total_SV.set('Total=' + str(self.total))

    def div_it(self):
        print "div_it called"

    def entry_label(self):
        ## Label to display the total so far
        self.total_SV = StringVar()
        total_lab = Label(root, textvariable=self.total_SV)
        total_lab.grid(column=0, row=0, columnspan=2, sticky=(W,E))
        self.total_SV.set("Total =")

        # Calculator TextField
        self.dfSV = StringVar()
        dsplyF = Entry(root, textvariable=self.dfSV)
        dsplyF['state'] = 'readonly'
        dsplyF['readonlybackground']='white'
        dsplyF['foreground']='purple'
        dsplyF.grid(column=2, row=0, columnspan=2, sticky=(W,E))
        self.dfSV.set("")


    def mul_it(self):
        print "mul_it called"

    def number_buttons(self):
        """ button zero through 9 with button location in a list
        """
        button_location = [ [0, 5], [0, 2], [1, 2], [2, 2], \
                                    [0, 3], [1, 3], [2, 3], \
                                    [0, 4], [1, 4], [2, 4] ] 
        cs = 3                  ## columnspan
        for num in range(0, 10):
            but = ttk.Button(root, text=str(num), \
                             command=partial(self.pressed, str(num)), width=7)
            col = button_location[num][0]     ## get location from the list
            r   = button_location[num][1]
            but.grid(column=col, row=r, columnspan=cs, sticky=(W,E))
            cs = 1

    def pressed(self, button_value):
        print "pressed", button_value

        ## a dictionary of symbol keys and the function to execute
        ## for each key
        functions_dict = {"+":'self.add_it()', "-":'self.sub_it()', \
                          "*":'self.mul_it()', "/":'self.div_it()', \
                          "=":'self.total_it()' }

        if button_value.isdigit():
            self.num_entered += button_value
        elif button_value in functions_dict:
            exec(functions_dict[button_value])
            self.num_entered = ""
        self.dfSV.set(self.num_entered)

    def sub_it(self):
        print "sub_it called"

    def total_it(self):
        print "total_it called"

    def symbol_buttons(self):
        for ctr, symbol in enumerate(["+", "-", "*", "/", "="]):
            but = ttk.Button(root, text=symbol, \
                             command=partial(self.pressed, symbol), width=7)
            but.grid(column=3, row=ctr+1)

if __name__ == "__main__":

    # Set Up Decimal Formating
    getcontext().prec = 30

    # Mainloop for root window
    root = Tk()
    root.title("Calculator")
    root.resizable(0,0)
    CL = Calculator(root)
    root.mainloop()
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.