Tkinter Button not changing from entry - python

Just messing around with tkinter for the first time and I dont know why my buttons are not working. Basically the input_grade is supposed to get a value from entry_for_grades which is quiz_amount and just print it on the same window but I keep getting back 0
I looked up and thought I was suppose to use lambda but it keeps giving me 0 regardless of what I have in entry and press ok
from tkinter import *
quiz_amount = IntVar()
def quiz():
quiz_window = Tk()
window(quiz_window)
quiz_window.title('Quiz Grades')
width = quiz_window.winfo_width()
height= quiz_window.winfo_height()
quiz_window.geometry('{}x{}'.format(width, height))
entry_for_grades = Entry(quiz_window, textvariable=quiz_amount)
entry_for_grades.pack()
grade_amount = Button(quiz_window,text='Ok',command=lambda:see_text(quiz_window)).place(x=85,y=60)
def see_text(window):
Label(window,text=float(quiz_amount.get())).place(x=85,y=90)

I used your code and made it a Minimal, Reproducible Example (I think) and it works fine for me.
Here is the code:
from tkinter import *
def quiz(quiz_window):
# window(quiz_window)
quiz_window.title('Quiz Grades')
width = quiz_window.winfo_reqwidth()
height= quiz_window.winfo_reqheight()
quiz_window.geometry('{}x{}'.format(width, height))
entry_for_grades = Entry(quiz_window, textvariable=quiz_amount)
entry_for_grades.pack()
grade_amount = Button(quiz_window,text='Ok',command=lambda:see_text(quiz_window)).place(x=85,y=60)
def see_text(window):
Label(window,text=float(quiz_amount.get())).place(x=85,y=90)
if __name__ == '__main__':
quiz_window = Tk()
quiz_amount = IntVar()
quiz(quiz_window)
quiz_window.mainloop()
The only problem I can think of is, like Novel said, you are using more than one Tk() window and trying to pass variables between these windows.
You should almost never use more than one Tk() window since you cannot pass information between two Tk() windows. Instead use TopLevel() windows, information can flow freely between Tk() and TopLevel() windows.

Related

How to update tkinter label text in real time

I have an application that gets the css3 colour of the pixel your cursor is on, and I would like to use tkinter to display the text in a little window. I following is the tkinter part of my code:
import pyautogui, PIL
import tkinter as tk
def cursorpixel():
x,y = pyautogui.position()
pixel = (x,y,x+1,y+1)
return pixel
def grabColor(square, max_colors=256):
img=PIL.ImageGrab.grab(square)
color = img.getcolors(max_colors)
return color
def main():
root=tk.Tk()
root.minsize(150, 50)
color = tk.Label(root,
text= grabColor(cursorpixel()),
fg = "black",
font = "Arial").pack()
root.mainloop()
while __name__ == "__main__":
main()
This works as I want, without the function of updating the label text whenever my cursor moves across the screen. It works once when launching the application and the label text stays the same. How would I make it so the label text updates whenever my cursor moves? I am using python 3.7
Thank you
Assigning a variable to the text argument doesn't help, because even if the value of the variable changes, it will not be reflected in the label. Here is my approach to this (this is just one out of many possible ways)
import pyautogui, PIL
import tkinter as tk
from threading import Thread
def cursorpixel():
x,y = pyautogui.position()
pixel = (x,y,x+1,y+1)
grabColor(pixel)
def grabColor(square, max_colors=256):
global color_label,root
img=PIL.ImageGrab.grab(square)
color = img.getcolors(max_colors)
color_label.config(text=color)
def refresh():
while True:
cursorpixel()
def main():
global color_label,root
root=tk.Tk()
root.minsize(150, 50)
color_label = tk.Label(root,
fg = "black",
font = "Arial")
color_label.pack()
Thread(target=refresh).start()
root.mainloop()
if __name__ == "__main__":
main()
NOTES
I have used multi threading instead and created a function refresh() which triggers the cursorpixel() in an infinite loop.
I have called the grabColor() function from cursorpixel() having pixel as parameter.
I have used the color_label.config() method to change the text in the label, you could also use color_label['text'] or maybe assign a textvariable var = StringVar() to the label and then use var.set() on it.
I am not sure if it is a good choice to put the __name__='__main__' in a while loop as you will not be able to close the window without terminating the task, new one will pop up every time you try to do so.
Answer
I added the .after command into the grabColor() function and combined the cursorpixel and grabColor() functions. I used .config to update the color. Here is the code:
import pyautogui, PIL
from tkinter import *
root=Tk()
root.minsize(150, 50)
colortext = Label(root)
colortext.pack()
def grabColor():
x,y = pyautogui.position()
pixel = (x,y,x+1,y+1)
img=PIL.ImageGrab.grab(bbox=pixel)
color = img.getcolors()
colortext.config(text=str(color))
root.after(100, grabColor)
grabColor()
root.mainloop()
Sources / Additional Resources
How do I create an automatically updating GUI using Tkinter?
You can use after() to grab the color periodically:
import tkinter as tk
from PIL import ImageGrab
def grab_color(label):
x, y = label.winfo_pointerxy()
color = ImageGrab.grab((x, y, x+1, y+1)).getpixel((0, 0))
label.config(text=str(color))
label.after(100, grab_color, label)
def main():
root = tk.Tk()
color_label = tk.Label(root, width=20)
color_label.pack(padx=10, pady=10)
grab_color(color_label)
root.mainloop()
if __name__ == "__main__":
main()
Note that winfo_pointerxy() is used instead of pyautogui.position() to reduce dependency on external module.

