Python Tkinter label cause window to say not responding when i use it more than once in 5 seconds or so.
Here is my code i am calling it with the variable data which is just a basic string
def print_data(data):
L1 = Tkinter.Label(app, text="You: " + data)
L1.pack()
I solved the issue i was running the script externally to my main script. I was calling the print data script without calling mainloop(). Thanks everyone :)
Related
The code i tried to accomplish my result:
from tkinter import*
import time
root=Tk()
lyrics=StringVar()
lyrics.set("unleash")
l=Label(root,textvariable=lyrics)
l.pack()
def change_text():
lyrics.set("you!!")
print('ses')
time.sleep(6.9)
change_text()
mainloop()
The problems in this are like the window is displayed after 10 sec. If I shift the mainloop() before the time.sleep() function the time.sleep() executes after the app is closed. The reason is simple that I didn't use after() function because the after() function doesn't accepts the sec value in decimal.
Any help is appreciated
The after() function takes the delay argument in milliseconds, where you would pass 6900 instead of 6.9. See: https://www.tcl.tk/man/tcl8.4/TclCmd/after.html
The problem is that mainloop() blocks further execution. You can always use a background thread:
def bg_thread():
time.sleep(6.9)
change_text()
thread = threading.Thread(target=bg_thread)
thread.start()
mainloop()
Threading, of course, brings with it a whole host of challenges. It's a good idea to make sure you know what you're doing when working with threads.
See also:
https://docs.python.org/3/library/threading.html#threading.Thread
Tkinter understanding mainloop
When do I need to call mainloop in a Tkinter application?
import time
def update_label():
///update label text here
label.config(text="New label text")
/// wait for 5 seconds before updating the label
time.sleep(5)
update_label()
So, I was trying to remake "you are an idiot" virus in python. The way I'm doing this is looping my python script. I tried to make it so that when you try to close a window more popups show up.
It was working the 1st time but, then I started getting this error _tkinter.TclError: can't invoke "wm" command: application has been destroyed, and I can't find a way to fix it. Here is my code for how I'm getting this error.
Also another reason why I need it looped is because I'm using random functions to make the windows appear in random positions.
# On closing function:
def on_closing():
restart()
root.protocol("WM_DELETE_WINDOW", on_closing)
root.title("you are an idiot")
root.mainloop()
# Restart function:
def restart():
os.system("python3 main.py")
Random position functions:
#random values
x = random.randint(100,600)
y = random.randint(200,600)
root.geometry("+{}+{}".format(x,y)) #randomized window position
Your could use the event binding for the Destroy event.
root.bind("<Destroy>", on_closing)
Is the code you shown the main.py?
Currently I'm working on a project of mine involving sensors, and showing that sensory data on a display via TKinter. Everythings written in Python 3.7.3.
The issue im currently handling, is to update the label in the window, while the mainloop is running.
What i mean by this, is that if i execute the script, first the window options get defined, then the update function gets defined with a while true loop. Then its supposed to start the window. Now because of the while true loop it does not reach the window.mainloop() point (obviously, the while loop doesn't break...). My interest was peaked and i tried to put the window.mainloop() function inside the while loop of the update (please don't blame me, i know my script is a spaghetti mess.) I figured out that i could run the whole thing in threads, and so i decided to thread the whole window process, and add queues for the sensor data. Now the while loop was still in the way and didnt work properly, and after a bit of googling i found a code snippet that might help me. After trying to implement it in my script, i got an exception "function init expects 3 arguments, but 4 were given.." (code below) and I'm kinda running out of ideas on this.
Bear in mind that im not raelly a developer, i just need a script that can handle sensor data, dispaly it in a window, and export the current data to a database. So go easy on the blame please.
Current Script:
import time
import board
import adafruit_dht
import threading
import queue
from tkinter import *
dhtDevice = adafruit_dht.DHT22(board.D4, use_pulseio=False)
tempQ = queue.Queue(maxsize=0)
humQ = queue.Queue(maxsize=0)
class windowMain:
def __init__(self):
self.tempC_label = Label(fenster, text="Placeholder TempC")
self.humidity_label = Label(fenster, text="Placeholder Humidity")
self.tempC_label.pack()
self.humidity_label.pack()
self.tempC_label.after(2000, self.labelUpdate)
self.humidity_label.after(2000, self.labelUpdate)
def labelUpdate(self, tempQ, humQ):
self.tempC_label.configure(text= tempQ.get() + "°C")
#this is just to confirm if the function called or not, to see if the label updated or not.
#if the label didnt update, and the function called, there is something wrong with the function
#if the label didnt update, and the function didnt call, there is a problem somwhere else
print("Current Temp: " +tempQ.get() + "°C")
self.label.after(2000, self.labelUpdate)
if __name__ == "__main__":
windowName = Tk()
windowName.title = ("Climatemonitor")
windowMain(windowName)
windowName.mainloop()
try:
windowThread = threading.Thread(target=windowMain, args=(tempQ, humQ, ))
windowThread.start()
except:
print("Unable to start thread")
while True:
try:
temperature_c= dhtDevice.temperature
tempText= temperature_c
tempText= str(tempText)
tempQ.put(tempText)
humidity = dhtDevice.humidity
humidityP = str(humidity)
#this one is just to check if the sensor reads data
print(
"Temp: {:.1f} C Humidity: {}% ".format(
temperature_c, humidity
)
)
time.sleep(2.0)
except RuntimeError as error:
print(error.args[0])
time.sleep(2.0)
continue
except Exception as error:
dhtDevice.exit()
raise error
time.sleep(2.0)
The ultimate goal is to display my sensor data, with a 2 second refresh (the HZ rate of the Sensor), while the sensor continues to read every 2 seconds.
I'd also like to add that this is my first time using Python, since im, again, not really a developer yet.
Thanks a bunch in advance for every critique and help
most simple way of doing this would be using a button to execute a function and then including your while loop in that function,
Using an button gives you an point where you can start running while instead of directly starting it as soon as you run your program
Sample code should be something like this,
import tkinter as t
def execute():
print('hello')
window = t.Tk()
window.title("system")
window.geometry("550x250")
b1 = t.Button(window, text="Start", width=15, command=execute)
b1.grid(row=1, sticky="W", padx=4)
window.mainloop()
As there will be no user interaction, a button can invoked using button.invoke method such as following,
import tkinter as t
def execute():
print('hello')
window = t.Tk()
window.title("system")
window.geometry("550x250")
b1 = t.Button(window, text="Start", width=0, command=execute)
#b1.grid(row=1, sticky="W", padx=4)
b1.invoke()
window.mainloop()
here removing .grid() will cause the button to disapper but can affect your GUI while updating the label value later , also have a look at this ->
Is there a way to press a button without touching it on tkinter / python?
Python tkinter button.invoke method trouble
I am working on a large program that opens new windows from a desktop widget. The desktop widget has a 'ticker' style label that displays a piece of text representing an iteration through a list. My problem is when I first wrote the program I called mainloop() with each new window I opened. The result was the new window and program would run as designed, but the ticker would freeze. Even upon closing the newly created window, the ticker would not restart. So I removed the mainloop() line. The result of this is the ticker continues to run and I can work within the new window, but everything is soooo laggy. I suspect this has something to do with the after() method?
Attached is a test code that I am using to try to sort this out before applying the correct code to my program. And I'm sure you can tell by reading the code, but I am self taught and an absolute newb, so please dumb down the explanations if possible. Thank so much!
from tkinter import *
def new_window():
nw = Tk()
item = Text(nw)
item.grid()
L = [1, 2, 3, 4, 5]
root = Tk()
Button(root, text = 'Open', command = new_window).grid(row = 1)
while True:
for i in L:
num = Label(root, text = i)
num.grid(row = 0)
root.after(2500)
num.update()
root.mainloop()
A tkinter application should always have exactly one instance ofTk, and you should call mainloop exactly once. If you have more than one instance the program will not likely work the way you expect. It's possible to make it work, but unless you understand exactly what is happening under the hood you should stick to this rule of thumb.
If you need more windows, create instances of Toplevel. You should not call mainloop for each extra window.
Also, you shouldn't have an infinite loop where you call after the way that you do. mainloop is already an infinite loop, you don't need another. There are several examples on this website of using after to call a function at regular intervals without creating a separate loop.
I am making a simple program that also incorporates the use of TKinter. The inclusion is to have it copy and paste to my clipboard and also to check the contents of my keyboard. However, without much change from me, the console spits out an error :
can't invoke "event" command: application has been destroyed while executing
"event generate $w <<ThemeChanged>>" (procedure "ttk::ThemeChanged" line 6)
invoke from within "ttk::ThemeChanged"`
My questions:
I do not understand what the error means;
I do not understand how to fix it.
From my understanding, these error usually pop up from the use of matplotlib, which I am not using. The python console still can function after this message but it is annoying and distracting.
here is the code that i think is affecting it.
from Tkinter import Tk
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append(finalbib)
r.destroy()
#os.startfile("TEMPPY.py")
clipbardtest=True
while clipbardtest:
r=Tk()
clippytest = r.clipboard_get()
r.destroy()
if clippytest==finalbib:
os.system('cls')
print "Successfully copied to clipboard"
#os.remove("TEMPPY.py")
clipbardtest=False
morebibdef()
else:
time.sleep(1.2)
#os.startfile("TEMPPY.py")
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append(finalbib)
r.destroy()
See one of the comments from this question
If you use this in a console script this might lead to an error, that
the .destroy() function will not work ("can't invoke "event" command:
application has been destroyed while executing [...]"). To prevent
this, call r.update() before r.destroy.
The error means that all of the tkinter windows have been destroyed, but that something is trying to generate an event. In order to generate an event you must have a window.