Tkinter IntVar weird Value - python

I made a new object of tk.IntVar and called it pwHardness
but its value is something random like 140358607937898IntVar.
i want the radio buttons to set the value of the variable pwHardness 1 or 2
import tkinter as tk
pwHardness = tk.IntVar
window = tk.Tk()
window.geometry("1600x500")
window.configure(bg="#323e52")
Label = tk.Label(text="Password Gen", background="#323e52", foreground="#fafafa")
Label.config(width=200)
Label.config(font=("Courier", 44))
setPwRadioButtonEasy = tk.Radiobutton(
text="Easy PW",
padx = 20,
var=pwHardness,
variable=pwHardness,
value=1,
)
setPwRadioButtonHard = tk.Radiobutton(
text="Hard PW",
padx = 20,
var=pwHardness,
variable=pwHardness,
value=2,
)
label1 = tk.Label(text=pwHardness)
Label.pack()
setPwRadioButtonEasy.pack()
setPwRadioButtonHard.pack()
label1.pack()
window.mainloop()
FYI This is going to be a Password Generator.

You aren't initializing the variable, you're just taking the IntVar object.
pwHardness = tk.IntVar()
would initialize a new IntVar – you're missing the parentheses.
Additionally, you're passing the var as a "string" value to text.
You'd want
label1 = tk.Label(text=pwHardness.get())
to "read" the variable into the label. However, it won't refresh automatically with that configuration.

You are missing parentheses after pwHardness = tk.IntVar. It should be pwHardness = tk.IntVar(). Additionally, change label1 = tk.Label(text=pwHardness) to label1 = tk.Label(textvar=pwHardness), so the label gets automatically updated. And, tk.IntVar must be initiated with a parent, e.g. the toplevel window. Example :
import tkinter as tk
root = tk.Tk()
var = tk.IntVar(root)
label = tk.Label(root, textvar=var)
label.pack()
while True:
inp = input("enter new value ")
if inp != "quit":
var.set(int(inp))
else:
break

Related

How can I set the text of a ttk.Entry?

It appears that I cannot set the text of a ttk.Entry with a root of ttk.Label during an event:
import tkinter
from tkinter import ttk
def modify_label_text(event):
entry = event.widget
newvalue = entry.get()
label = entry.master
label.configure(text=newvalue)
entry.unbind("<Return>")
entry.pack_forget()
label.focus()
def create_entry(event):
label = event.widget
oldvalue = label.cget("text")
newvalue = tkinter.StringVar()
entry = ttk.Entry(label, textvariable=newvalue)
'''
entry = tkinter.Entry(label, textvariable=newvalue)
'''
entry.pack()
entry.delete(0, "end")
entry.insert(0, oldvalue)
entry.bind("<Return>", modify_label_text)
entry.focus()
root = tkinter.Tk()
clickme = ttk.Label(root, width=16)
clickme.pack()
clickme.bind("<Button-1>", create_entry)
clickme.focus()
root.mainloop()
When I click the empty label and enter a new value, the value is reflected in the label. However, if I click the label again to "edit" the value, the entry field is empty again.
Furthermore, if I use tkinter.Entry rather than ttk.Entry, it appears to work.
Why is the text of the entry only set when using tkinter.Entry? How can I fix this to work with ttk.Entry?
This may not an answer, but a bit too large for a comment. Also could someone elaborate this behavior in a different enviorment. I ran that code with:
Mashine:
Windows 10 Home; x64-base,Intel(R) Core(TM) i3-2120 # 3.30GHz, 3300 MHz, 2Cores
with
Python 3.7.2 and tkinter 8.6
After some research I couldnt find a reason for this behavior. Neither in the docs, nor in the sometimes tricky style_map or in the default bindings.
Can I assume that you create the labels with the entries in a function/loop? You may want to reuse the entry, because for some reason the exact same code works if you adress the entry by winfo_children(). And even if I call .update_idletasks() or just for experience the evil .update() it dosent work for no reason.
import tkinter
from tkinter import ttk
def modify_label_text(event):
entry = event.widget
newvalue = entry.get()
label = entry.master
label.configure(text=newvalue)
entry.unbind("<Return>")
entry.pack_forget()
label.focus()
def create_entry(event):
label = event.widget
oldvalue = label.cget("text")
newvalue = tkinter.StringVar()
if len(label.winfo_children()) == 0:
print('new')
entry = ttk.Entry(label, textvariable=newvalue)
'''
entry = tkinter.Entry(label, textvariable=newvalue)
'''
e = label.winfo_children()[0]
e.pack()
e.delete(0, "end")
e.insert(0, oldvalue+' works')
e.bind("<Return>", modify_label_text)
e.focus()
root = tkinter.Tk()
clickme = ttk.Label(root, width=16)
clickme.pack()
clickme.bind("<Button-1>", create_entry)
clickme.focus()
root.mainloop()
Another solution could be:
def create_entry(event):
label = event.widget
oldvalue = label.cget("text")
newvalue = tkinter.StringVar()
entry = ttk.Entry(label, textvariable=newvalue)
'''
entry = tkinter.Entry(label, textvariable=newvalue)
'''
root.after(100,after_time,entry,oldvalue)
def after_time(entry,oldvalue):
entry.pack()
entry.delete(0, "end")
entry.insert(0, oldvalue)
entry.bind("<Return>", modify_label_text)
entry.focus()
I suggest you create an instance of Entry outside the function and simply pack() and pack_forget() in the function. pack_forget() will not delete your widget it will only hide it from the layout. To delete the widget you might have to use widget.destroy().
import tkinter
from tkinter import ttk
def modify_label_text(event):
newvalue = entry.get()
clickme.configure(text=newvalue)
entry.pack_forget()
clickme.focus()
def create_entry(event):
label = event.widget
entry.pack()
entry.focus()
root = tkinter.Tk()
newvalue = tkinter.StringVar()
clickme = ttk.Label(root, width=16)
clickme.pack()
clickme.bind("<Button-1>", create_entry)
clickme.focus()
entry = ttk.Entry(clickme, textvariable=newvalue)
entry.bind("<Return>", modify_label_text)
root.mainloop()
Edit(writing my comment as answer)
I suspect that it has to do something with the textvariable being set. Simply removing it or changing the newvalue to global scope seems to work. Also, since you don't seem to be using .set or .get methods you can simply remove it if you want.

