How to update python gui? - python

I want to update my gui every second (i dont actually care about the time, but it should be like realtime). I got a script, where actually a Label as an int should increase by one and displayed. But i don't get the change, also i want to place the Label according to the width of the root, but it doesn't update. Only the update is a problem, maybe someone can help me with that. (Im a Beginner-Noob).
Script:
from tkinter import *
import time
c = 0
root = Tk()
root.title("Real Time Plot")
root.minsize(width = 200, height = 300)
m = root.winfo_reqwidth() / 2
root.update()
Text = Label(root, text = c)
Text.place(x =m, y = 150)
c = c + 1
print(m)
root.mainloop()

I've created a timer so I suppose you can do it like I did. Hope this works for you.
First, create a StringVar:
text = StringVar (value = "text")
Then create a Label with textvariable.
yourlabel = Label(root, textvariable = Text)
And then just make a function that will update the yourlabel:
yourlabel.set(and here you pass the new value)
So then your yourlabel will have the value that you ve passed. So then you can use something like self.after to update a func every 1000 ms.

You have to use a Python Threading, which will carry out this flawlessly!
Here is the code:
from tkinter import *
import threading
import time
def realtime_update():
while True:
global c, Text
c += 1
Text.configure(text=c+1)
time.sleep(0.001)
root_width = root.winfo_geometry()
root_width = root_width.split('x')
root_width = int(root_width[0])
Text.place(x=root_width/2, y=150)
time.sleep(0.01)
c = 0
root = Tk()
root.title("Real Time Plot")
root.minsize(width = 200, height = 300)
m = root.winfo_reqwidth() / 2
Text = Label(root, text = c)
Text.place(x=int(m), y = 150)
print(m)
threading.Thread(target=realtime_update, daemon=True).start()
root.mainloop()
It solves the following:
Realtime Update (precision to 0.01s)
Label changes position when root window resizes

You are updating just the variable value, not the value of the label.
You need to update the label with the content of c after increasing it:
Text.configure(text=c)
So it becomes something like that:
from tkinter import *
import time
c = 0
root = Tk()
root.title("Real Time Plot")
root.minsize(width = 200, height = 300)
m = root.winfo_reqwidth() / 2
root.update()
Text = Label(root, text = c)
Text.place(x =m, y = 150)
root.update()
time.sleep(2)
c = c + 1
Text.configure(text=c)
root.update()
print(m)
root.mainloop()
I did some minor update to your code, like adding a sleep time, to better show the behaviour.

Related

I want to a create a moving label

import tkinter as tk
from tkinter import *
import keyboard
import time
a = 120
root = tk.Tk()
root.state('zoomed')
root.configure(bg='white')
root.resizable(False, False)
a = 30
x = 0
def increase():
global a
a += 10
def ar():
for i in range(50):
labele1.place(x=120, y=a)
root.after(1000, increase)
c1 = Canvas(root, width=700, height=700, bg='gray95')
c1.place(x=450, y=60)
labele1 = tk.Label(c1, text='_______', font='Calibri 20')
startbutton = tk.Button(text='Başla', command=ar)
startbutton.pack()
root.mainloop()
I want to create a moving label which moves per second. Everything looks clear but it doesn't work well. I want to make a car race app but first the walls should move back and it exit the project
The idea to use root.after is correct, but the implementation is wrong. Just because you update the value of a inside a function, tkinter will not automatically update that value with its widget unless you manually ask it to. So what you can do is:
Make the label a canvas object (recommended since you will be making a game and canvas is closer to give you tools you need):
def ar():
global a
a += 10 # Increase the value of a
c1.coords('wall', [120, a]) # Change the coord of the tag 'wall'
root.after(25, ar) # Repeat this function every 25 ms
....
labele1 = tk.Label(c1, text='_______', font='Calibri 20')
c1.create_window(120, a, window=labele1, tags='wall') # Initial coords -> x=120, y=30
Change the location of the label using place_configure:
def ar():
global a
a += 10 # Increase the value of a
labele1.place_configure(y=a)
root.after(25, ar) # Repeat this function every 25 ms
....
labele1 = tk.Label(c1, text='_______', font='Calibri 20')
labele1.place(x=120, y=a)
Plus checking frame size and decreasing functions.
the main problem was a minor bug which you should change in line 37.
import tkinter as tk
from tkinter import *
import keyboard
import time
a = 120
root = tk.Tk()
root.state('zoomed')
root.configure(bg='white')
root.resizable(False, False)
a = 30
x = 0
moving_rate = 10
max_y = 600
min_y = 30
flag_mov_func= 1
def moving_func(): #increase or decrease function
global a
global flag_mov_func
if flag_mov_func :
a += moving_rate
if a + moving_rate == max_y: #simple logic bouncing if it ends
flag_mov_func=0
elif flag_mov_func==0 :
a -= moving_rate
if a - moving_rate == min_y:
flag_mov_func=1
def ar():
moving_func()
labele1.place(x=120, y=a)
root.after(1000, ar)
flag_is_called=1
def button1(): #new update on code to make the button work once.
global flag_is_called
if flag_is_called:
flag_is_called=0
ar()
c1 = Canvas(root, width=700, height=700, bg='gray95')
c1.place(x=450, y=60)
labele1 = tk.Label(c1, text='_______', font='Calibri 20')
startbutton = tk.Button(text='Başla', command=button1)
startbutton.pack()
root.mainloop()

