Full disclosure, I am a Python newb, and even newer to Tkinter. I have the below code which I was able to parse together from various sources which shows the buttons and dialogue box as I want them to be shown. The "Cancel" button works appropriately, but when I enter proper credentials and click "OK", nothing happens. Based on what I have read, I think I may have a binding and/or callback issue, but I am not sure. After several hours of reading and watching YouTube videos, I am banging my head against the desk. Any help would be greatly appreciated.
from Tkinter import *
master = Tk()
def login_info():
bankUsername = bank_user.get()
bankPassword = bank_pass.get()
return
Label(master, text=str(properBankName) + " Username: ").grid(row=0, sticky = "E")
Label(master, text="Password: ").grid(row=1, sticky = "E")
master.title("Please Enter Credentials")
bank_user = Entry(master)
bank_pass = Entry(master)
bank_user.grid(row=0, column=1)
bank_pass.grid(row=1, column=1)
Button(master, height=1, width=8, text='OK', command=login_info).grid(row=3, column=0, sticky = "E", pady=4)
Button(master, height=1, width=8, text='Cancel', command=master.quit).grid(row=3, column=1, sticky = "W", pady=4)
master.mainloop()
I use global variables to keep values and then I use master.destroy() to close window.
(on Linux master.quit() doesn't execute master.destroy() which close window)
I use variable login to recognize which button was clicked.
I use columnspan=2 for Entry and move Buttons one cell to the right - and now it looks better.
BTW: lines Button(...).grid(...) were very long so I splited them into two lines to make more readable.
Code:
from Tkinter import *
# --- functions ---
def login_info():
# inform function to use external/global variables
global bankUsername
global bankPassword
global login
login = True
bankUsername = bank_user.get()
bankPassword = bank_pass.get()
# quit window
master.destroy()
# --- main ---
# create global variables
bankUsername = None
bankPassword = None
login = False
# - GUI
master = Tk()
Label(master, text="Username:").grid(row=0, sticky="E")
Label(master, text="Password:").grid(row=1, sticky="E")
master.title("Please Enter Credentials")
bank_user = Entry(master)
bank_pass = Entry(master)
bank_user.grid(row=0, column=1, columnspan=2)
bank_pass.grid(row=1, column=1, columnspan=2)
b = Button(master, height=1, width=8, text='OK', command=login_info)
b.grid(row=3, column=1, sticky="E", pady=4)
b = Button(master, height=1, width=8, text='Cancel', command=master.destroy)
b.grid(row=3, column=2, sticky="W", pady=4)
master.mainloop()
# --- executed after closing window ---
if login: # if login is True:
print(bankUsername)
print(bankPassword)
else:
print("Canceled")
Related
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 3 years ago.
Python beginner with little tkinter or OOP experience.
Functional code from a tkinter youtube tutorial, which called all tkinter functions globally, copied and modified into seperate functions.
Code now calls functions immediately upon start.
Photo no longer displays if exit button is commented.
What am I missing?
#simple glossary example demonstrating tkinter basics
#program broken by adding main and attempting to partition into seperate functions
from tkinter import *
dictionary_db = {
'algorithm' : 'Algorithm: Step by step instructions to complete a task.',
'bug' : 'Bug: Piece of code that causes a program to fail.'
}
photo_file_name = "logo.png"
#click function used by submit button
def click(text_entry, output):
entered_text = text_entry.get()
output.delete(0.0, END)
try:
definition = dictionary_db[entered_text]
except:
definition = "Sorry not an exisiting word. Please try again."
output.insert(END, definition)
#exit function used by exit button
def close_window(window):
window.destroy()
exit()
#configure window
def config(window):
# config
window.title("My tkinter demo")
window.configure(background="black")
#create objects
photo1 = PhotoImage(file=photo_file_name)
photo_label = Label (window, image=photo1, bg="black")
entry_label = Label(window, text="Enter the word you would like a definition for: ", bg="black", fg="white", font="none 12 bold")
text_entry = Entry(window, width=20, bg="white")
output = Text(window, width=75, height=6, wrap=WORD, background="white")
submit_button = Button(window, text="SUBMIT", width=6, command=click(text_entry, output))
definition_label = Label (window, text="\nDefinition", bg="black", fg="white", font="none 12 bold")
exit_label = Label (window, text="click to exit", bg="black", fg="white", font="none 12 bold")
exit_button = Button(window, text="Exit", width=6, command=close_window(window))
#place objects
photo_label.grid(row=0, column=0, sticky=E)
entry_label.grid(row=1, column=0, sticky=W)
text_entry.grid(row=2, column=0, sticky=W)
submit_button.grid(row=3, column=0, sticky=W)
definition_label.grid(row=4, column=0, sticky=W)
output.grid(row=5, column=0, columnspan=2, sticky=W)
exit_label.grid(row=6, column=0, sticky=W)
exit_button.grid(row=7, column=0, sticky=W)
#main
def main():
window = Tk()
config(window)
window.mainloop()
if __name__ == '__main__':
main()
'''
You're invoking the functions, when all you really should be doing is binding the functions to the command keyword argument.
Wrong:
def my_function():
print("you clicked the button")
button = Button(command=my_function())
Right:
def my_function():
print("you clicked the button")
button = Button(command=my_function)
However, the "Right" way of doing this won't work for you, since your functions accept parameters. In that case you can make a lambda:
def my_function(arg):
print(arg)
button = Button(command=lambda: my_function("hello world"))
So basically I am practising using Tkinter and I was going to make a little clicker game based on anime. I have researched loads, however, no matter what I try the text saying how many RC cells I have won't show anything at all. please keep it simple as I'm still new to coding.
from tkinter import *
rcc=1
x=1
#click function
def click():
global rcc
rcc=rcc+1
return rcc
while x==1:
rccc=str(rcc)
window=Tk()
window.title("my click game boi")
rc=StringVar()
rc.set=(rccc)
window.configure(background="black")
##### my photo
photo1=PhotoImage(file="kanekipic.gif")
Label (window, image=photo1, bg='black') .grid(row=0, column=0, sticky=E)
Button(window, text="eat", width=3, command=click) .grid(row=3, column=0,
sticky=W)
Label1=Label(window, textvariable=rc, bg="red", fg="white") .grid(row=1, column=0, sticky=S)
print (rcc)
window.mainloop()
The best solution (in the sense that it preserves the desired goal and is "kept simple"), I came up with is:
#!/usr/bin/env python3
from tkinter import *
rcc = 1
def click():
global rcc
rcc += 1
rc.set(rcc)
print('rcc was increased to {}'.format(rcc))
if __name__ == '__main__':
window = Tk()
window.title("my click game boi")
window.configure(background='black')
rc = IntVar()
photo1 = PhotoImage(file="kanekipic.gif")
Label(window, image=photo1, bg='black').grid(row=0, column=0, sticky=E)
Button(window, text="eat", width=3, command=click).grid(row=3, column=0, sticky=W)
Label(window, textvariable=rc, bg="red", fg="white").grid(row=1, column=0, sticky=S)
window.mainloop()
Whenever you click on the eat button, the counter will be increased.
I wrote this piece of code, which is supposed to ask a user if all of his files have the same date and if yes, that he should write his date into a grid.
After entering the dates both windows should disappear and i want to keep the date.
Unfortunately I don't manage to let the first Input-Box disappear and after this whole procedure the entry date is [ ] again.
from tkinter import *
entry_date = []
if amountfiles == 1:
def moredates():
master.destroy()
def setdate():
def entry_date():
entry_date = e1.get()
entry_date = str(entry_date)
print("Date for all files is: ",entry_date)
master.destroy()
def quit():
sys.exit()
master = Tk()
Label(master, text="Please enter date (format YYYYMMDD, i.e. 20160824): ").grid(row=0)
e1 = Entry(master)
e1.grid(row=0, column=1)
Button(master, text='Quit', command=master.destroy).grid(row=3, column=1, sticky=W, pady=4)
Button(master, text='Insert', command=entry_date).grid(row=2, column=1, sticky=W, pady=4)
mainloop( )
master = Tk()
Label(master, text="Do all files have the same date?").grid(row=0)
Button(master, text='No...', command=moredates).grid(row=2, column=0, sticky=W, pady=4)
Button(master, text='Yes!', command=setdate).grid(row=1, column=0, sticky=W, pady=4)
Button(master, text='Close & Contiune', command=master.destroy).grid(row=3, column=0, sticky=W, pady=4)
mainloop( )
As the outer master variable is re-assigned in the function setdate(), the call master.destroy() will only close the new master, not the outer master. Try modifying the function setdate() as below:
def setdate():
def append_date():
date = e1.get() # get the input entry date
entry_date.append(date) # save the input date
print("Date for all files is: ", date)
master.destroy()
top = Toplevel() # use Toplevel() instead of Tk()
Label(top, text="Please enter date (format YYYYMMDD, i.e. 20160824): ").grid(row=0)
e1 = Entry(top)
e1.grid(row=0, column=1)
Button(top, text='Quit', command=master.destroy).grid(row=3, column=1, sticky=W, pady=4)
Button(top, text='Insert', command=append_date).grid(row=2, column=1, sticky=W, pady=4)
master.wait_window(top) # use Tk.wait_window()
I am in the process of learning basic Python. I am currently attempting to create a simple calculator program that only has addition and subtraction. I have one issue though. I am not sure how I would add text to my Python label upon button press. Right now, upon pressing the '1' button, my program will change the display label to the text "1". However, I want my program to add text, not set it.
For example, if I press 'button 1' 5 times, it currently will reset the label text 5 times and will result with a single 1. I want it to add the number to the label upon press, not replace.
Current Result after pressing button 5 times: 1
Requested result after pressing button 5 times: 11111
Here is my current code for the program. If anything is unclear, just ask; thanks.
from tkinter import *
window = Tk()
# Creating main label
display = Label(window, text="")
display.grid(row=0, columnspan=3)
def add_one():
display.config(text='1')
# Creating all number buttons
one = Button(window, text="1", height=10, width=10, command=add_one)
two = Button(window, text="2", height=10, width=10)
three = Button(window, text="3", height=10, width=10)
four = Button(window, text="4", height=10, width=10)
five = Button(window, text="5", height=10, width=10)
six = Button(window, text="6", height=10, width=10)
seven = Button(window, text="7", height=10, width=10)
eight = Button(window, text="8", height=10, width=10)
nine = Button(window, text="9", height=10, width=10)
zero = Button(window, text="0", height=10, width=10)
# Placing all number buttons
one.grid(row=1, column=0)
two.grid(row=1, column=1)
three.grid(row=1, column=2)
four.grid(row=2, column=0)
five.grid(row=2, column=1)
six.grid(row=2, column=2)
seven.grid(row=3, column=0)
eight.grid(row=3, column=1)
nine.grid(row=3, column=2)
# Creating all other buttons
add = Button(window, text="+", height=10, width=10)
subtract = Button(window, text="-", height=10, width=10)
equal = Button(window, text="=", height=10, width=10)
# Placing all other buttons
add.grid(row=4, column=0)
subtract.grid(row=4, column=1)
equal.grid(row=4, column=2)
window.mainloop()
You should use a StringVar for this. And your callback needs to get the current contents of the StringVar, modify it, and use the modified string to set the new value of the StringVar. Like this:
import tkinter as tk
window = tk.Tk()
# Creating main label
display_text = tk.StringVar()
display = tk.Label(window, textvariable=display_text)
display.grid(row=0, columnspan=3)
def add_one():
s = display_text.get()
s += '1'
display_text.set(s)
one = tk.Button(window, text="1", height=10, width=10, command=add_one)
one.grid(row=1, column=0)
window.mainloop()
BTW, you should try to make your program a little more compact by using for loops to create and lay out your buttons, in accordance with the DRY principle.
Also, it's not a good idea to use from tkinter import *. It imports over 130 names into your namespace, making it easy to create name collisions if you accidentally use a Tkinter name for one of your own variables or functions.
You can define add_one like the following, to first get the existing value and then append a new value to it:
def add_one():
current_value = display.cget("text")
new_value = current_value + "1"
display.config(text=new_value)
Is this what you're looking for:
from tkinter import *
root = Tk()
var = StringVar()
def f1():
var.set(" ")
var.set("1")
def f2():
var.set(" ")
var.set("2")
label = Label(root, textvariable=var)
label.pack()
button1 = Button(root, text="One", command=f1)
button1.pack()
button2 = Button(root, text="Two", command=f2)
button2.pack()
?
I have a very basic program that spits out a string of values, but I am not quite sure how to clear these values. At the moment I have it set up so that I just exit the window and start a new one so that I'm not rewriting over new values all the time. Is there a simple way to add another button that just says something like 'clear' and does exactly that? My code is as below:
def create_widgets(self):
self.entryLabel = Label(self, text="Please enter a list of numbers:")
self.entryLabel.grid(row=0, column=0, columnspan=2)
self.listEntry = Entry(self)
self.listEntry.grid(row=0, column=2, sticky=E)
self.entryLabel = Label(self, text="Please enter an index value:")
self.entryLabel.grid(row=1, column=0, columnspan=2, sticky=E)
self.indexEntry = Entry(self)
self.indexEntry.grid(row=1, column=2)
self.runBttn = Button(self, text="Run Function", command=self.psiFunction)
self.runBttn.grid(row=2, column=0, sticky=W)
self.answerLabel = Label(self, text="Output List:")
self.answerLabel.grid(row=2, column=1, sticky=W)
self.clearBttn = Button(self, text="Clear Output", command=)
self.clearBttn.grid(row=3, column=0, sticky=W)
def clear():
config.self.entryLabel(text="")
tk.Button(text="write", command=write).grid()
tk.Button(text="clear", command=clear).grid()
self.clearBttn = Button(self, text="Clear Output", command=clear)
self.clearBttn.grid(row=3, column=0, sticky=W)
You kinda asked two different questions here. I'll address the first, since that is what you came in with. To change the label, just update its text using the config method:
import Tkinter as tk
root = tk.Tk()
label = tk.Label()
label.grid()
def write():
label.config(text="Blah"*6)
def clear():
label.config(text="")
tk.Button(text="write", command=write).grid()
tk.Button(text="clear", command=clear).grid()
root.mainloop()