In my previous Question grab_set() function not working in tkinter, Flavio Moraes suggested me a code.
When I tried to implement it in my main code, I was getting an error which I have recorded here: https://youtu.be/qQyeTmbdqT0
Here is a piece of that code which produces exactly the same error:
from tkinter import *
def login():
#ALL GIFs etc.
top.resizable(0, 0)
top.title("IDLE for MySQL- Login")
top.geometry("1080x720")
submit_button = Button(top,
text="Login", fg="#FFFFFF", bd=4, bg="#000000", width=8, font=("Helvetica", 18), command=check).place(
x=410,
y=400)
quit_button = Button(top,
text="Quit", fg="#FFFFFF", bd=4, bg="#000000", width=8, font=("Helvetica", 18), command=exit).place(
x=550,
y=400)
def check():
global nlabel, top
#user = _id.get() [_id = Entry]
#passw = _p.get() [_p = Entry]
global mydb, c
while True:
try:
"""
mydb = mysql.connector.connect(
host="localhost",
user=user,
password=passw
)
c = mydb.cursor(buffered=True)"""
raise TypeError #Any error just to produce a "Wrong Password" Effect
except:
inc = Toplevel()
inc.wait_visibility()
inc.grab_set_global()
inc.focus_set()
inc.geometry("300x100")
msg = Label(inc,
text="Incorrect User ID/ Password", font=("Helvetica", 12)).place(
x=10,
y=15)
button1 = Button(inc,
text="Ok", bg="#FFFFFF", bd=3, fg="#000000", font=("Helvetica", 18), command=closepop).place(
x=190,
y=55)
button2 = Button(inc,
text="Exit", bg="#FFFFFF", bd=3, fg="#000000", font=("Helvetica", 18), command=exit).place(
x=240,
y=55)
else:
break
def closepop():
global inc
inc.grab_release()
inc.destroy()
top = Tk()
login()
top.mainloop()
From what I understand, the problem is that every time the code is checking for the password regardless of any button pressed by the used or not. I even tried butting it in a loop, but that also didn't work.
The while True loop is an infinite loop and inside the loop your raising an error, which will lead to execution of the except block, and since your not properly breaking out of the loop, it keeps on happening. Its not clear what your trying to do with the code, but this is the problem. One potential solution is to use after() which will repeat the function a given amount time, in ms. Like root.after(5000,check), this will execute check() after 5000ms(5 sec).
Related
Really hoping to get an explanation /fix for this issue. Using Python3 and tkinter.
I have a program window that calls a chain of functions for log in to a database. One of them calls a toplevel() log in dialog that should return an array / list of values. The toplevel dialog creates a set of entries that are read by a nested function and values stashed in a global list and then destroys toplevel window. The list is returned by the outer function to an original calling function.
Works great except if this function call originates from a higher level TK dialog. As is, I have to close out the entire program to get a return from that function. How do I fix this? Function listed here
Thanks!
# GUI constructor for log in
def login():
# Create logwin window
logwin = Toplevel()
logwin.title("Log In")
# Called by login() GUI/bsubmit - returns credentials from log in GUI
def userinfo():
global carray
sname=serventry.get()
lname=lnentry.get()
pname=passentry.get()
carray = [sname, lname, pname]
logwin.destroy()
print("userinfo() = ", carray)
# Create GUI
servlabel = Label(logwin, text="Server Address: ")
servlabel.grid(row=0, column=0)
serventry = Entry(logwin)
serventry.grid(row=0, column=1)
serventry.focus()
lnlable = Label(logwin, text="User Name: ")
lnlable.grid(row=1, column=0, padx=5)
lnentry = Entry(logwin)
lnentry.grid(row=1, column=1, padx=4)
passlabel = Label(logwin, text="Enter Password: ")
passlabel.grid(row=2, column=0)
passentry = Entry(logwin, show="*")
passentry.grid(row=2, column=1)
bsubmit = Button(logwin, text="Submit", command=userinfo, default='active')
bsubmit.grid(row=4, column=1, columnspan=2)
logwin.mainloop()
print("login() end:", carray)
return(carray)
I found the answer to this one:
I was using logwin.destroy in the inner function userinfo() and for whatever reason this did not allow the function to continue while the main Tk() construct was running. I then tried placing logwin.quit() on the inner loop and this allowed the function to progress as intended but did not destroy the logwin construct. Placing logwin.destroy() after the logwin.mainloop() then takes care of this. Data is passed back to my program and life is good.
def login():
# Create logwin window
logwin = Toplevel(root)
logwin.title("Log In")
# Called by login() GUI/bsubmit - returns credentials from log in GUI
def userinfo():
global carray
sname=serventry.get()
lname=lnentry.get()
pname=passentry.get()
carray = [sname, lname, pname]
logwin.quit()
print("userinfo() = ", carray)
return carray
# Create GUI
servlabel = Label(logwin, text="Server Address: ")
servlabel.grid(row=0, column=0)
serventry = Entry(logwin)
serventry.grid(row=0, column=1)
serventry.focus()
lnlable = Label(logwin, text="User Name: ")
lnlable.grid(row=1, column=0, padx=5)
lnentry = Entry(logwin)
lnentry.grid(row=1, column=1, padx=4)
passlabel = Label(logwin, text="Enter Password: ")
passlabel.grid(row=2, column=0)
passentry = Entry(logwin, show="*")
passentry.grid(row=2, column=1)
bsubmit = Button(logwin, text="Submit", command=userinfo, default='active')
bsubmit.grid(row=4, column=1, columnspan=2)
logwin.bind('<Return>', userinfoalt) # binds alternate credentials function to the return key.
logwin.mainloop()
logwin.destroy()
print("login() end:", carray)
return(carray)
I'm making a trivia game where data is from www.opentdb.com. I want it to continually loop through the main program after it tells you whether your answer is correct or not. (clicking an answer and shows green label but will stay at that screen). I would like it to wait a few seconds and have tried using .after(3000, main()) but do not know how to reset the screen and repeat.Im sorry if this sounds very confusing. Thank you for your assistance :)
from tkinter import *
import trivia
import html
t = trivia.Trivia()
root = Tk()
root.geometry("1366x768")
root.configure(bg='#4dc4ff')
root.iconbitmap("icon.ico")
root.title("Trivia Party!")
frame = Frame(root, bg='#4dc4ff')
class Buttons:
def __init__(self, text):
self.text = html.unescape(text) # remove html entities
self.correct_label = Label(root, text="Correct!", font=("Arial", 30), background="#98FB98", width=20, height=2) # green correct label
def reveal_answer(self):
if self.text == t.return_correct_answer(): # if its the right answer
self.correct_label.pack(pady=175)
frame.destroy()
else:
self.correct_label.config(text="Incorrect", background="#ff6347")
self.correct_label.pack(pady=175)
Label(root, background="#4dc4ff", text=("The correct answer was: " + t.return_correct_answer()),
font=("Arial", 40)).pack()
frame.destroy()
def create(self):
Button(frame, text=self.text, borderwidth=0, highlightbackground="#00abff", font=("Helvetica", 30),
command=self.reveal_answer).pack(side=LEFT, expand=YES)
frame.pack(fill=BOTH, expand=YES)
buttons = []
question = Label(frame, text=html.unescape(t.return_question()), font=("Arial", 25), height=3, bg="#00abff").pack(fill=X)
for i in t.all_answers: # t.all_answers is pulling all of the multiple choice answers ie "coke", "pepsi" "sprite"
buttons.append(Buttons(i).create()) # i is the individual answer eg "pepsi" and is making a button
root.mainloop()
This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 2 years ago.
I have a small issue for which I can`t find the reason.
I have the following GUI, and it pops the message box when I run it, even though it is inside a procedure which is triggered only on button press.
Tried even creating a secondary function which will show only the message box and still did not fix the issue.
Thank you for your help... I am quite sure that there is an easy fix which I just do not see...
import tkinter as tk
from tkinter import ttk
import tkinter.messagebox
import jl_generator
def run():
jl_generator.run_process()
tkinter.messagebox.showerror('Done','Done')
def show():
temp_list = user_input_list
for i in range(0, len(user_input_list[0])):
listBox.insert("", "end", values = (user_input_list[0][i],user_input_list[1][i],user_input_list[2][i],user_input_list[3][i],user_input_list[4][i],user_input_list[6][i],user_input_list[8][i]))
# Column Names for the TreeView
cols = ('Entity', 'Customer Nr', 'Account Code', 'Profit Centre', 'Partner Profit Centre', 'Amount', 'Nr Of Journal Lines')
# Input data for the tree view
user_input_list, journal_code = jl_generator.get_user_input()
#Creating the
root = tk.Tk()
root.title('JL Generator')
#Create the treeview
listBox = ttk.Treeview(root, columns=cols, show='headings')
for col in cols:
listBox.heading(col, text=col)
listBox.grid(row=1, column=0, columnspan=3)
#-------------LABELS--------------
#Title Label
label = tk.Label(root, text="Journal Lines Generator", font=("Arial",30)).grid(row=0, columnspan=3)
#Journal Code Label
show_journal_code = tk.Label(root, text = 'Journal Code = ' + journal_code).grid(row=6, column=1)
#Number of Journal Lines Label
show_number_of_journal_lines = tk.Label(root, text = 'Number of Journal Lines = ' + str(sum(user_input_list[8][i] for i in range(0, len(user_input_list[0]))))).grid(row=5, column=1)
#------------BUTTONS-----------
#Run the Generation
run_process = tk.Button(root, text="Generate JLs", width=15, command=run()).grid(row=4, column=1)
#Show the input data
showScores = tk.Button(root, text="Show Input", width=15, command=show).grid(row=4, column=0)
#Close the window
closeButton = tk.Button(root, text="Exit", width=15, command=exit).grid(row=4, column=2)
root.mainloop()
run_process = tk.Button(root, text="Generate JLs", width=15, command=run()).grid(row=4, column=1)
this is incorrect.
I used to feel confused about this.
You should use:
run_process = tk.Button(root, text="Generate JLs", width=15, command=run).grid(row=4, column=1)
In python,function is an object,call function should use function()
If you debug this code,you will find that after debug this code
run_process = tk.Button(root, text="Generate JLs", width=15, command=run()).grid(row=4, column=1)
you will find it will call run function and run it.
And Finally,run_process["command"] will be the returned value ofrun()
I'm new to Python and Tkinter. Here is a game I made for practice with GUIs. The problem I am having is when restarting a new game the code allows the loser to give the first guess. This is an unintended plus that I can't explain. My code is intended to give player 1 the first guess always, but that doesn't happen. I have done my due diligence and think the problem is in the transition between the reset_game method and the player_guess method.
Please describe why my code is not giving player1 the first guess when restarting the game.
If there are any comments as to format, structure, DRY issues, etc. I would appreciate those also.
''' 2 player guessing game with GUI'''
from tkinter import *
from random import randint
import tkinter.messagebox
# create window
root = Tk()
root.title('2 Player Guessing Game')
target_number = randint(1, 100)
message = StringVar()
current_player = ''
# reset target number for a new game
def reset_target_number():
global target_number
target_number = randint(1, 100)
# sets current player variable
def set_current_player(num):
global current_player
current_player = num
# gets player's guess and toggles turn back and forth. passes guess to game_play method
def player_guess():
if p1_entry.get():
print(target_number)
guess = int(p1_entry.get())
set_current_player(1)
game_play(guess)
p1_entry.delete(0, END)
p1_entry.config(state=DISABLED)
p2_entry.config(state=NORMAL)
p2_entry.focus_set()
#print(current_player + ' should be 1')
else:
guess = int(p2_entry.get())
set_current_player(2)
game_play(guess)
p2_entry.delete(0, END)
p2_entry.config(state=DISABLED)
p1_entry.config(state=NORMAL)
p1_entry.focus_set()
#print(current_player + ' should be 2')
# evaluates the guess and returns a message to the message_label. also, calls congrats method when a player has
# guessed correctly
def game_play(guess):
if guess == target_number:
display_message('Winner!')
congrats(current_player)
elif guess < target_number:
display_message('Too Low')
print(current_player, ' is low')
else:
display_message('Too High')
print(current_player, ' is high')
# displays appropriate message in message_label
def display_message(result):
message.set(result)
# opens message box to declare winner. Gives option to exit or play again
def congrats(player_num):
if player_num == 1:
winner = "Player 1"
else:
winner = 'Player 2'
answer = tkinter.messagebox.askquestion('Congratulations', winner + ' is the WINNER!! \n Would you like to play again?')
if answer == 'no':
root.quit()
else:
reset_game()
def reset_game():
reset_target_number()
message = StringVar()
set_current_player(0)
#print(target_number, message, current_player)
p2_entry.delete(0, END)
p1_entry.delete(0, END)
p2_entry.config(state=DISABLED)
#print('Did this run?')
p1_entry.config(state=NORMAL)
#print('Did this also run?')
p1_entry.focus_set()
# create instruction widgets
instruc_label = Label(root, text='Game Instructions')
instruc_label.grid(row=0, column=0, padx=2, pady=2, sticky=W)
instructions = Label(root, text="Players will take turns guessing the mystery number. The first player to guess correctlyl wins! The other player doesn't win: but that doesn't mean the other player is a loser. It just means that that player did not win this time. No amount of failures determines whether a person is a loser. It is a person's attitude and character towards their failures that determines a winner and a loser.", wraplength=490, justify=LEFT)
instructions.grid(row=1, column=0, columnspan=3, padx=5, pady=5)
# create game play widgets
p1_label = Label(root, text='Player 1')
p1_label.grid(row=2, column=0)
p1_entry = Entry(root, font='Helvetica 44 bold', fg='black', bg='lightyellow', relief=SUNKEN, width=4, state=NORMAL, justify=CENTER)
p1_entry.grid(row=3, column=0)
p1_entry.focus_set()
message_label = Label(root, textvariable=message, fg='white', bg='darkgreen', relief=GROOVE, height=10, width=20)
message_label.grid(row=2, column=1, rowspan=2)
p2_label = Label(root, text='Player 2')
p2_label.grid(row=2, column=2)
p2_entry = Entry(root, font='Helvetica 44 bold', fg='black', bg='lightyellow', relief=SUNKEN, width=4, state=DISABLED, justify=CENTER)
p2_entry.grid(row=3, column=2)
# create submit button to enter guesses
submit = Button(root, text='Submit', width=20, command=player_guess)
submit.grid(row=4, columnspan=3, pady=5, padx=5)
root.mainloop()
Mahalo!
In player_guess, winner decided in game_play.
If there is a winner, you are resetting the game with reset_game but your code continues after game_play returns and changes states of entries. game_play should be the last thing player_guess should do.
def player_guess():
if p1_entry.get():
....
game_play(guess)
else:
....
game_play(guess)
or just move game_play out of if-elses since you are calling it either way.
def player_guess():
if p1_entry.get():
....
guess = int(p1_entry.get())
else:
....
guess = int(p2_entry.get())
game_play(guess)
i am using tkinter to make a gui and have made various different buttons and now i have made all this i am unsure how to correctly make the first gui box close as the second one opens (sign_in function)
from tkinter import *
class login:
def __init__(self, master):
frame = Frame(master)
frame.grid()
self.button1 = Button(frame, text="signup", fg="green",command=self.sign_in)
self.button2 = Button(frame, text="sign in", fg="black",)
self.button3 = Button(frame, text="quit", fg="red", command=frame.master.destroy)
self.button1.grid(stick=W)
self.button2.grid(stick=W)
self.button3.grid(stick=W)
def sign_in(self):
frame = Frame()
frame.grid()
name = Label(root, text="Name: ")
password = Label(root, text="password: ")
entry1 = Entry(root)
entry2 = Entry(root)
name.grid(row=0, sticky=E)
password.grid(row=1, sticky=E)
entry1.grid(row=0, column=1)
entry2.grid(row=1, column=1)
c = Checkbutton(root, text="keep me logged in")
c.grid(columnspan=2, sticky="w")
root = Tk()
account=login(root)
root.mainloop()
Your code contains some indentation errors so I'll just go by your question.
when i click the button 'signup' it closes that gui and opens the next one
You can do so by first withdrawing your root window like this: root.withdraw() which will hide your original window. Then create a Toplevel window like this: newWindow = tk.Toplevel(root) to create a new window. You will just need to place these lines in the button command call.
Here's what you can change in the sign_in note that I changed all the masters to frame and not root:
def sign_in(self):
root.withdraw()
frame = Toplevel(root)
name = Label(frame, text="Name: ")
password = Label(frame, text="password: ")
entry1 = Entry(frame)
entry2 = Entry(frame)
name.grid(row=0, sticky=E)
password.grid(row=1, sticky=E)
entry1.grid(row=0, column=1)
entry2.grid(row=1, column=1)
c = Checkbutton(frame, text="keep me logged in")
c.grid(columnspan=2, sticky="w")