Issue with progress bar thread

I created a small GUI using Tkinter. It has a button on click of which some data is written to Excel.
To show the progress, I added a progress bar but since the process is resource intensive, the progress bar appears only at the end. Therefore, I used threading as shown.
In the Main function below, I initialized the progress bar in a different thread but I want to update the current value of the task in Start function.
Because of this line:
progressbar.Start()
it is just continuously running without anything to do with the current progress.
def Start():
x = 0
progressbar["value"] = x
for idx, val in enumerate(rows):
region_url = val[1]
if (model_url != '-'):
url = 'http://testurl/' + region_url
x = x + 1
if (x > 4):
break
# Main
if __name__ == '__main__':
window = Tk()
new = progress(window)
# Add a grid
mainframe = Frame(window)
mainframe.grid(column=0,row=0, sticky=(N,W,E,S) )
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
mainframe.pack(pady = 100 , padx = 150)
# DropDown
popupMenu = OptionMenu(mainframe, tkvar, *regionList)
Label(mainframe, text="Region").grid(row = 1, column = 0)
# Button
btnSubmit = Button(mainframe, text= "Execute",command=StartScrap).grid(row = 2, column = 18)
popupMenu.grid(row = 2, column =0)
# Progress Bar
progressbar = ttk.Progressbar(window, orient = HORIZONTAL,length=300, mode = 'indeterminate')
progressbar.pack()
t = threading.Thread()
progressbar["maximum"] = 4
progressbar.start()
window.mainloop()
There are a couple things in your code that needs fixing.
Firstly you defined the function Start which controls how your progressbar is updated, but you never call it.
Secondly, you define the progressbar mode as indeterminate and that just start the progress bar - it works but it will just periodically move the progressbar.
Thirdly, you defined the Thread t but never put a target function.
Here's how to move your progressbar in a thread:
from tkinter import *
from tkinter import ttk
import threading
import time
def Start():
def update_pbar():
for i in range(5): #replace this with your method to update your progressbar
time.sleep(1)
progressbar["value"] = i
t = threading.Thread(target=update_pbar)
t.start()
# Main
if __name__ == '__main__':
window = Tk()
progressbar = ttk.Progressbar(window, orient = HORIZONTAL,length=300, mode = 'determinate')
progressbar.pack()
progressbar["maximum"] = 4
btnSubmit = Button(window, text="Execute", command=Start).pack()
window.mainloop()

How to move tkinter windows using python after it has been created?

I am looking to move a tkinter window to different x and y coordinates after it has been created. For example 5 seconds after the window has been created move it to
x=??? and y=???.
from tkinter import*
root = Tk()
root.title("lol")
root.geometry("300x300")
photo = PhotoImage(file="pepe.gif")
label = Label(image=photo).place(x=10, y=10)
root.mainloop()
The above code is just an example, how does it need to be modified to move by itself?
This example will show you how to reset the root geometry that controls the position of the window on screen; clicking on the image will toggle the locationof the window.
from tkinter import *
def move_me(idx=[0]): # <- creates a closure for the index of the location strings
loc = ["300x300+200+200", "300x300+300+300"]
root.geometry(loc[idx[0]]) # <-- reset the geometry
idx[0] = (idx[0]+1) % 2 # <-- toggles the index between 0 and 1
root = Tk()
root.title("lol")
root.geometry("300x300-100+100")
photo = PhotoImage(file="pepe.gif")
button = Button(root, image=photo, command=move_me)
button.place(x=10, y=10)
root.mainloop()
[edit] with auto repeat moving the window.
(attention, you have challenging game to catch the window to close it)
from tkinter import *
import random
def move_me():
x, y = str(random.randrange(800)), str(random.randrange(800))
loc = "300x300+" + x + '+' + y
root.geometry(loc)
root.after(500, move_me) # <-- auto call to move_me again every 1/2 second
root = Tk()
root.title("lol")
root.geometry("300x300+100+100")
photo = PhotoImage(file="pepe.gif")
label = Label(root, image=photo)
label.place(x=10, y=10)
move_me() # <-- call to move_me
root.mainloop()

