I coded a python GUI program with tkinter that displays a label wherein its text changes every 0.25 seconds, according to the chronology of the list in the variable 'loadings'. I made it work by putting the function as a thread. Otherwise, it would not work. The code works perfectly as intended. However, every time i close the program, a RuntimeError appears and i do not know what the problem is. I searched on the internet for the error but none of what i have found are related to tkinter at all.
code:
from tkinter import *
import threading, time
root = Tk()
loading_label = Label(root)
loading_label.pack()
loadings = ['loading', 'loading.', 'loading..', 'loading...']
def loadingscreen():
while True:
for loading in loadings:
loading_label.config(text=loading)
time.sleep(0.25)
loadingthread = threading.Thread(target=loadingscreen)
loadingthread.start()
root.mainloop()
error:
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Users\HP\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:\Users\HP\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "C:/Users/HP/PycharmProjects/myfirstproject/threadingtest.py", line 14, in loadingscreen
loading_label.config(text=loading)
File "C:\Users\HP\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1637, in configure
return self._configure('configure', cnf, kw)
File "C:\Users\HP\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1627, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
RuntimeError: main thread is not in main loop
Process finished with exit code 0
The reason is that u have used the Threading in the Tkinter loop which I guess we shouldn't.
Safe play is to use after. so Custom label can help us in this case
from tkinter import *
import threading, time
import sys
root = Tk()
class Custom(Label):
def __init__(self,parent,lst):
super().__init__(parent)
self['text']=lst[0]
self.marker=0
self.lst=lst[:]
self.note=len(lst)
self.after(250,self.change)
def change(self):
if self.marker>=self.note:self.marker=0
self['text']=self.lst[self.marker]
self.marker+=1
self.after(250,self.change)
loadings = ['loading', 'loading.', 'loading..', 'loading...']
loading_label = Custom(root,loadings)
loading_label.pack()
# destroy it whenever u want
root.mainloop()
Related
My code stopped working quite literally overnight, due to an issue with Tkinter.
I'm using PySimpleGui for my project, which was working the previous day.
When I run my program it showed the bellow error:
File "E:/Projekty Python/dcs_assistant/gui_and_video.py", line 1, in <module>
import PySimpleGUI as sg
File "C:\Users\pawni\Miniconda3\envs\dcs_assistant\lib\site-packages\PySimpleGUI\__init__.py", line 2, in <module>
from .PySimpleGUI import *
File "C:\Users\pawni\Miniconda3\envs\dcs_assistant\lib\site-packages\PySimpleGUI\PySimpleGUI.py", line 125, in <module>
tclversion_detailed = tkinter.Tcl().eval('info patchlevel')
File "C:\Users\pawni\Miniconda3\envs\dcs_assistant\lib\tkinter\__init__.py", line 2354, in __getattr__
return getattr(self.tk, attr)
AttributeError: module '_tkinter' has no attribute 'eval'
Process finished with exit code 1
Line 125 is this:
tclversion_detailed = tkinter.Tcl().eval('info patchlevel')
This, as per Tkinter documentation, should simply return the version of Tkinter library (https://tkdocs.com/tutorial/install.html).
When I ran a dummy program using just Tkinter to test if Tkinter alone works. I got another error:
Traceback (most recent call last):
File "E:/Projekty Python/dcs_assistant/test.py", line 3, in <module>
tk = tkinter.Tk()
File "C:\Users\pawni\Miniconda3\envs\dcs_assistant\lib\tkinter\__init__.py", line 2272, in __init__
self._loadtk()
File "C:\Users\pawni\Miniconda3\envs\dcs_assistant\lib\tkinter\__init__.py", line 2286, in _loadtk
tk_version = self.tk.getvar('tk_version')
AttributeError: module '_tkinter' has no attribute 'getvar'
Process finished with exit code 1
The code for the dummy program was:
import tkinter
from tkinter.constants import *
tk = tkinter.Tk()
frame = tkinter.Frame(tk, relief=RIDGE, borderwidth=2)
frame.pack(fill=BOTH,expand=1)
label = tkinter.Label(frame, text="Hello, World")
label.pack(fill=X, expand=1)
button = tkinter.Button(frame, text="Exit", command=tk.destroy)
button.pack(side=BOTTOM)
tk.mainloop()
I tried to uninstall and re-install Tkinter again using both pip and conda. No joy.
I am trying to make a digital clock through python tkinter .My code is
import tkinter,time
def exiter():
root.destroy()
root=tkinter.Tk()
root.title("Digital Clock")
root.geometry("340x100")
root.resizable(False,False)
root.protocol("WM_DELETE_WINDOW",exiter)
def time_setter():
hr=tkinter.Label(root,font=('k',60,'bold'),text=time.strftime("%H:%M:%S"))
hr.grid(row=0,column=0)
while True:
root.update()
time_setter()
After I close the window I get an error
Traceback (most recent call last):
File "c:\Users\Tanmay Daga\OneDrive\Documents\Programming\Clock-Tkinter\digital_clock.py", line 20, in <module>
time_setter()
File "c:\Users\Tanmay Daga\OneDrive\Documents\Programming\Clock-Tkinter\digital_clock.py", line 13, in time_setter
hr=tkinter.Label(root,font=('k',60,'bold'),text=time.strftime("%H:%M:%S"))
File "C:\Program Files\Python39-32\lib\tkinter\__init__.py", line 3145, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "C:\Program Files\Python39-32\lib\tkinter\__init__.py", line 2569, in __init__
self.tk.call(
_tkinter.TclError: can't invoke "label" command: application has been destroyed
How do I break the loop when the window is closed.
How do I know when the window is closed
from tkinter import *
from time import strftime
def clock_tick():
string = strftime('%H:%M:%S %p')
lbl.config(text=string)#set the text
lbl.after(1000, time)#updater
root=Tk()
lbl = Label(root, font=('calibri', 40, 'bold'),
background='purple',
foreground='white')
lbl.pack(anchor = 'center')
clock_tick()
root.title("Digital Clock")
root.geometry("340x100")
root.resizable(False,False)
root.mainloop() #this is the loop you are looking for instead of the while loop
The loop is wrong. For tkinter there is a built in loop that is much better to use. Exiting this with the X will provide a clean exit if you set the loop up by using root.mainloop(). Here is a good example of what you are trying to do
https://www.geeksforgeeks.org/python-create-a-digital-clock-using-tkinter/
I'm creating a simple program that uses turtle in a tkinter canvas to allow the user to draw with the mouse. The drawing function seems to work fine however after you draw for a bit the program stops and calls a RecursionError.
from turtle import *
import tkinter as tk
box=tk.Tk()
canv=ScrolledCanvas(box)
canv.pack()
screen=TurtleScreen(canv)
p=RawTurtle(screen)
p.speed(0)
def draw(event):
p.goto(event.x-256,185-event.y) #The numbers are here because otherwise the turtle draws off center. Might be different depending on computer.
canv.bind('<B1-Motion>', draw)
box.mainloop()
This should in theory draw just fine but instead it is calling a RecursionError. I'm lost as to what I can do to prevent this other than maybe wrap the function in a try loop. Any help would be really appreciated.
The output in the Python Shell:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files (x86)\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
File "C:\Users\Charlie\Desktop\demo.py", line 17, in draw
p.speed(0)
File "C:\Program Files (x86)\Python36-32\lib\turtle.py", line 2174, in speed
self.pen(speed=speed)
File "C:\Program Files (x86)\Python36-32\lib\turtle.py", line 2459, in pen
self._update()
File "C:\Program Files (x86)\Python36-32\lib\turtle.py", line 2660, in _update
self._update_data()
File "C:\Program Files (x86)\Python36-32\lib\turtle.py", line 2651, in _update_data
self._pencolor, self._pensize)
File "C:\Program Files (x86)\Python36-32\lib\turtle.py", line 545, in _drawline
self.cv.coords(lineitem, *cl)
File "<string>", line 1, in coords
RecursionError: maximum recursion depth exceeded while calling a Python object
I've spent a good deal of time looking around for an answer and as far as I can tell there isn't one anywhere easy to find. This is my first question on this site so please forgive me if something I did was wrong.
I was not able to reproduce your recursion error but I have seen it before. Usually in situations where there are new events coming in while the event handler is busy handling an event. (Which is why it looks like recursion.) The usual fix is to turn off the event handler inside the event handler. Give this a try to see if it works any better for you:
from turtle import RawTurtle, ScrolledCanvas, TurtleScreen
import tkinter as tk
box = tk.Tk()
canv = ScrolledCanvas(box)
canv.pack()
screen = TurtleScreen(canv)
p = RawTurtle(screen)
p.speed('fastest')
def draw(x, y):
p.ondrag(None)
p.setheading(p.towards(x, y))
p.goto(x, y)
p.ondrag(draw)
p.ondrag(draw)
box.mainloop()
Here is my code:
import threading
import tkinter.simpledialog
def showDialog(evt):
dlg = tkinter.simpledialog.SimpleDialog(root,text='Test!', buttons=['OK'])
dlg.go()
def test():
threading.Thread(target=root.event_generate, args=('<<showDialog>>',)).start()
root = tkinter.Tk()
root.bind('<<showDialog>>',showDialog)
tkinter.Button(text = 'showDialog',command = test).pack()
root.mainloop()
I run this code with Python3.4
The First time I click showDialog Button it work perfectly
but if I press OK and click the button again,it raise a RuntimeError:
Exception in thread Thread-2:
Traceback (most recent call last):
File "D:\Program Files\Python34\lib\threading.py", line 921, in _bootstrap_inner
self.run()
File "D:\Program Files\Python34\lib\threading.py", line 869, in run
self._target(*self._args, **self._kwargs)
File "D:\Program Files\Python34\lib\tkinter\__init__.py", line 1501, in event_generate
self.tk.call(args)
RuntimeError: main thread is not in main loop
I'm learning python recently,this code is just a demo.I want to do some work after press the button in sub-thread,because it will cost a few second and I don't want to stuck the UI. When the work is done,it will show a dialog.?
Can someone please tell me how can I do this using tkinter and why this problem occur?
Thanks!And sorry for my poor English.
Mixing threads with GUIs, and in particular tk, is tricky. I do not know all the rules, but unpredictable exceptions and deadlocks are two of the problems. I am a bit surprised that generating an event in a separate thread from the main thread and mainloop worked even once. (Why are you trying that?) A simplified function that run in the same thread does work consistently.
def test():
root.event_generate('<<showDialog>>')
We implemented a distributed chat, which is using a Tkinter GUI. As I updated my system to Fedora18 Im getting exceptions when calling a Tkinter event, almost the same as described here:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib64/python2.7/threading.py", line 551, in bootstrap_inner self.run()
File "/usr/lib64/python2.7/threading.py", line 504, in run self.target(*self.__args, **self.__kwargs)
File "/hachat/peer.py", line 156, in startRecvLoop
self.processMessage(msg, addr)
File "/hachat/peer.py", line 222, in processMessage
self.gui.receive(msg)
File "/hachat/gui.py", line 74, in receive
self.textfenster.insert(END,msg.name+": "+msg.text+'\n')
File "/usr/lib64/python2.7/lib-tk/Tkinter.py", line 2986, in insert
self.tk.call((self._w, 'insert', index, chars) + args)
TclError: out of stack space (infinite loop?)
Here is a snipped out of the gui-class:
import Tkinter
import ScrolledText
import tkMessageBox
import tkSimpleDialog
import threading
class gui(object):
def __init__(self, parent):
self.root = Tkinter.Tk()
self.textfenster = ScrolledText.ScrolledText(self.fpopup,width=90,height=24,background='white')
self.textfenster.pack(fill=Tkinter.BOTH, expand=Tkinter.YES)
def run(self):
self.guiRunThread = threading.Thread(target=self.root.mainloop())
self.guiRunThread.daemon = True
self.guiRunThread.start()
def receive(self,msg):
self.textfenster.insert(Tkinter.END,msg.name+": "+msg.text+'\n')
self.textfenster.see(Tkinter.END)
The Exception appears only on my system, the reason seems to be that tk was not compiled with support for threads. I have to get rid of this Exeption - as the program is distributed it needs to run on different systems. So Im asking for how to get rid of this exception as well as an hint to get tk for supporting threads.
Im using Python version is 2.7.3, Tcl/Tk version 8.5. import Tkinter; Tkinter.Tk().tk.eval("puts $tcl_platform(threaded)") is giving back a Exception as well.
I solved the problem with Queues to communicate with Tk. See Mutli-threading python with Tkinter for an example!
This one works:
from Tkinter import *
from ScrolledText import ScrolledText
from threading import Thread
scrolled = None
def start():
global scrolled
root = Tk()
scrolled = ScrolledText(root)
scrolled.pack(fill=BOTH, expand=YES)
return root
Thread(target=start().mainloop).start()
print scrolled.get(0.0, END)