Fast changing labels in Tkinter?

I would like to display some numbers, as fast as possible in Tkinter. The Program, I am trying to do, gets many numbers send and should show those.
Here is an similar environment, where tinter has to change a label very quickly.
from tkinter import *
import time
window = Tk()
lbl13 = Label(window, text="-")
lbl13.grid(column=0, row=0)
x = 0
while 1:
lbl13.config(text = str(x))
time.sleep(2)
x +=1
window.mainloop()
The Tkinter window doesn't even open on my computer. Is that because i have too weak hardware? What could I change that this Program also runs on my Computer. Thank you for every answer!
The infinite while loop will keep the program from getting to the line where you call window.mainloop(). You should call window.update() repeatedly instead of window.mainloop() at the end:
from tkinter import *
import time
window = Tk()
lbl13 = Label(window, text="-")
lbl13.grid(column=0, row=0)
x = 0
while 1:
lbl13.config(text = str(x))
window.update()
x +=1
Using after and a proper mainloop is probably a more more flexible way to achieve what you want; it is also reusable in different contexts, and can be used in an application that does more than trivially increment a number on a label:
maybe something like this:
import tkinter as tk
if __name__ == '__main__':
def increment():
var.set(var.get() + 1)
label.after(1, increment)
window = tk.Tk()
var = tk.IntVar(0)
label = tk.Label(window, textvariable=var)
label.pack()
increment()
window.mainloop()

Problem with calling functions with tkinter

from tkinter import *
from random import *
root = Tk()
#A function to create the turn for the current player. The current player isnt in this code as it is not important
def turn():
window = Tk()
dice = Button(window, text="Roll the dice!", bg= "white", command=lambda:diceAction(window))
dice.pack()
window.mainloop()
#a function to simulate a dice. It kills the function turn.
def diceAction(window):
result = Tk()
y = randint(1, 6)
quitButton = Button(result, text="Ok!", bg="white", command=result.destroy)
quitButton.pack()
window.destroy()
result.mainloop()
#A function to create the playing field and to start the game
def main():
label1 = Button(root, text="hi", bg="black")
label1.pack()
while 1:
turn()
print("Hi")
turn()
main()
root.mainloop()
My problem is that the code in the while function after the first turn() the code isnt executed until i close the root window(which i dont want because it represents the playing field). You can copy this code and execute it yourself if you want.
I have no idea what causes this and havent found anything online. Sorry for the long code but i wrote it so that it is executeable.
I don't know why this particular problem is occurring, but there are a couple of things in your code that are considered bad practice.
Instead of creating multiple instances of Tk(), you should use Toplevel widgets for any pop-up windows needed. Also, it's better to use root.mainloop() to run the program rather than a while loop.
I've made some edits to your code so that it uses a Toplevel widget and discards of the while loop.
from tkinter import *
from random import *
#A function to create the turn for the current player. The current player isnt in this code as it is not important
def turn(prev=None):
# destroy the previous turn
if prev:
prev.destroy()
# pop up with dice
window = Toplevel()
dice = Button(window, text="Roll the dice!", bg= "white")
dice.config(command=lambda b=dice, w=window:diceAction(b, w))
dice.pack()
#a function to simulate a dice, reconfigures the pop-up
def diceAction(button, window):
# roll dice
y = randint(1, 6)
# use dice result here?
print(y)
# reconfigure button, the command now starts a new turn
button.config(text='ok', command=lambda w=window:turn(prev=w))
root = Tk()
# I hijacked this button to use as a start button
label1 = Button(root, text="hi", bg="black", command=turn)
label1.pack()
root.mainloop()
I don't know if this is what you need, but it functions as the code in the question would if it worked.
Sorry I couldn't help with the cause of the error.