Tkinter Label text is Variable

A hoy hoy, I would like to know how I can take a parameter in a function and make it a label and also then .grid_forget() label again (Answer is on a "Restart?" window). I'm making a currency converter from scratch and my code is terrible.
Take a look at one of my Tkinter programs. Look at where it says counter. That is the variable. The Tkinter website is also so helpful! Good luck!
from tkinter import *
import sys
root = Tk()
root.geometry("480x320")
root.title("School Days Left!")
global counter
counter = 30
def upClick():
global counter
counter += 1
def downClick():
global counter
counter -= 1
mButton1.config(text = counter, borderwidth = 0, highlightthickness=0, relief='ridge', pady = "100")
mButton1 = Button(text = counter, command = downClick, height = 4000, width = 320, font = ("Monospace", 200))
mButton1.pack()
root.mainloop()

Change position of label in Tkinter window

I am writing a simple program that pulls up an image (BackgroundFinal.png) and displays it in a window. I want to be able to press a button on the window to move the picture down by 22 pixels. Everything works except the button does not do anything.
import Tkinter
import Image, ImageTk
from Tkinter import Button
a = 0 #sets inital global 'a' and 'b' values
b = 0
def movedown(): #changes global 'b' value (adding 22)
globals()[b] = 22
return
def window(): #creates a window
window = Tkinter.Tk();
window.geometry('704x528+100+100');
image = Image.open('BackgroundFinal.png'); #gets image (also changes image size)
image = image.resize((704, 528));
imageFinal = ImageTk.PhotoImage(image);
label = Tkinter.Label(window, image = imageFinal); #creates label for image on window
label.pack();
label.place(x = a, y = b); #sets location of label/image using variables 'a' and 'b'
buttonup = Button(window, text = 'down', width = 5, command = movedown()); #creates button which is runs movedown()
buttonup.pack(side='bottom', padx = 5, pady = 5);
window.mainloop();
window()
If I am not mistaken, the button should change the global 'b' value, therefore changing the y position of the label. I really appreciate any help, sorry for my god-awful conventions. Thanks in advance!
You have a few problems here.
First, you're using pack and place. In general, you should only use 1 geometry manager within a container widget. I don't recommend using place. That's just too much work that you need to manage.
Second, you're calling the callback movedown when you construct your button. That's not what you want to do -- You want to pass the function, not the result of the function:
buttonup = Button(window, text = 'down', width = 5, command = movedown)
Third, globals returns a dictionary of the current namespace -- It's not likely to have an integer key in it. To get the reference to the object referenced by b, you'd need globals()["b"]. Even if it did, changing the value of b in the global namespace won't change the position of your label because the label has no way of knowing that change. And in general, if you need to use globals, you probably need to rethink your design.
Here's a simple example of how I would do it...
import Tkinter as tk
def window(root):
buf_frame = tk.Frame(root,height=0)
buf_frame.pack(side='top')
label = tk.Label(root,text="Hello World")
label.pack(side='top')
def movedown():
buf_frame.config(height=buf_frame['height']+22)
button = tk.Button(root,text='Push',command=movedown)
button.pack(side='top')
root = tk.Tk()
window(root)
root.mainloop()
Thanks for the reply but, It was not really what I was looking for. I'll post what I found worked best here for anybody else with the same problem.
Essentially, It is much better, in this case, to use a Canvas instead of a label. With canvases, you can move objects with canvas.move, here is a simple example program
# Python 2
from Tkinter import *
# For Python 3 use:
#from tkinter import *
root = Tk()
root.geometry('500x500+100+100')
image1 = PhotoImage(file = 'Image.gif')
canvas = Canvas(root, width = 500, height = 400, bg = 'white')
canvas.pack()
imageFinal = canvas.create_image(300, 300, image = image1)
def move():
canvas.move(imageFinal, 0, 22)
canvas.update()
button = Button(text = 'move', height = 3, width = 10, command = move)
button.pack(side = 'bottom', padx = 5, pady = 5)
root.mainloop()
my code may not be perfect (sorry!) but that is the basic idea. Hope I help anybody else with this problem

Categories