How do I delete a Tkinter label using a button command?

I want my program to run in a way that once the user presses the Info button, a label called GameInfoLabel is displayed due to a command from the Info button. Within the same condition (if the Info button is pressed), I want to add a Back button that deletes/destroys the GameInfoLabel.
I have attempted to implement this in the code below, but I'm getting the message
NameError: name 'GameInfoLabel' is not defined.
from tkinter import *
root = Tk()
root.title("Game Menu")
root.geometry("1920x1080")
root.resizable(True, True)
def QuitGameInfo():
GameInfoLabel.destroy()
BackInfoButton['state'] = NORMAL
def GameInfo():
RulesNotepad = open("GameInfo.txt",'r')
Rules = RulesNotepad.read()
GameInfoLabel = Label(root, text = Rules, fg = "blue", bg = "red", height = "14", width = "140").pack()
BackInfoButton = Button(root, text = "Back", command = QuitGameInfo).pack()
RulesNotepad.close()
button3 = Button(root, text = "Info", command = GameInfo, width = "20", height = "3").pack()
root.mainloop()
The error is due to that GameInfoLabel is a local variable inside GameInfo() and it is not accessible inside QuitGameInfo().
You can fix this error by either declaring GameInfoLabel as global or pass it to QuitGameInfo() via argument. Same apply on BackInfoButton as well.
However you need to fix another issue: both GameInfoLabel and BackInfoButton are None because they are result of pack().
Below is the modified code using global solution:
from tkinter import *
root = Tk()
root.title("Game Menu")
root.geometry("1920x1080")
root.resizable(True, True)
def QuitGameInfo():
GameInfoLabel.destroy()
#BackInfoButton['state'] = NORMAL # why ??? Should it be destroyed as well?
BackInfoButton.destroy()
def GameInfo():
global GameInfoLabel, BackInfoButton
with open("GameInfo.txt",'r') as RulesNotepad:
Rules = RulesNotepad.read()
GameInfoLabel = Label(root, text = Rules, fg = "blue", bg = "red", height = "14", width = "140")
GameInfoLabel.pack()
BackInfoButton = Button(root, text = "Back", command = QuitGameInfo)
BackInfoButton.pack()
Button(root, text = "Info", command = GameInfo, width = "20", height = "3").pack()
root.mainloop()
However I would suggest to use a frame to hold the GameInfoLabel and BackInfoButton and the frame is hidden initially. When Info button is clicked, show the frame. When Back button is clicked, hide the frame.
from tkinter import *
root = Tk()
root.title("Game Menu")
root.geometry("1920x1080")
root.resizable(True, True)
def GameInfo():
with open("GameInfo.txt",'r') as RulesNotepad:
Rules = RulesNotepad.read()
GameInfoLabel.config(text=Rules)
info_frame.pack() # show the game info frame
Button(root, text="Info", command=GameInfo, width="20", height="3").pack()
# create the game info frame but don't show it initially
info_frame = Frame(root)
GameInfoLabel = Label(info_frame, fg="blue", bg="red", height="14", width="140")
GameInfoLabel.pack()
Button(info_frame, text="Back", command=info_frame.pack_forget).pack()
root.mainloop()
As mentioned in acw1668's comment GameInfoLabel is local to the GameInfo() method. This means once this method has finished running anything declared in it ceases to exist.
The usual solution to this is passing/returning variables to functions to get results for instance your game info could return the label, however since you want to call these functions automatically when an event occurs, e.g. your button is pressed, this is not so easy.
I believe the easiest solution to your problem would be to declare the GameInfoLabel variable globally (in the global scope), this is not always the best coding practice but I'm not certain of tkinter's ability to pass variables parameters to an event handler and this can be complicated.
Also as mentioned by acw1668 you call .pack() immediately on the new label which is returned from the initialization Label(...). Pack then does not return the label so we do that separately.
This should work, give it a careful read.
from tkinter import *
root = Tk()
root.title("Game Menu")
root.geometry("1920x1080")
root.resizable(True, True)
# Declare any global UI Components
GameInfoLabel = None # Dont set a Label yet
def QuitGameInfo():
GameInfoLabel.destroy()
BackInfoButton['state'] = NORMAL
def GameInfo():
RulesNotepad = open("GameInfo.txt",'r')
Rules = RulesNotepad.read()
GameInfoLabel = Label(root, text = Rules, fg = "blue", bg = "red", height = "14", width = "140")
GameInfoLabel.pack()
BackInfoButton = Button(root, text = "Back", command = QuitGameInfo).pack()
RulesNotepad.close()
button3 = Button(root, text = "Info", command = GameInfo, width = "20", height = "3")
button3.pack()
root.mainloop()