Issue with Combobox

excuse the greeness. Trying to build GUI where option selected from Combobox populates text box. Nothing happening. First time programming so appreciate i have made a lot of errors here.
import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext
# function to display course selected
def courseDisplay():
box = course.get()
print(box)
# Create instance
win = tk.Tk()
win.resizable(130,130)
win.title("RaceCourse GUI")
# create combobox
course = tk.StringVar()
courseChosen = ttk.Combobox(win,width=60,textvariable=course,state='readonly')
courseChosen['values'] = ("Choose a course","Ascot", "Bath", "Chester")
courseChosen.grid(column=5, row=1,rowspan = 3, columnspan = 3,padx = 300, pady = 40)
courseChosen.current(0)
courseChosen.bind("<<ComboboxSelected>>", courseDisplay)
# create scrolled Text control
scrolW = 46
scrolH = 10
box = scrolledtext.ScrolledText(win, width=scrolW, height=scrolH, wrap=tk.WORD)
box.grid(column=5, row=8, columnspan=3,padx = 300,pady = 10)
# Start GUI
win.mainloop()
Since function courseDisplay is called when some event occurs on combobox (namely, when some option is selected), it should accept one variable (usually called event). So, your function should look like this:
def courseDisplay(event=None):
box = course.get()
print(box)
Of course, You should add another logic for showing test in textbox instead of print.

Button Command with class in Python

I'm trying to get this right but so far no luck. Would appreciate it if someone can help me with it.
import tkinter
class MyGUI:
def __init__(self):
self.main_window = tkinter.Tk()
self.button1 = tkinter.Button(self.main_window,text='Average',command=self.average)
self.button1.pack()
tkinter.mainloop()
def average(self):
self.mini_window = tkinter.Tk()
self.avg_mess = tkinter.Label(self.mini_window,text='Results:')
self.avg_result_var = tkinter.StringVar()
self.avg_result_display = tkinter.Label(self.mini_window,textvariable=self.avg_result_var)
self.avg_mess.pack()
self.avg_result_display.pack()
self.button2 = tkinter.Button(self.mini_window,text='Calculate',command=self.avg_calc)
self.button2.pack()
def avg_calc(self):
self.avg_result = (100+300+80)/3
self.avg_result_var.set(self.avg_result)
gui = MyGUI()
The problem occurs when the Calculate button is clicked but the avg_result_var does not change its value. And hence the avg.result_display remains blank. I suspect there is something wrong with the function call when the button is pressed. I'm using Python 3.x. Thanks.
You're almost doing it correctly, but there are a couple of problems
First, the result never changes because you use the same numbers each time you do a calculation. The result is always the same so it appears that it is not changing.
The second problem is that you're creating two instances of Tk. Tkinter isn't designed to work like that, and it causes problems such as the one you are observing. If you need additional pop-up windows, use Toplevel rather than Tk.
Here's a modified version of your program, though I've added a random number in the computation so you can see it change each time.
import Tkinter as tkinter
import random
class MyGUI:
def __init__(self):
self.main_window = tkinter.Tk()
self.button1 = tkinter.Button(self.main_window,text='Average',command=self.average)
self.button1.pack()
tkinter.mainloop()
def average(self):
self.mini_window = tkinter.Toplevel()
self.avg_mess = tkinter.Label(self.mini_window,text='Results:')
self.avg_result_var = tkinter.StringVar()
self.avg_result_display = tkinter.Label(self.mini_window,textvariable=self.avg_result_var)
self.avg_mess.pack(fill="both")
self.avg_result_display.pack()
self.button2 = tkinter.Button(self.mini_window,text='Calculate',command=self.avg_calc)
self.button2.pack()
def avg_calc(self):
x = random.randint(100,200)
self.avg_result = (100+300+x)/3
print "result:", self.avg_result
self.avg_result_var.set(self.avg_result)
gui = MyGUI()

Categories