So I've been struggling with an issue for a week or so, been googling around trying to find different solutions, etc and getting nowhere. I was advised to put functioning code on here so I've cut it down some while still showing the issue.
I want to have a main page listing a set of goals, then if you click on the "Goal Entry" button up top a new window opens where you can input additional goals. Then you type in your desired additions, hit enter, and it adds it to the list on the main page.
I've accomplished all of the above EXCEPT, after you add the goals (and I have the list printing before and after so I know they're being added) and the entry window closes, the list of labels (created by an iteration) hasn't updated accordingly.
How do I get the list on the main page to automatically update when a new item is added to the list?
from tkinter import *
pg = ["goal1","goal2"]
pgtotal=1
psum=len(pg)
class yeargoals():
global pg, hg, fg, rg, rgtotal
def __init__(self,master):
self.master = master
master.title("This Year's Goals")
self.buttonframe = Frame(root)
self.buttonframe.pack(side=TOP, padx = 150, fill=BOTH)
self.home = Button(self.buttonframe, text="Home Page")
self.home.grid(row=1, column=1, padx=10)
self.enter = Button(self.buttonframe, text="Goal Entry", command=self.winenter)
self.enter.grid(row=1, column=2, padx=10)
self.finalize = Button(self.buttonframe, text="Finalize for Year")
self.finalize.grid(row=1, column=3, padx=10)
self.dashboard = Button(self.buttonframe, text="Goal Dashboard")
self.dashboard.grid(row=1,column=4, padx=10)
self.goalframe = Frame(root)
self.goalframe.pack(side=TOP, padx=150, pady=50, fill=BOTH, expand = True)
#Makes the label Fram I want the Checkboxes to go in
self.LabelFramep= LabelFrame(self.goalframe,text="Professional Goals")
self.LabelFramep.pack(side=LEFT, padx=10, anchor = N, fill=BOTH, expand = True)
#Makes the from the list above
for goal in pg:
l = Checkbutton(self.LabelFramep, text=goal, variable=Variable())
l.config(font=("Courier",12))
l.grid(sticky=W)
self.ptotal=Label(self.LabelFramep,text="Progress so far: "+str(pgtotal)+"/"+str(psum))
self.ptotal.config(font=("Courier",12))
self.ptotal.grid(sticky=W)
self.pper=Label(self.LabelFramep, text=str(round((pgtotal/psum)*100))+"% Complete")
self.pper.config(font=("Courier",12))
self.pper.grid(sticky=W)
def winenter(self):
global pg
self.winenter = Toplevel(root)
options = ["Professional", "Health", "Financial", "Reward Items"]
variable = StringVar(self.winenter)
variable.set(options[0])
#Title of entry section
t1 = Label(self.winenter, text="New Goal Entry")
t1.grid(row=0, column=1, columnspan=2)
#dropdown menu
d = OptionMenu(self.winenter, variable, *options)
d.grid(row=1, column=2)
#entry fields
e1 = Entry(self.winenter)
e1.grid(row=2, column=2, padx = 10, pady=5)
e2 = Entry(self.winenter)
e2.grid(row=3, column=2, padx=10, pady=5)
e3 = Entry(self.winenter)
e3.grid(row=4, column=2, padx=10, pady=5)
e4 = Entry(self.winenter)
e4.grid(row=5, column=2, padx=10, pady=5)
e5 = Entry(self.winenter)
e5.grid(row=6, column=2, padx=10, pady=5)
#Label for entry fields
l1 = Label(self.winenter, text="Goal Number 1")
l1.grid(row=2, column=1)
l2 = Label(self.winenter, text="Goal Number 2")
l2.grid(row=3, column=1)
l3 = Label(self.winenter, text="Goal Number 3")
l3.grid(row=4, column=1)
l4 = Label(self.winenter, text="Goal Number 4")
l4.grid(row=5, column=1)
l5 = Label(self.winenter, text="Goal Number 5")
l5.grid(row=6, column=1)
def enter():
global pg, main
print (pg)
if variable.get() == "Professional":
pg.append(e1.get())
self.winenter.destroy()
print (pg)
#Goal entry execute button
b = Button(self.winenter, text="Enter Goals", command=enter)
b.grid(row=7, column = 1)
root = Tk()
Window = yeargoals(root)
root.mainloop()
In your callback function to button "Enter Goals", you have done nothing to update your main window. Maybe you think the main window will magically keep updated with the variable pg, no, you need to do all those updates manually in your callback function.
For example, change your callback enter() to:
def enter():
global pg, main
print (pg)
if variable.get() == "Professional":
pg.append(e1.get())
l = Checkbutton(self.LabelFramep, text=pg[-1], variable=Variable())
l.config(font=("Courier",12))
l.grid(sticky=W)
self.winenter.destroy()
print (pg)
You can find the main window is updated after you click "Enter Goals".
Related
Hello im having python learning project. I want to insert in GUI two numbers, which are defining range for program to generate random number from.
I am really having problems with calling function with press of the button. And constantly getting error ValueError: invalid literal for int() with base 10: '', when trying to convert string from entry in GUI to int and then inserting them into random.randint.
Thx for Help!
from tkinter import *
import random
root = Tk()
root.title("Generator custom random number")
#function that gets number from entry converts string to int and defines target number in stevilo
def function():
string_answer1 = prvo_stevilo.get()
int1 = int(string_answer1)
string_answer2 = drugo_stevilo.get()
int2 = int(string_answer2)
stevilo = random.randint(int1, int2)
#Defining GUI
navodilo = Label(root, text="Choose custom lower and upper number to chose random number from", width=60)
navodilo2 = Label(root, text="From", width=20, borderwidth=3)
navodilo3 = Label(root, text="To", width=20, borderwidth=3)
prvo_stevilo = Entry(root, width=20, borderwidth=3)
drugo_stevilo = Entry(root, width=20, borderwidth=3)
gumb = Button(root, text="Generate number", width=17, height=2, command=function)
praznavrstica = Label(root, text="")
izpis = Label(root, text="Random number is: ", width=20)
izpis_stevila = Label(root, text="" + stevilo)
#Showcase of gui
navodilo.grid(row=0, column=0, columnspan=1)
navodilo2.grid(row=1, column=0, columnspan=1)
navodilo3.grid(row=3, column=0, columnspan=1)
prvo_stevilo.grid(row=2, column=0, columnspan=1)
drugo_stevilo.grid(row=4, column=0, columnspan=1)
praznavrstica.grid(row=5, column=0, columnspan=1)
gumb.grid(row=6, column=0, columnspan=1)
praznavrstica.grid(row=7, column=0, columnspan=1)
izpis.grid(row=8, column=0, columnspan=1)
izpis_stevila.grid(row=9, column=0, columnspan=1)
#Loop
root.mainloop()
I've noticed few problems with your code. I was able to make it running without too many changes, although probably it is not the best way.
First answer to your question: you are getting this error, because you are trying to change string -> '' to int. It happens because function() is running before you click button.
Another problem:
izpis_stevila = Label(root, text="" + stevilo)
variable 'stevilo' simply doesn't exist before calling function(), so delete it from here.
My proposition for changes:
1)
gumb = Button(root, text="Generate number", width=17, height=2,command = lambda: function())
Without lambda your function will run no matter of state of your button.
2)
first = IntVar(root, value=0)
second = IntVar(root, value=1)
prvo_stevilo = Entry(root, width=20, borderwidth=3, textvariable=first)
drugo_stevilo = Entry(root, width=20, borderwidth=3, textvariable=second)
If you run function without any values in your entry you will get error. This change allows you to put default value for your entry widgets.
3)
def function():
if prvo_stevilo.get() == '' or drugo_stevilo.get() =='':
return
else:
string_answer1 = prvo_stevilo.get()
int1 = int(string_answer1)
string_answer2 = drugo_stevilo.get()
int2 = int(string_answer2)
stevilo = random.randint(int1, int2)
izpis_stevila = Label(root, text=str(stevilo))
izpis_stevila.grid(row=9, column=0)
Firstly check if your entry is not empty.
Secondly update label, also remeber about changing int to string here text=str(stevilo).
I have only been programming 3 months so any advice on improvement to my code is appreciated even if it inst related to my specific question.
Its a simple small project with tkinter. Two fields to enter your first and last name then you hit the swap button and it will swap what ever you put in the name fields.
Problem is I dont want to use globals and I cant seem to figure it out I know its probably something easy and I did spend time trying to figure it out.
If you have any improvements to the code let me know.
from tkinter import *
### I dont Want Globals but cant figure out another method for doing this
### Hope some one can help me with this part
evar = ""
evar1 = ""
def mainWindow():
root = Tk()
root.title("Swap Names")
root.geometry("400x150+100+250")
return root
def createVar():
global evar
global evar1
evar = StringVar()
evar1 = StringVar()
def firstNameFrame(root):
frame1 = Frame(root)
frame1.pack(side=TOP, padx=2, pady=2)
label = Label(frame1, text="First Name:")
label.pack(side=LEFT, padx=2, pady=2)
entry = Entry(frame1, textvariable = evar)
entry.pack(side=LEFT, pady = 2)
def lastNameFrame(root):
frame2 = Frame(root)
frame2.pack(side=TOP, padx=2, pady=2)
label = Label(frame2, text="Last Name:")
label.pack(side=LEFT, padx=1, pady=1)
entry = Entry(frame2, textvariable = evar1)
entry.pack(side=LEFT, pady = 5)
def swapFrame(root):
frame3 = Frame(root)
frame3.pack(side=TOP, padx=10, pady = 10)
swapButton = Button(frame3, text="Swap",command = swap)
swapButton.pack(side=LEFT, padx =5, pady=5)
### I would like to some how use swap with out using a global
def swap():
b=evar.get()
evar.set(evar1.get())
evar1.set(b)
def main():
root = mainWindow()
createVar()
firstNameFrame(root)
lastNameFrame(root)
swapFrame(root)
root.mainloop()
main()
One of the solutions can be wrapping all the code related to the initialization and working with Tk in a separate class, so instead of global variables, we will use the class instance variables:
from tkinter import *
class Gui(object):
def __init__(self):
self.root = Gui._init_main_window()
self.first_name_var = StringVar()
self.last_name_var = StringVar()
self._init_first_name_frame()
self._init_last_name_frame()
self._init_swap_frame()
#staticmethod
def _init_main_window():
root = Tk()
root.title("Swap Names")
root.geometry("400x150+100+250")
return root
def _init_first_name_frame(self):
frame1 = Frame(self.root)
frame1.pack(side=TOP, padx=2, pady=2)
label = Label(frame1, text="First Name:")
label.pack(side=LEFT, padx=2, pady=2)
entry = Entry(frame1, textvariable=self.first_name_var)
entry.pack(side=LEFT, pady=2)
def _init_last_name_frame(self):
frame2 = Frame(self.root)
frame2.pack(side=TOP, padx=2, pady=2)
label = Label(frame2, text="Last Name:")
label.pack(side=LEFT, padx=1, pady=1)
entry = Entry(frame2, textvariable=self.last_name_var)
entry.pack(side=LEFT, pady=5)
def _init_swap_frame(self):
frame3 = Frame(self.root)
frame3.pack(side=TOP, padx=10, pady=10)
swap_button = Button(frame3, text="Swap", command=self._swap)
swap_button.pack(side=LEFT, padx=5, pady=5)
def _swap(self):
tmp = self.first_name_var.get()
self.first_name_var.set(self.last_name_var.get())
self.last_name_var.set(tmp)
def mainloop(self):
return self.root.mainloop()
def main():
gui = Gui()
gui.mainloop()
if __name__ == '__main__':
main()
A small comment to the code above: adding a prefix __ to variables or methods allows you to hide access to them directly by name outside the class using the name mangling.
UPD: According to #Coal comment, changed the double underscore prefixes to single underscore, as there is no need to use a name mangling.
This is assuming that when you say you don't want to use global, that you also mean that you don't want to use self:
from tkinter import Tk, Button, Entry
def swap(fn, ln):
# Get the contents of the two fields.
first = fn.get()
last = ln.get()
# Clear the contents of both fields.
first_name.delete(0, 'end')
last_name.delete(0, 'end')
# Set each field to the previous content of the other field.
first_name.insert(0, last)
last_name.insert(0, first)
root = Tk()
first_name = Entry(root)
last_name = Entry(root)
first_name.insert(0, "Enter first name")
last_name.insert(0, "Enter last name")
first_name.pack()
last_name.pack()
swap_button = Button(root, text="SWAP", command=lambda:swap(first_name, last_name))
swap_button.pack()
root.mainloop()
I have programmed a script which takes random four elements from a table and question to the user using tkinter, random and sqlite3. Currently, I can ask a question. Implement four choices with radiobuttons. I can also test if the answer is correct or not and show the result to the user via toplevel().
Problem is, how can I refresh the question after the continue button clicked?
My whole code is below. I have tried refreshing the random numbers and labels under continue_asking or another def called from continue_asking. But it doesn't work at all.
from tkinter import *
from sqlite3 import *
from random import *
class Question(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.prepare_question()
def prepare_question(self):
self.tumu = {0:['ask1','answer1'], # instead of SQL query
1:['ask2','answer2'],
2:['ask3','answer3'],
3:['ask4','answer4']}
self.create_widgets()
def create_widgets(self):
self.choiceFrame = Frame(self)
self.choiceFrame.grid(row=2, column=0)
self.choiceNum = IntVar()
for i in range(4):
Radiobutton(self.choiceFrame, text=self.tumu[i][1], variable=self.choiceNum, value=i) \
.grid(row=2, column=i, padx=5, pady=5)
self.q_num = randrange(4)
self.q_word = self.tumu[self.q_num][0]
lbl_question = Label(self, text="Which one is the meaning of the word: " + self.q_word, font="Courier 12")
lbl_question.grid(row=0, column=0, columnspan=4, padx=5, pady=5, sticky=W)
txt_question = Text(self, height=1, font="Courier 12", pady=2)
txt_question.tag_configure("myStyle", font="Courier 12 bold")
txt_question.insert("end", "Please choose the answer and ")
txt_question.insert("end", "click okay to see the results.", "myStyle")
txt_question.configure(state="disabled")
txt_question.grid(row=1, column=0, columnspan=4, padx=5, sticky=W)
btn_okay = Button(self, text="Okay", font="12", command=self.a_control)
btn_okay.grid(row=3, column=0, columnspan=2)
def a_control(self):
self.choosenWord = self.q_num
self.frm_answer = Toplevel()
self.frm_answer.title("Result")
self.selectedWord = self.choiceNum.get()
txt_result = Text(self.frm_answer, height=4, width = 40)
if self.choosenWord == self.selectedWord:
txt_result.insert("end", "Congrats! Your answer is correct.\n")
else:
txt_result.insert("end","Your answer is not correct.\n")
txt_result.insert("end", "Correct answer is " + self.tumu[self.q_num][1] + '\n')
txt_result.insert("end", "Please click Continue to continue.\n")
txt_result.insert("end", "Click cancel to quit.")
txt_result.grid(row=0, column=0, columnspan=2, padx = 5, pady=5)
txt_result.configure(state="disabled")
btn_continue = Button(self.frm_answer, text="Continue", command=lambda: self.continue_asking(self.frm_answer))
btn_continue.grid(row=1, column=0, padx=5, pady=5, sticky = W)
btn_quit = Button(self.frm_answer, text="Cancel", command=self.end_asking)
btn_quit.grid(row=1, column=1, padx=5, pady=5, sticky = W)
def continue_asking(self,frm_answer):
frm_answer.destroy()
def end_asking(self):
root.destroy()
root = Tk()
app = Question(root)
root.mainloop()
I have tried adding prepare_question to continue_asking. It keeps asking questions but widgets are not changing. They are just overlapping.
EDIT
So let's restart from scratch, i was totally wrong because no widget was removed and they stacked in the main Frame children list.
You still don't need to write so much code, mostly move some parts.
First, to be able to update the widgets and prepare the new question peacefully, move
self.create_widgets() in the constructor and put the random index self.q_num and self.q_word inside prepare_question, since it belongs to the logic of the question creation.
In create_widgets() you only need to keep some control on the label question, so we add self.lbl_question...
Finally, i suggest to create a new function update_widgets(), but you can put the logic inside continue_asking().
In this function, call prepare_question to update the next question (sql query and random stuff). Since we move the random index, everything is ready to update each widget:
text of the question label
text of radiobuttons. I'm not so proud of the loop to change those, but that'll do the trick. (we keep the values created for the indexes to match the new ones, i'm not very sure about this logic with SQL queries, i follow your first implementation with text=self.tumu[i][1])
If someone can tell how to get the radiobutton value more easily, i'm interested
Here is the whole code:
from tkinter import *
from sqlite3 import *
from random import *
class Question(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.prepare_question()
self.create_widgets()
def prepare_question(self):
self.tumu = {0:['ask1','answer1'], # instead of SQL query
1:['ask2','answer2'],
2:['ask3','answer3'],
3:['ask4','answer4']}
self.q_num = randrange(4)
self.q_word = self.tumu[self.q_num][0]
def create_widgets(self):
self.choiceFrame = Frame(self)
self.choiceFrame.grid(row=2, column=0)
self.choiceNum = IntVar()
for i in range(4):
Radiobutton(self.choiceFrame, text=self.tumu[i][1], variable=self.choiceNum, value=i) \
.grid(row=2, column=i, padx=5, pady=5)
self.lbl_question = Label(self, text="Which one is the meaning of the word: " + self.q_word, font="Courier 12")
self.lbl_question.grid(row=0, column=0, columnspan=4, padx=5, pady=5, sticky=W)
txt_question = Text(self, height=1, font="Courier 12", pady=2)
txt_question.tag_configure("myStyle", font="Courier 12 bold")
txt_question.insert("end", "Please choose the answer and ")
txt_question.insert("end", "click okay to see the results.", "myStyle")
txt_question.configure(state="disabled")
txt_question.grid(row=1, column=0, columnspan=4, padx=5, sticky=W)
btn_okay = Button(self, text="Okay", font="12", command=self.a_control)
btn_okay.grid(row=3, column=0, columnspan=2)
def a_control(self):
self.choosenWord = self.q_num
self.frm_answer = Toplevel()
self.frm_answer.title("Result")
self.selectedWord = self.choiceNum.get()
txt_result = Text(self.frm_answer, height=4, width = 40)
if self.choosenWord == self.selectedWord:
txt_result.insert("end", "Congrats! Your answer is correct.\n")
else:
txt_result.insert("end","Your answer is not correct.\n")
txt_result.insert("end", "Correct answer is " + self.tumu[self.q_num][1] + '\n')
txt_result.insert("end", "Please click Continue to continue.\n")
txt_result.insert("end", "Click cancel to quit.")
txt_result.grid(row=0, column=0, columnspan=2, padx = 5, pady=5)
txt_result.configure(state="disabled")
btn_continue = Button(self.frm_answer, text="Continue", command=self.continue_asking)
btn_continue.grid(row=1, column=0, padx=5, pady=5, sticky = W)
btn_quit = Button(self.frm_answer, text="Cancel", command=self.end_asking)
btn_quit.grid(row=1, column=1, padx=5, pady=5, sticky = W)
def continue_asking(self):
self.frm_answer.destroy()
self.update_widgets()
def update_widgets(self):
self.prepare_question()
# change question text
self.lbl_question.configure(text = "Which one is the meaning of the word: " + self.q_word)
# change Radiobutton
for child in self.choiceFrame.children.values():
index = child.config()['value'][4]
child.configure(text = self.tumu[index][1])
if index == 0: # reset the focus
child.select()
def end_asking(self):
root.destroy()
root = Tk()
app = Question(root)
root.mainloop()
First crap post: (the not to do part)
You don't need to change so much code to fix the present issue, have you already tried the following ?
def continue_asking(self,frm_answer):
frm_answer.destroy()
self.prepare_question()
I won't review the whole code, there is another place for that, but you can also avoid the lambda when you call continue_asking(), since you store the frame in self.frm_answer
btn_continue = Button(self.frm_answer, text="Continue", command=self.continue_asking)
# [...]
def continue_asking(self):
self.frm_answer.destroy()
self.prepare_question()
I would like to create 2 different groups of radio buttons. The user would select one option from either group. There would be a function that would get the values(strings) from the selected radio buttons and then print them. Here's my code but it doesn't work (i'm new to python).
from tkinter import *
root = Tk()
btn1 = "lol"
btn2 = "lel"
def funkcija():
n = entry1.get()
m = "null"
X = btn1.get()
Y = btn2.get()
print("%s %s je %s %s." % (n, X, m, Y))
theLabel = Label(root, text="Vnesite količino in izberite prvo valuto.")
theLabel.grid(row=0, columnspan=3)
gumb1=Radiobutton(root,text="Euro",value = "euro",variable = "btn1").grid(row=2, column=1, sticky=W)
gumb2=Radiobutton(root,text="Dolar",value = "dolar",variable = "btn1").grid(row=3, column=1, sticky=W)
gumb3=Radiobutton(root,text="Funt",value = "funt",variable = "btn1").grid(row=4, column=1, sticky=W)
label3= Label(root, text="Izberite drugo valuto.")
label3.grid(row=6, columnspan=3)
label35= Label(root)
label35.grid(row=5, columnspan=3)
gumb4=Radiobutton(root,text="Euro",value = "euro",variable = "btn2").grid(row=7, column=1, sticky=W)
gumb5=Radiobutton(root,text="Dolar",value = "dolar",variable = "btn2").grid(row=8, column=1, sticky=W)
gumb6=Radiobutton(root,text="Funt",value = "funt",variable = "btn2").grid(row=9, column=1, sticky=W)
label1 = Label(root, text="Količina:")
label1.grid(row=1, sticky=E)
entry1 = Entry(root)
entry1.grid(row=1, column=1, sticky=W)
go = Button(root, text="Izračun", fg="white", bg="black", command=funkcija)
go.grid(row=10, columnspan=3)
root.mainloop()
In your radio button, analyze the parameters that you are passing:
gumb1 = Radiobutton(root,
text = "Euro",
value = "Euro",
variable = "btn2"
The parameters value and variable are what stores the data of the radio button. You've set your value option correctly. The interpreter will automatically set the variable with the value when the radio button is selected.
But here's where your issue is:
variable = "btn2"
"btn2" is a string. Not very useful though, is it? In fact, you're trying to perform methods on it that don't even exist. Such as here:
def funkcija():
X = btn2.get()
In fact, taking this information, you almost got there!
At the top of your script, you need to set btn2 to Tkinter's StringVar, like so:
from tkinter import *
btn1 = StringVar()
btn2 = StringVar()
Now that's done, let's change our parameters in our radio buttons.
gumb1 = Radiobutton(root,
text = "Euro",
value = "Euro",
variable = btn2
Now, Tkinter will automatically update the variable when it is selected. To get the value, do the same that you had done in your funkcija.
X = btn2.get()
And then the value of btn2 (which was updated by the radio buttons) will not be read, and stored into the variable X.
I have been trying to desing a form in tkinter using python, but unfortunately I am stuck again, but now putting a form into the notebook I already have. I have run them separately and they work perfect, the problem starts when I try to put them together.
For example, if I write in "componentComb= ttk.Combobox(frameOne, width="19")" instead of frameOne I put firstStep which is what I want to do (merge them), I have an error like this:
componentComb= ttk.Combobox(firstStep, width="19")
NameError: name 'firstStep' is not defined
Which I don't understand, I have already defined, but probably wrong!!! Can you help me with this problem?
Below you have the code I have been "fighting" with, and I hope you can help me!
Thanks in advance
Here is my code:
#Starts
import Tkinter
from Tkinter import *
from ttk import *
import tkMessageBox
import ttk
# start of GUI code
root = Tk()
root.title("Model A")
root.minsize(1000, 150)
root.maxsize(1100, 200)
notebook = ttk.Notebook(root)
notebook.pack(fill='both', expand='yes')
notebook.pressed_index = None
# Child Frame
frameOne = Tkinter.Frame(notebook, bg='white')
frameOne.pack(fill='both', expand=True)
frameTwo = Tkinter.Frame(notebook, bg='white')
frameTwo.pack(fill='both', expand=True)
frameThree= Tkinter.Frame(notebook, bg='white')
frameThree.pack(fill='both', expand=True)
frameFour= Tkinter.Frame(notebook, bg='white')
frameFour.pack(fill='both', expand=True)
# Pages
notebook.add(frameOne, text='Standard')
notebook.add(frameTwo, text='TID')
notebook.add(frameThree, text='MEE')
notebook.add(frameFour, text='Final')
# Merging form and notebook
def defocus(event):
event.widget.master.focus_set()
if __name__ == '__main__':
firstStep = Tkinter.Label(notebook, text=" 1. Enter Main Details: ", font=("fixedsys", "16","bold italic"))
firstStep.grid(row=2, columnspan=7, sticky='W', \
padx=5, pady=5, ipadx=5, ipady=5)
#Main Selection
componentComb= ttk.Combobox(frameOne, width="19")
componentComb = Combobox(frameOne, state="readonly", values=("TGB", "RST", "CCPa"))
componentComb.grid(column=4, row=0, columnspan="5", sticky="nswe")
componentComb.set("Main Selection")
#Temperature Selection
tempComb = ttk.Combobox(frameOne, width="14")
tempComb = Combobox(frameOne, state="readonly", values=("-40", "-30", "-20","-10", "0", "10","20", "30"))
tempComb.grid(column=0, row=2, columnspan="2", sticky="w")
tempComb.set("Temperature Selection")
#Device Type Selection
DeviceTypeComb = ttk.Combobox(frameOne, width="14")
DeviceTypeComb = Combobox(frameOne, state="readonly", values=("QML", "Non-QML"))
DeviceTypeComb.grid(column=3, row=2, columnspan="2", sticky="w")
DeviceTypeComb.set("Device Type Selection")
#Junction Temperature Selection
JunctionTempComb = ttk.Combobox(frameOne, width="16")
JunctionTempComb = Combobox(frameOne, state="readonly", values=("-40", "-30", "-20","-10", "0", "10","20", "30"))
JunctionTempComb.grid(column=5, row=2, columnspan="2", sticky="w")
JunctionTempComb.set("Junction Temp Selection")
#Chip Area in Cm2 Selection
ChipAreaComb = ttk.Combobox(frameOne, width="12")
ChipAreaComb = Combobox(frameOne, state="readonly", values=("0.001","0.002","0.003","0.004","0.005","0.006"))
ChipAreaComb.grid(column=7, row=2, columnspan="2", sticky="e")
ChipAreaComb.set("Chip Area Selection")
#Time of Exposure
TimeOfExpoComb = ttk.Combobox(frameOne, width="12")
TimeOfExpoComb = Combobox(frameOne, state="readonly", values=("1", "2", "3","4", "5"))
TimeOfExpoComb.grid(column=9, row=2, columnspan="2", sticky="w")
TimeOfExpoComb.set("Time of Exposure")
root.mainloop()
firstStep is a local variable in the defocus function, and you are trying to access it in a global scope.
You have to define it outside of the function so that it has a meaning in the global scope. But note that because you are assigning it within the function, you need to use the global keyword so that it doesn't think you're introducing a new local variable with the same name.
This should work:
firstStep = None #define the variable globally
def defocus(event):
event.widget.master.focus_set()
if __name__ == '__main__':
global firstStep # we want to reassign the global version of this variable
firstStep = Tkinter.Label(notebook, text=" 1. Enter Main Details: ", font=("fixedsys", "16","bold italic"))
firstStep.grid(row=2, columnspan=7, sticky='W', \
padx=5, pady=5, ipadx=5, ipady=5)
componentComb= ttk.Combobox(firstStep, width="19")