I'm trying to make this program end straight away without asking the question " The program is still running,Do you want to kill it? " if the wrong password entered for the third time. Tried using 'quit()' but the program become not responding. Please help me.
import Tkinter
global root
global s
# this is the main/root window
root = Tkinter.Tk()
root.title("Stock Plus system")
root.geometry('800x600')
b2Var=Tkinter.StringVar()
s = 1
def win2():
# this is the child window
labelcementin = Tkinter.Label(root,text='Cement quantity in:')
labelcementin.grid(row=1,column=1)
labelhammerin = Tkinter.Label(root,text='Hammer quantity in;')
labelhammerin.grid(row=2,column=1)
labelspannerin = Tkinter.Label(root,text='Spanner quantity in:')
labelspannerin.grid(row=3,column=1)
labelbrickin = Tkinter.Label(root,text='Brick quantity in:')
labelbrickin.grid(row=4,column=1)
labelmirrorin = Tkinter.Label(root,text='Mirror quantity in:')
labelmirrorin.grid(row=5,column=1)
labelcementout = Tkinter.Label(root,text='Cement quantity out:')
labelcementout.grid(row=1,column=3)
labelhammerout = Tkinter.Label(root,text='Hammer quantity out:')
labelhammerout.grid(row=2,column=3)
labelspannerout = Tkinter.Label(root,text='Spanner quantity out:')
labelspannerout.grid(row=3,column=3)
labelbrickout = Tkinter.Label(root,text='Brick quantity out:')
labelbrickout.grid(row=4,column=3)
labelmirrorout = Tkinter.Label(root,text='Mirror quantity out:')
labelmirrorout.grid(row=5,column=3)
def calc_val():
Total_StockIn=int(cementinVar.get())+int(hammerinVar.get())+int(spannerinVar.get())+int(brickinVar.get())+int(mirrorinVar.get())
StockInLabel=Tkinter.Label(root,text='The total stock in is '+str(Total_StockIn))
StockInLabel.grid(row=8,column=2)
Total_Expenses= (int(cementinVar.get())*16)+(int(hammerinVar.get())*10)+(int(spannerinVar.get())*8)+(int(brickinVar.get())*2)+(int(mirrorinVar.get())*22)
ExpensesLabel=Tkinter.Label(root,text='The total expenses is RM ' + str(Total_Expenses))
ExpensesLabel.grid(row=9,column=2)
Total_Income= (int(cementoutVar.get())*18)+(int(hammeroutVar.get())*12)+(int(spanneroutVar.get())*10)+(int(brickoutVar.get())*4)+(int(mirroroutVar.get())*25)
IncomeLabel = Tkinter.Label(root,text = 'The Total income is RM ' +str(Total_Income))
IncomeLabel.grid(row=8, column= 4)
Remaining_Stock =Total_StockIn-(int(cementoutVar.get())+int(hammeroutVar.get())+int(spanneroutVar.get())+int(brickoutVar.get())+int(mirroroutVar.get()))
RemainingLabel = Tkinter.Label(root,text = 'The remaining stock is ' + str(Remaining_Stock))
RemainingLabel.grid(row=9, column = 4)
Total_Profit = (Total_Income) - (Total_Expenses)
ProfitLabel = Tkinter.Label(root,text = 'The total profit is RM ' + str(Total_Profit))
ProfitLabel.grid(row=10, column = 3)
quit()
boxcementin = Tkinter.Entry(root,width=12,textvariable=cementinVar)
boxcementin.grid(row=1, column=2)
boxhammerin = Tkinter.Entry(root,width=12,textvariable=hammerinVar)
boxhammerin.grid(row=2, column=2)
boxspannerin = Tkinter.Entry(root,width=12,textvariable=spannerinVar)
boxspannerin.grid(row=3, column=2)
boxbrickin = Tkinter.Entry(root,width=12,textvariable=brickinVar)
boxbrickin.grid(row=4, column=2)
boxmirrorin = Tkinter.Entry(root,width=12,textvariable=mirrorinVar)
boxmirrorin.grid(row=5, column=2)
boxcementout = Tkinter.Entry(root,width=12,textvariable=cementoutVar)
boxcementout.grid(row=1, column=4)
boxhammerout = Tkinter.Entry(root,width=12,textvariable=hammeroutVar)
boxhammerout.grid(row=2, column=4)
boxspannerout = Tkinter.Entry(root,width=12,textvariable=spanneroutVar)
boxspannerout.grid(row=3, column=4)
boxbrickout = Tkinter.Entry(root,width=12,textvariable=brickoutVar)
boxbrickout.grid(row=4, column=4)
boxmirrorout = Tkinter.Entry(root,width=12,textvariable=mirroroutVar)
boxmirrorout.grid(row=5, column=4)
button = Tkinter.Button(root,text='Calculate',command=calc_val)
button.grid(row=7,column=3)
def textboxvalue():
#For password entry
global s
if (s!=3 ):
Password=b2Var.get()
Username=b1Var.get()
if Password ==('stock123'):
label4=Tkinter.Label(root,text='Welcome to stock plus system, press login again to start using')
label4.grid(row=0,column=3)
Button_1 = Tkinter.Button(root, text="Login", command=win2)
Button_1.grid(row=7,column=3)
else:
s =s+1
label3=Tkinter.Label(root,text='Try again')
label3.grid(row=3,column=1)
else:
label5=Tkinter.Label(root,text='bye')
label5.grid(row=4,column=4)
label6=Tkinter.Label(root,text='Thank You for using Stock Plus System ')
label6.grid(row=5,column=4)
#Widgets in main window
Button_1 = Tkinter.Button(root, text="Login", command=textboxvalue)
Button_1.grid(row=7, column=3)
b1Var = Tkinter.StringVar()
b2Var = Tkinter.StringVar()
box1Label = Tkinter.Label(root,text='Username:')
box1Label.grid(row=1,column=3)
box2Label = Tkinter.Label(root,text='Password:')
box2Label.grid(row=2,column=3)
box1Text = Tkinter.Entry(root,textvariable=b1Var,width=12)
box1Text.grid(row=1, column=4)
box2Text = Tkinter.Entry(root,textvariable=b2Var,width=12,show='*')
box2Text.grid(row=2, column=4)
cementinVar = Tkinter.IntVar()
hammerinVar = Tkinter.IntVar()
spannerinVar = Tkinter.IntVar()
brickinVar = Tkinter.IntVar()
mirrorinVar = Tkinter.IntVar()
cementoutVar = Tkinter.IntVar()
hammeroutVar = Tkinter.IntVar()
spanneroutVar = Tkinter.IntVar()
brickoutVar = Tkinter.IntVar()
mirroroutVar = Tkinter.IntVar()
root.mainloop()
You have two, or maybe three, problems with your use of quit.
First, you put it in the wrong place. You want to quit if the user fails to login three times. But your quit() call comes at the end of calcval, which only gets called after the user has successfully logged in and calculated a value, so of course it's not going to help.
Second, you called the wrong thing. The quit function is a special thing used for quitting the interactive interpreter. You usually shouldn't use it in applications at all (use sys.exit() for command-line programs), and especially not in GUI apps. The quit method is called on the same Tkinter window you called mainloop() on, and tells it to quit the main loop.
So, what you want to do is add this line inside the else block that has the Thank You for using Stock Plus System text:
root.quit()
That may not work, depending on your platform, and how you're running your program—or, if you're running from IDLE, it may cause IDLE to quit as well. Tkinter is finicky. If you have the first problem, add this line before the quit; if you have the second problem, use it instead of the quit.
root.destroy()
If you want to understand, see this thread. Briefly: destroy destroys any widget and all of its children. And when you call it on a root widget that owns the mainloop, it also ends the loop. quit sends a message to the mainloop that tells it to destroy all widgets it knows about and then kill the Tcl interpreter. Normally, it should always be safe to just quit, but there are some cases where it can miss a widget and freeze up—and when you're running under IDLE, you may be sharing the same Tcl interpreter as IDLE itself, so quit may kill or hang it as well.
Have you already tried to use
import sys
sys.exit()
or directly
raise SystemExit(0)
Related
I would like to implement a very simple GUI for my project. I was previously using just Print statements to output some text and data. However, that is not very conveneint and since a person will need to operate a device that I am coding, he needs to be clearly see the instructions that I am going to display on GUI.
my code:
main()
myConnection = mysql.connector.connect( host=hostname, user=username, passwd=password, db=database )
counter = 0
window = tk.Tk()
window.title("GUI")
window.geometry("400x200")
while(1):
# OPERACIJOS KODAI:
# 0 - PILDYMAS
# 1 - KOMPLEKTAVIMAS
# 2 - NETINKAMAS KODAS
tk.Label(window,text = "Scan barcode here:").pack()
entry = tk.Entry(window)
entry.pack()
var = tk.IntVar()
button = tk.Button(window,text="Continue",command = lambda: var.set(1))
button.pack()
print("waiting...")
button.wait_variable(var)
result = entry.get()
print("Entry string=",result)
var.set(0)
operacijos_kodas=Scanning_operation(myConnection,result)
print("operacijos kodas=",operacijos_kodas)
if(operacijos_kodas == 0):
tk.label(window,text = "PILDYMO OPERACIJA:").pack()
pildymo_operacija(myConnection)
elif(operacijos_kodas == 1):
tk.Label(window,text = "PAKAVIMO OPERACIJA:").pack()
insertData_komplektacija(myConnection,"fmb110bbv801.csv");
update_current_operation(myConnection);
picking_operation();
elif(operacijos_kodas == 2):
print("Skenuokite dar karta")
#break
window.mainloop();
Nothing is being displayed. It just opens up an empty GUI window.
First of all, I am unsure where should I call function window.mainloop().
Secondly, since my system runs in an infinite while loop ( the operation starts when a user scans a bar-code, then he completes an operation and the while loop starts over again (waiting for user to scan a bar-code). So I just simply have to display some text and allow user to input data in the text box.
Could someone suggest me whether this GUI is suitable for my needs or I should look for an alternatives?
UPDATE*********************
I have tried to use mainloop:
print ("Using mysql.connector…")
main()
GPIO_SETUP()
myConnection = mysql.connector.connect( host=hostname, user=username, passwd=password, db=database )
counter = 0
window = tk.Tk()
window.resizable(False,False)
window_height = 1000
window_width = 1200
#window.attributes('-fullscreen',True)
#window.config(height=500,width=500)
#can = Canvas(window,bg='red',height=100,width=100)
#can.place(relx=0.5,rely=0.5,anchor='center')
window.title("GUI")
screen_width = window.winfo_screenwidth()
screen_height= window.winfo_screenheight()
x = int((screen_width/ 2) - (window_width / 2))
y = int((screen_height/ 2) - (window_height / 2))
window.geometry("{}x{}+{}+{}".format(window_width,window_height,x,y))
label1=Label(window,text = "SKENUOKITE BARKODA(GUID) ARBA DAIKTO RIVILINI KODA:")
label1.pack()
entry = Entry(window)
entry.pack()
var = tk.IntVar()
button = Button(window,text="Testi operacija",width = 30,command = lambda: var.set(1))
button.pack()
#button2 = Button(window,text="RESTARTUOTI SISTEMA",width = 30,command = restart_devices())
#button2.pack()
print("waiting...")
button.wait_variable(var)
Scanned_serial = entry.get()
print("Entry string=",Scanned_serial)
var.set(0)
label2=Label(window,text = "Vykdoma operacija:")
label2.pack()
window.update()
window.after(1000,Full_operation(Scanned_serial,label2,window))
window.mainloop()
This is my code. As you can see. i call Full_operation function and then window.mainloop()
my Full_operation:
def Full_operation(Scanned_serial,label2,window):
operacijos_kodas=Scanning_operation(myConnection,Scanned_serial)
print("operacijos kodas=",operacijos_kodas)
if(operacijos_kodas == 0):
label2.config(text = "SPAUSKITE MYGTUKA ANT DEZES KURIA NORITE PILDYTI:")#update the label2
window.update()#call update to update the label
pildymo_operacija(myConnection,Scanned_serial,label2,window)
elif(operacijos_kodas == 1):
insertData_komplektacija(myConnection,"fmb110bbv801.csv");
update_current_operation(myConnection);
#label2.config(text = "IMKITE DAIKTUS IS ZALIOS DEZUTES:")#update the label2
picking_operation(myConnection,label2);
elif(operacijos_kodas == 2):
print("Skenuokite dar karta")
label2.config(text = "NUSKENUOTAS NEGALIMAS KODAS:")#update the label2
window.update()#call update to update the label
How can I ensure that everytime I enter FUll_operation function I start from clean GUI again and start another operation.
Now I am able to complete operation once. After that, the GUI is not responsive.
I have added a print statement at the beggining of my full_operation and it does not execute after I complete it once so my mainwindow does not seem to work properly.
You'll need to adapt your code to work with a GUI. You can't introduce infinite loops in to tkinter GUI's without causing all sorts of problems.
Mainloop should only be called once.
I'd suggest that you move all of your scanning/saving operations in to a separate function which you schedule to occur periodically using the tkinter after method.
For example if you call your function scan you would schedule it to occur after 1 second using
root.after(1000, scan)
A more advanced method would be to have your scanning code running on a separate thread.
Also, you are currently trying to create the label each time you go round the while loop rather than just creating and packing them once and updating the text of the labels when you perform the "scanning". You can update the text of a label using the config method, for example
## Create a label
label1 = tk.Label(window,text = "PAKAVIMO OPERACIJA:")
##Pack the label
label1.pack()
## Update the text later
label1.config(text="New Text")
Here is an example of updating tkinter widgets periodically from a function.
import tkinter as tk
import random
def scanning():
num = random.randint(0,100)
entryTemperature.delete(0, tk.END) #Delete the current contents
entryTemperature.insert(0, f"{num} K") #Add new text
root.after(1000, scanning) #Schedule the function to run again in 1000ms (1 second)
root = tk.Tk()
entryTemperature = tk.Entry(root)
entryTemperature.grid(padx=50,pady=50)
root.after(1000, scanning)
root.mainloop()
I am working an a tool where-in I am getting the initial user credentials and an unique identifier via Tkinter GUI interface. Post that after a lot of data fetching and processing I would get a report into an excel sheet using xlsxwriter package.
I generally exit/close the tkinter window using destroy() method on click of a button. Here, I want to show the user the status of the report creation in a Tkinter messagebox and then close the main window.
Note: I am using .pyw extension, so that the end user who is using the tool shouldn't see the console. So once the user hits the submit button, I will show a label at the footer of the window saying "Processing ..."
Sample code:
from tkinter import *
#Some other libraries are imported
mScrn = Tk()
mScrn.title("Report Generation Tool v1.0")
mScrn.geometry("200x180")
mScrn.resizable(False, False)
tk_uid_lbl = Label(mScrn, text="MVS1 Username")
tk_uid_lbl.pack()
tk_uid_lbl.place(x=20,y=20)
uid = StringVar()
tk_uid = Entry(mScrn, bd=3, textvariable=uid)
tk_uid.pack()
tk_uid.place(x=150, y=20)
tk_pwd_lbl = Label(mScrn, text="MVS1 Password")
tk_pwd_lbl.pack()
tk_pwd_lbl.place(x=20,y=60)
pwd = StringVar()
tk_pwd = Entry(mScrn, bd=3, show='*', textvariable=pwd)
tk_pwd.pack()
tk_pwd.place(x=150, y=60)
tk_ver_lbl = Label(mScrn, text="Version #")
tk_ver_lbl.pack()
tk_ver_lbl.place(x=20,y=100)
ver = StringVar()
tk_ver=Entry(mScrn, bd=3, textvariable=ver)
tk_ver.pack()
tk_ver.place(x=150, y=100)
tk_sub_button = Button(text='Submit', command = show_footer)
tk_sub_button.pack()
tk_sub_button.place(x=150, y=150)
mScrn.mainloop()
#The data provided in the GUI is used for access and a lot of process goes on
#Close the Tkinter window post the process is done
Thanks in Advance. I am using Python3
I am having a hard time understanding your question. My understanding is that using destroy() is exactly what you are looking for. Use destroy() when you are finished. You basically already answered your own question. I would find it helpful if you could explain your question more thoroughly. I agree with Goyo but I cannot comment.
I don't know how to get the data before closing the mainloop(). In
that aspect once that is closed I cannot show the label on the GUI and
then close with user consent (i.e. after clicking 'ok' in message box)
I don't undestand where is your problem, you can save your data with a lot ways, list, module, object, file, etc.
import tkinter as tk
import random
import threading
import time
# Simulate a process
def get_data(callback):
while True:
if len(data) == 10:
break
time.sleep(.5)
data.append(random.randint(1, 200))
callback()
def wait_end(label, tk_var_end, num=0):
label["text"] = "Processing " + " ." * num
num += 1
if num == 4:
num = 0
if not tk_var_end.get():
mScrn.after(500, wait_end, label, tk_var_end, num)
def execute():
for entry in (tk_uid, tk_pwd, tk_ver):
entry['state'] = tk.DISABLED
tk_sub_button.destroy()
tk_process_lbl = tk.Label(mScrn)
tk_process_lbl.pack()
tk_process_lbl.place(x=150,y=150)
tk_var_end = tk.BooleanVar(False)
wait_end(tk_process_lbl, tk_var_end)
process = threading.Thread(
target=get_data,
kwargs=(dict(callback=lambda: tk_var_end.set(True)))
)
process.start()
mScrn.wait_variable(tk_var_end)
mScrn.after(500, tk_process_lbl.config, dict(text='Process completed'))
mScrn.after(1500, mScrn.quit)
mScrn = tk.Tk()
data = []
mScrn.title("Report Generation Tool v1.0")
mScrn.geometry("400x180")
mScrn.resizable(False, False)
tk_uid_lbl = tk.Label(mScrn, text="MVS1 Username")
tk_uid_lbl.pack()
tk_uid_lbl.place(x=20,y=20)
uid = tk.StringVar()
tk_uid = tk.Entry(mScrn, bd=3, textvariable=uid)
tk_uid.pack()
tk_uid.place(x=150, y=20)
tk_pwd_lbl = tk.Label(mScrn, text="MVS1 Password")
tk_pwd_lbl.pack()
tk_pwd_lbl.place(x=20,y=60)
pwd = tk.StringVar()
tk_pwd = tk.Entry(mScrn, bd=3, show='*', textvariable=pwd)
tk_pwd.pack()
tk_pwd.place(x=150, y=60)
tk_ver_lbl = tk.Label(mScrn, text="Version #")
tk_ver_lbl.pack()
tk_ver_lbl.place(x=20,y=100)
ver = tk.StringVar()
tk_ver= tk.Entry(mScrn, bd=3, textvariable=ver)
tk_ver.pack()
tk_ver.place(x=150, y=100)
tk_sub_button = tk.Button(text='Submit', command = execute)
tk_sub_button.pack()
tk_sub_button.place(x=150, y=150)
mScrn.mainloop()
print(data)
But, you can also make your own class which will inherit of Tk, in this class you could override the quit or destroy method of Tk.
I keep getting this issue in my code when I try to use the retrieve command that I had made, I want the button named 'retrieve' to get the information in the entry box. This will then trigger the strGame command.
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1699, in __call__
return self.func(*args)
TypeError: retrieve() missing 1 required positional argument: 'entry'
My code:
from tkinter import *
verif = False
true=True
items=['pistol','knife','sword']
command=False
root=Tk()
root.iconbitmap('GameLogo.ico')
strvar=StringVar()
root.title('RPG Game')
root.geometry('900x600')
root.resizable(False,False)
frame1 = Frame(root, relief=RAISED)
frame1.pack(side=LEFT, fill=Y, padx=10, pady=10)
entry = Entry(frame1).pack(fill=X)
def retrieve(entry):
result=entry.get()
return result
retreive = Button(frame1, command=retrieve, text="Click to input").pack(fill=X)
def srtGame():
try:
if retrieve(e1)==str('drop'):
print("HELLO")
command = True
print ("Your inventory:", items)
dropItem = input("Which item do you want to drop? ")
for i in range(len(items)):
if items[i] == dropItem:
items.remove(dropItem)
print("Your", dropItem,"has been dropped. ")
print("Your inventory", items)
verif = True
if verif == False and command == True:
print("You don't have that item. Please enter another command.")
except:
IndexError
StartGame = Button(frame1, text="Start game.", relief=RAISED, command=srtGame).pack(fill=X)
GameOutput = Label(frame1, textvariable=strvar, relief=RAISED).pack(fill=X)
root.mainloop()
There are numerous errors in this program, which I will clarify here.
Useless variable assignments
The lines that goes like:
widgetVar = Widget(args).geometry(args)
Such as:
entry = Entry(frame1).pack(fill=X)
retreive = Button(frame1, command=retrieve, text="Click to input").pack(fill=X)
Is surely not doing what you intended. By chaining the construction of the widget along with geometry call, what really happens is: Widget(...) returns an instance, on which pack() or other geometry manager is called, that in turn returns None.
Hence all these variables are None, and if you need to store a reference you should break it down to two different lines of code.
Unnecessary "middlemen"
As I understand, you want your game to start (probably load another window/screen) on clicking Start game.
You can just add code to check the Entry contents when the user presses Start game directly, instead of having a button to Input that really does nothing useful as such.
Understand Tkinter vars
The point of using Tkinter vars is to avoid explicitly accessing the Widget to check data that it contains. For example, if you bind StringVar to the Entry, you no longer need to access the Entry object directly.
Mixing command-line and GUI
I would recommend using the Dialog in Tkinter, that can be used to create a pop-up with a text field, to ask the user for which item to drop.
Working Code
from Tkinter import *
items = ['pistol', 'knife', 'sword']
root = Tk()
strvar = StringVar()
root.title('RPG Game')
root.geometry('900x600')
root.resizable(False, False)
frame1 = Frame(root, relief=RAISED)
frame1.pack(side=LEFT, fill=Y, padx=10, pady=10)
entry = Entry(frame1, textvariable=strvar)
entry.pack(fill=X)
def srtGame():
if strvar.get() == str('drop'):
print("HELLO")
print("Your inventory:", items)
# TODO:
# Use Dialog window to ask for item to drop
# Let that be stored in `dropItem`
dropItem = None # Temporary
# Better than using for loop for this
if dropItem in items:
items.remove(dropItem)
print("Your", dropItem, "has been dropped. ")
print("Your inventory", items)
else:
print("You don't have that item. Please enter another command.")
startButton = Button(
frame1, text="Start game.", relief=RAISED, command=srtGame)
startButton.pack(fill=X)
GameOutput = Label(frame1, textvariable=strvar, relief=RAISED)
GameOutput.pack(fill=X)
root.mainloop()
So my first GUI window is meant for taking input from user :
from tkinter import *
from main import *
root = Tk()
root.configure(background="orange")
root.wm_title("Python Project")
label_1 = Label(root, text="Project Name",bg="orange",fg="black")
label_2 = Label(root, text="Site URL Link",bg="orange",fg="black")
entry_1 = Entry(root)
entry_2 = Entry(root)
label_1.grid(row=0,sticky=W)
label_2.grid(row=3333,sticky=W)
entry_1.grid(row=0,column=1,padx=50,ipadx=100)
entry_2.grid(row=3333,column=1,ipadx=100)
def callback():
a1 = entry_1.get()
a2 = entry_2.get()
mmm(a1,a2,root) # main program
button1 = Button(root,text="Run",command=callback)
button2=Button(root,text="Quit",command=root.quit)
button1.grid(row=3334,ipadx=15,padx=50,column=1)
button2.grid(row=3335,column=1,ipadx=15,padx=50)
root.mainloop()
And then i use another GUI window someone in this forum made to show my results :
from tkinter import *
root = Tk()
textbox = Text(root)
textbox.pack()
def redirector(inputStr):
textbox.insert(INSERT, inputStr)
sys.stdout.write = redirector # whenever sys.stdout.write is called, redirector is called.
sys.stderr.write = redirector
root.mainloop()
Now every time i run the first GUI , both GUIs open although there is no way the code reached the second GUI code yet... What is the problem here?
Also the second GUI is supposed to print from a class , but i have a bunch of error when I try to just put it there . What changes I need to make so I can make this 2nd GUI work with a class?
I am making a python program to track various user merits and ranks. It needs to have a graphical user interface. However, when I add a while loop, it hangs! The while loop is needed to hold up the program until input is given. Here is the code:
def __init__(self):
global master, mainCanvas;
tree.write('./oldUsrData.xml')
god = self
#Create Base Window
master=Tk()
master.title("Briar Woods Falcon Robotics Merit Tracker 2.0")
master.maxsize(500,500)
#Create the Credit Label
creditLabel = Label(master, text="Developed by Falcon Robotics. Powered by Python.")
creditLabel.grid(row = 1, column= 1)
creditLabel.pack()
#Make the Main Canvas
mainCanvas = Canvas(master, width = 500, height=500, fill = None)
#Password Entry
inputPass = StringVar()
passwordEntry = Entry(master, textvariable=inputPass, show="$")
passwordEntry.grid(row=2, column=1)
#Define a few Action Functions
def startSetUp():
god.setUp()
def checkPassword(self):
if inputPass.get() == encryptionKey:
passwordEntry.destroy()
mainCanvas.create_text(250,250,text="CORRECT PASSWORD", tags="correctPassword")
continueButton = Button(master, text="Continue", command=startSetUp)
mainCanvas.create_window(270,270, window=continueButton, tags="correctPassword")
else:
exit()
passwordEntry.bind('<Key-Return>', checkPassword)
passwordEntry.pack()
mainCanvas.pack()
master.mainloop()
#define the merit ranks
global meritDict;
meritDict = { -4: 'Untouchable',
-3: 'Scum',
-2: 'Criminal',
-1: 'Mindless Grunt',
0: 'Citizen',
1: 'Vigilante',
2: 'Generic Hero',
3: 'Sharkboy/ Lavagirl',
4: 'Wonderwomen/Matter-eating lad',
5: 'Member of the Justice League',
6: 'X-men',
7: 'Avenger'}
def setUp(self):
#Verify Merit Dictionary
mainCanvas.delete("correctPassword")
mainCanvas.create_text(30,30,text="This is the Merit Ranking System. Change Program Source Code to edit",anchor="nw", tags="merit")
for x in range(-4,8,1):
mainCanvas.create_text(200,(x+4)*20+50, text= str(x) + ": " + str(meritDict[x]), anchor='w')
#create Quitter function
quitted = False
def quitter():
quitted = True
exit()
quit()
quitterButton = Button(master, text="Quit", command=quitter)
mainCanvas.create_window(50, 330, window=quitterButton, tag="quitter")
#Create User Name Entry
userEntryFinished = False;
def getUserEntry():
userVar = StringVar()
user = ""
def userEnter(self):
user = userVar.get()
mainCanvas.create_text(250, 350, text="User Inputted: " + user, tags="userEnter");
userEntryFinished=True;
userEntry = Entry(master, textvariable=userVar)
mainCanvas.create_window(250, 330, window=userEntry, tags="userEnter")
userEntry.bind('<Key-Return>', userEnter)
getUserEntry();
while not userEntryFinished:
pass
... #<--Further, irrelevant code
The code continues, but through trial and error, I determined that the while loop was the source of error. Also, I will need to take input until the quit button is pressed, so how can I go about that? Also, why do all while loops cause this strange problem?
I am using tkinter with python 2.6.
Note: Everything is already defined, just not included in this snippet of code. tree and root are global.
Clarification: Code Hangs when the "Continue" Button is pressed
Also: Is there a way to just wait for user input? That would help a lot.
Your code already has a "while loop" -- that is the loop created when you call mainloop. In GUI programming, you shouldn't be creating your own loops in code to wait for user input. Instead, you create widgets and then respond to events that occur in/on those widgets.
The specific reason your program hangs is because your while loop prevents the event loop from doing what is supposed to do, which is to respond to events. Not just user events, but requests from the system to redraw itself.
The solution is simply to remove your while not userEntryFinished loop, and instead redesign your code to respond to events. Put all the code that is after that loop into a function. Then, in getUserEntry, instead of / in addition to setting the flag, you can call this function.