Adding elements using Tkinter Dynamically

I am trying to create the program that has an add button, When it is clicked, several different elements like entries and buttons should appear on the output window. Firstly I am not able to structure the display correctly and secondly I am not sure as to how to get the values entered by the user in entry widget of Tkinter.
Here is the Code:
from tkinter import *
from tkinter import messagebox
lb = Tk()
def addentry():
i = 3 // the 3 here should keep on incrementing so that the row goes on increasing as the user
keeps on adding different entries. This is for the display
ent1 = Entry(lb, bd=5).grid(row =i ,column= 0)
ent2 = Entry(lb, bd=5).grid(row = i, column=2)
ent3 = Entry(lb, bd=5).grid(row = i, column=4)
ent4 = Entry(lb, bd=5).grid(row = i , column=6)
addent = Button(lb, text = "Add Entry",command = addentry).grid(row = 0, column = 2)
It's all about keepin references. References are used to identify objects.
import tkinter as tk
root = tk.Tk()
my_entries = []
entry_row = 1
def addentry():
global entry_row
ent = tk.Entry(root, bd=5)
ent.grid(row =entry_row ,column= 0)
my_entries.append(ent)
entry_row = entry_row+1
def getter():
for entry in my_entries:
my_stuff = entry.get()
print(my_stuff)
addent = tk.Button(root, text = "Add Entry",command = addentry)
addent.grid(row = 0, column = 0)
getent = tk.Button(root,text='get input', command= getter)
getent.grid(row=0, column=1)
root.mainloop()
In this exampel we keepin the references of the tk.Entry and the variable entry_row while we would like to work with later on. There are a bunch of solution for this. Here we had used a global variable and a list in the global namespace to access them.

Python entry to store input into a variable stores nothing, returns initial value

Ok, so basic story. I have created an entry. After you introduce text, you have to click a button to store the inputted text into a variable that is later printed.
Here is the code:
from Tkinter import *
def myClick(entry_name, var):#defines function to get input from entry and store into var
var = entry_name.get()
root = Tk()#creates initial tk
lbl1 = Label(root, text = "hello")#before entry label
lbl1.grid(row = 0, column = 0)#label griding
ent = Entry(root, width = 15)# the entry
ent.grid(row = 1, column = 0)#entry gridding
hello = None #variable to store entry input
bt1 = Button(root, command = myClick(ent, hello))#button 1 creation and function attribution
bt1.grid(row = 3, column = 0)#button 1 griding
root.mainloop()
print(hello)
It is very unclear to me why the function does not get the input from the entry.
bt1 = Button(root, command = myClick(ent, hello))
In this line, you call myClick function with parameters, not just pass it. That means that myClick is executed once after the module is launched and then it does nothing. If you want to print the entry input, I recommend you do the following:
from tkinter import *
root = Tk()
lbl1 = Label(root, text="hello")
lbl1.grid(row=0, column=0)
ent = Entry(root, width=15)
ent.grid(row=1, column=0)
def myClick():
var = ent.get()
print(var)
bt1 = Button(root, command=myClick)
bt1.grid(row=3, column=0)
root.mainloop()
Also code after root.mainloop() doesn't excecute.
just define a normal function :
from tkinter import *
def blinta():
var = ent.get()
ent.delete(0,END)
print(var)
root = Tk()#creates initial tk
lbl1 = Label(root, text = "hello")#before entry label
lbl1.grid(row = 0, column = 0)#label griding
ent = Entry(root, width = 15)# the entry
ent.grid(row = 1, column = 0)#entry gridding
bt1 = Button(root, command = blinta)
bt1.grid(row = 3, column = 0)
root.mainloop()
This will work I'm sure.

Update label content on click using Python

I'm trying to update the content of a label, in Python, by clicking a button. For each clicks a counter will be raised and the value of the label will be updated by the current value of the counter (j). Here is the code:
import time
import random
import MySQLdb
from Tkinter import *
j=0
def PrintNumber():
global j
j+=1
print j
return
mgui=Tk()
mgui.geometry('200x200')
mgui.title('Queue System')
st = Button(mgui, text="Next Customer", command = PrintNumber)
st.pack()
f = PrintNumber()
label = Label(mgui, text=f)
label.pack()
mgui.mainloop()
Please be kind, i'm new in Python. :)
You can use a Tkinter variable class instance to hold a value. If you assign the textvariable option of the Label widget to the variable class instance, it will update automatically as the value of the instance changes. Here's an example:
from Tkinter import *
root = Tk()
var = IntVar() # instantiate the IntVar variable class
var.set(0) # set it to 0 as the initial value
# the button command is a lambda expression that calls the set method on the var,
# with the var value (var.get) increased by 1 as the argument
Button(root, text="Next Customer", command=lambda: var.set(var.get() + 1)).pack()
# the label's textvariable is set to the variable class instance
Label(root, textvariable=var).pack()
mainloop()
You can change the label text in the function that responds to the command (PrintNumber() in this case) using label.config(), e.g.:
from tkinter import *
def PrintNumber():
global j,label
j+=1
label.config(text=str(j))
return
j = 0
mgui=Tk()
mgui.geometry('200x200')
mgui.title('Queue System')
st = Button(mgui, text="Next Customer", command = PrintNumber)
st.pack()
label = Label(mgui, text=str(j))
label.pack()
mgui.mainloop()
Here is another way you could do it
import time
import random
import MySQLdb
from Tkinter import *
def PrintNumber(label):
PrintNumber.counter += 1 #simulates a static variable
print PrintNumber.counter
label.configure(text=str(PrintNumber.counter)) #you update label here
mgui=Tk()
mgui.geometry('200x200')
mgui.title('Queue System')
PrintNumber.counter = 0 #add an attribute to a function and use it as a static variable
label = Label(mgui) #create label
#pass the label as parameter to your function using lambda notation
st = Button(mgui, text="Next Customer", command=lambda label=label:PrintNumber(label))
st.pack()
label.pack()
mgui.mainloop()

Categories

Resources