NameError: name 'Ptime' is not defined using tkinter scale scroller - python-3.x

I'm trying to create a function to modify the timecode shift of a script for instant replay, but when I create the function including the variable mentioned by Tkinter, I'm getting a name not defined error. I used a software called "PAGE" to create the GUI so I really have a very basic knowledge of tkinter. I'm not quite sure what code I need to include so I'm just going to paste all of the function definition and the entire support script generated by PAGE
I moved all of my function definitions into the support script but to no avail
def set_Tk_var():
global Ptime
Ptime = tk.DoubleVar()
global Pspeed
Pspeed = tk.StringVar()
text = "play: timecode: 00:00:0" + str(Ptime) + ";00 \\nc"
def IRplay():
print('testguiPAGE_support.IRplay')
session.write(b"stop\n")
session.write( text.encode() )
sys.stdout.flush()
in the main script the only place it's being referred to is:
def vp_start_gui():
global val, w, root
root = tk.Tk()
testguiPAGE_support.set_Tk_var()
top = Toplevel1 (root)
testguiPAGE_support.init(root, top)
root.mainloop()
w = None
def create_Toplevel1(root, *args, **kwargs):
global w, w_win, rt
rt = root
w = tk.Toplevel (root)
testguiPAGE_support.set_Tk_var()
top = Toplevel1 (w)
testguiPAGE_support.init(w, top, *args, **kwargs)
return (w, top)
getting error
Traceback (most recent call last):
File "C:\Users\InstSmart\Desktop\Rplay\Outputs\testguiPAGE.py", line 23, in <module>
import testguiPAGE_support
File "C:\Users\InstSmart\Desktop\Rplay\Outputs\testguiPAGE_support.py", line 40, in <module>
text = "play: timecode: 00:00:0" + str(Ptime) + ";00 \\nc"
NameError: name 'Ptime' is not defined
if there is anymore info you need, comment it, and I will add to the question

Related

TkCalendar: Trying to display multiple DateEntries on screen simultaneously leads to TclError

I am currently working on a school project that records employee information for a company and generates a rota based on factors such as employee availability, job role, etc.
In order to record employee holidays, I am using the module TkCalendar, which has its own Calendar and DateEntry objects which can be used to display GUI calendar information. However, I have recently changed computer and a segment of code which was used to allow users to add in holidays does no longer work; it appears that, when trying to create the second DateEntry object, TkCalendar raises an error which seems to imply that the options I have passed into the second object are invalid. This is confusing, as the first DateEntry object seems to be generated fine. Below is a test case example of the issue I am having:
from tkinter import *
from tkcalendar import DateEntry
class TestApp:
def __init__(self, root):
self.root = root
self.window = Frame(self.root)
self.window.pack()
self.label, self.calendar = [], []
self.font = ('Impact Bold', 13, 'bold')
labels = ['Select start date:', 'Select end date:']
for i in range(2):
self.label.append(Label(self.window, text=labels[i], font=self.font))
self.label[-1].grid(row=i+1, column=0)
self.calendar.append(DateEntry(self.window, font=self.font, locale='en_GB', width=15))
self.calendar[-1].grid(row=i+1, column=3)
if __name__ == '__main__':
root = Tk()
app = TestApp(root)
root.mainloop()
This generates the following exceptions:
Traceback (most recent call last):
File "C:\Users\xav\Documents\Python files\TkCalendar DateEntry test case.py", line 24, in <module>
app = TestApp(root)
File "C:\Users\xav\Documents\Python files\TkCalendar DateEntry test case.py", line 18, in __init__
self.calendar.append(DateEntry(self.window, font=self.font, locale='en_GB', width=15))
File "C:\Users\xav\AppData\Local\Programs\Python\Python38\lib\site-packages\tkcalendar\dateentry.py", line 105, in __init__
self._setup_style()
File "C:\Users\xav\AppData\Local\Programs\Python\Python38\lib\site-packages\tkcalendar\dateentry.py", line 160, in _setup_style
self.style.map('DateEntry', **maps)
File "C:\Users\xav\AppData\Local\Programs\Python\Python38\lib\tkinter\ttk.py", line 403, in map
self.tk.call(self._name, "map", style, *_format_mapdict(kw)),
_tkinter.TclError: Invalid state name r
The TkCalendar documentation can be found here. Thanks for any help in advance!
This issue have been reported in tkcalendar https://github.com/j4321/tkcalendar/issues/61 and seems to come from a change in python https://bugs.python.org/issue38661. As far as I know it happens only in Windows (I use tkcalendar with python 3.8 in linux without issues). The issue is that the style map returned by self.style.map('TCombobox') is not a valid style map, while it used to be and should be according to the ttk.Style.map() docstring.
Below is a temporary fix while waiting for a solution for the python issue. The idea is to override the method of the DateEntry which triggers the error and manually provide the correct style map to the DateEntry (see code below).
from tkcalendar import DateEntry as TkcDateEntry
import tkinter as tk
class DateEntry(TkcDateEntry):
def _setup_style(self, event=None):
# override problematic method to implement fix
self.style.layout('DateEntry', self.style.layout('TCombobox'))
self.update_idletasks()
conf = self.style.configure('TCombobox')
if conf:
self.style.configure('DateEntry', **conf)
# The issue comes from the line below:
maps = self.style.map('TCombobox')
if maps:
try:
self.style.map('DateEntry', **maps)
except tk.TclError:
# temporary fix to issue #61: manually insert correct map
maps = {'focusfill': [('readonly', 'focus', 'SystemHighlight')],
'foreground': [('disabled', 'SystemGrayText'),
('readonly', 'focus', 'SystemHighlightText')],
'selectforeground': [('!focus', 'SystemWindowText')],
'selectbackground': [('!focus', 'SystemWindow')]}
self.style.map('DateEntry', **maps)
try:
self.after_cancel(self._determine_downarrow_name_after_id)
except ValueError:
# nothing to cancel
pass
self._determine_downarrow_name_after_id = self.after(10, self._determine_downarrow_name)

Animating a gif W/O using PIL

I am currently trying to make life easier by having the code pull all the frames into my code and execute the animation. My current code is:
import time
from tkinter import *
import os
root = Tk()
imagelist = []
for file in os.listdir("MY-DIRECTORY"):
if file.endswith(".gif"):
imagelist.append(PhotoImage(file=str(os.path.join("MY-DIRECTORY", file))))
# extract width and height info
photo = PhotoImage(file=imagelist[0])
width = photo.width()
height = photo.height()
canvas = Canvas(width=width, height=height)
canvas.pack()
# create a list of image objects
giflist = []
for imagefile in imagelist:
photo = PhotoImage(file=imagefile)
giflist.append(photo)
# loop through the gif image objects for a while
for k in range(0, 1000):
for gif in giflist:
canvas.create_image(width / 2.0, height / 2.0, image=gif)
canvas.update()
time.sleep(0.1)
root.mainloop()
When I try to execute the file it gives me this error which I cannot make sense of.
Traceback (most recent call last):
File "C:/Users/Profile/Desktop/folder (2.22.2019)/animation2.py", line 21, in <module>
photo = PhotoImage(file=imagelist[0])
File "C:\Users\Profile\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 3545, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "C:\Users\Profile\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 3501, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't open "pyimage1": no such file or directory
Note: I am adapting this code to fit my needs I did not write it.
I ran some print statements to verify the pyimage was being uploaded to the array but I cannot figure out why its saying there is no such file or directory if its already uploaded to the array. Can you all please shine some light.
I found that I was creating an unnecessary array of objects lower in the code. giflist[]. I ultimately resolved the issue by removing it and having the loop use the array that was created earlier in the code imagelist. The following code works now.
import time
from tkinter import *
import os
root = Tk()
imagelist = []
for file in os.listdir("My-Directory"):
if file.endswith(".gif"):
imagelist.append(PhotoImage(file=str(os.path.join("My-Directory", file))))
# Extract width and height info
photo = PhotoImage(file="My-Directory")
width = photo.width()
height = photo.height()
canvas = Canvas(width=width, height=height)
canvas.pack()
# Loop through the gif image objects for a while
for k in range(0, len(imagelist)):
for gif in imagelist:
canvas.create_image(width / 2.0, height / 2.0, image=gif)
canvas.update()
time.sleep(0.1)
root.mainloop()

_tkinter.TclError: image "\full\directory\link.gif" doesn't exist

I'm sorry to be a pain, and I know that there are god knows how many other questions referring to this 'image doesn't exist' tkinter error, however, none of the ones that I have found appear to have an issue with the entire directory, they all seem to just be referring to the file name only.
So, I'm trying to make a Logo Quiz, (I have removed some irrelevant code from the example because otherwise it will be too long to place here..)
However, when I try to show the logo, it tells me that the image doesn't exist.
Showing me an issue with the entire directory link, of which if I copy directly from the error and place into Windows Explorer, opens the image perfectly fine.
Here's the code:
from tkinter import *
import tkinter.messagebox
import random
from PIL import Image, ImageTk
import os
class Window(Frame):
global questionstart
def questionstart():
if gameplayvar == 0:
chosenlinknumber = random.randint(0, len(templist)-1)
chosen = templist[chosenlinknumber]
temp = chosen.split("\\")
temp2 = temp[2].split(".")
temp3 = temp2[0].split("L")
global directory
quizlogo_label = Label(root, image = directory)
quizlogo_label.grid(row=1, column=2)
root = Tk()
root.geometry("900x590")
root.iconbitmap(r'\\replacing\the\server\directory\Documents\pythontests\Logos\logoquizlogo_YVp_icon.ico')
C = Canvas(root, bg="blue", height=500, width=500)
possiblelinks = [
'\\NewLogos\AdobeLogo.gif',
'\\NewLogos\AmazonLogo.gif',
'\\NewLogos\AppleLogo.gif',
'\\NewLogos\BMWLogo.gif',
'\\NewLogos\ChromeLogo.gif',
'\\NewLogos\DebianLogo.gif',
'\\NewLogos\DiscordLogo.gif',
'\\NewLogos\FirefoxLogo.gif',
'\\NewLogos\GoogleLogo.gif',
'\\NewLogos\MicrosoftLogo.gif',
'\\NewLogos\OperaLogo.gif',
'\\NewLogos\PhotoshopLogo.gif',
'\\NewLogos\PlayStationLogo.gif',
'\\NewLogos\PythonLogo.gif',
'\\NewLogos\TwitterLogo.gif',
'\\NewLogos\VisualStudioCodeLogo.gif',
'\\NewLogos\WindowsLogo.gif'
]
templist = possiblelinks
chosenlinknumber = random.randint(0, len(templist)-1)
chosen = templist[chosenlinknumber]
p1 = '\\replacing\the\server\directory\Documents\pythontests'
directory = p1+chosen
app = Window(root)
root.mainloop()
And this is what is returned when I run it:
"C:\Program Files (x86)\Python36-32\python.exe" "//replacing/the/server/directory/Documents/pythontests/tkinterimagetry1.py"
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 "//replacing/the/server/directory/Documents/pythontests/tkinterimagetry1.py", line 143, in quizstart
questionstart()
File "//replacing/the/server/directory/Documents/pythontests/tkinterimagetry1.py", line 121, in questionstart
quizlogo_label = Label(root, image = directory)
File "C:\Program Files (x86)\Python36-32\lib\tkinter\__init__.py", line 2760, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "C:\Program Files (x86)\Python36-32\lib\tkinter\__init__.py", line 2293, in __init__
(widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: image "\\replacing\the\server\directory\Documents\pythontests\NewLogos\DiscordLogo.gif" doesn't exist
I don't have a clue what is causing it to not find the file as the directory that is being giving out as an error works perfectly fine in Windows Explorer..
Thanks,
Xan
this is the problematic part:
global directory
quizlogo_label = Label(root, image = directory)
the Label constructor expects the image to be passed in as an ImageTk Instance, not a string containing the filename.
it needs to be something like:
global directory
self.photo = Image.PhotoImage(directory)
self.image = ImageTk.PhotoImage(self.photo)
quizlogo_label = Label(root, image = self.photo)
note that both instances of image classes as assigned as attributes of self which is the instance of Window so that they are not garbage collected when the function exits

Can't destroy inherited tkinter.Tk() window

I'm having a ton of trouble killing a tkinter window created using the below fashion. I'm getting the error shown below. I'm pretty new to Python, so any help would be greatly appreciated.
class InspectWindow(tk.Frame):
def __init__(self, sender_email, recipient_email, email_body,
master = None):
super().__init__(master)
self.create_widgets()
def create_widgets(self):
self.yes = tk.Button(self)
self.yes['text'] = 'send me!'
self.yes['command'] = self.send_email()
def send_email(self):
root.destroy()
root = tk.Tk()
popup = InspectWindow(sender_email, recipient_email, email_body,
master=root)
popup.mainloop()
Traceback (most recent call last):
File "spam.py", line 108, in <module>
master=root)
File "spam.py", line 16, in __init__
self.create_widgets()
File "AutomateFellowshipEmails.py", line 23, in create_widgets
self.yes['command'] = self.send_email()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1486, in __setitem__
self.configure({key: value})
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1479, in configure
return self._configure('configure', cnf, kw)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1470, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: invalid command name ".!inspectwindow.!button"
The problem is this line of code:
self.yes['command'] = self.send_email()
It is the exact same as if you did this:
result = self.send_email()
self.yes['command'] = reuslt
Since self.send_email() destroys the root window and then returns None, it's the same as doing this:
root.destroy()
self.yes['command'] = None
Once you destroy the root widget -- which causes all other widgets to be destroyed -- you will get an error anytime you try to call a method on a widget. When you try to configure self.yes, self.yes no longer exists so you get an error.
The solution is to pass a reference to the function of a button so that you don't immediately call it. You do it like this:
self.yes['command'] = self.send_email
Notice the lack of parenthesis on self.send_email. Instead of calling the function immediately, you are telling tk "here is the name of a function that I want you to call when the user clicks the button".
you must keep a reference of master in order to call methods on it.
(and a few other errors too)
something like this (I removed undefined variables mail, etc...)
import tkinter as tk
class InspectWindow(tk.Frame): # if this is a popup, you may like to inherit from tk.TopLevel?
def __init__(self, master = None): # removed undefined variables, you can put them back in
self.master = master # keep a reference of master
super().__init__(self.master)
self.create_widgets()
self.pack() # pack into parent window
def create_widgets(self):
self.yes = tk.Button(self)
self.yes['text'] = 'send me!'
self.yes['command'] = self.send_email # removed () call, this takes a method, not a method call
self.yes.pack() # pack into self
def send_email(self):
self.master.destroy() # call destroy on self.master
# maybe you want to call on self instead, depending what you want to destroy
root = tk.Tk()
popup = InspectWindow(master=root) # removed undefined variables, you can put them back in
popup.mainloop()

How to make functions that draw lines in canvas (tkinter 3.x) properly

I am making a program that draws a line(you decide where is the beggining and end of it with the sliders/scales), problem is im getting these errors(That i wish i understood) when i press the psy Button(code below the errors) :
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\python351\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
File "C:/Users/Koteu/PycharmProjects/guji/fsd.py", line 23, in creat
cans.create_line(ar1,ar2,br1,br2)
File "C:\python351\lib\tkinter\__init__.py", line 2331, in create_line
return self._create('line', args, kw)
File "C:\python351\lib\tkinter\__init__.py", line 2319, in _create
*(args + self._options(cnf, kw))))
_tkinter.TclError: bad screen distance ".14855536.14855504"
Process finished with exit code 0
anyways, the code :
import os
import sys
from tkinter import *
root = Tk()
app=Frame(root)
root.geometry("1200x1200")
ar1 = Scale(root,from_=0,to=600)
ar2= Scale(app,from_=0,to=600,deafultvar=0)#app instead of root because the button for unknown to me reason
#wouldn't appear in GUI otherwise
br1= Scale(root,from_=0,to=600)
br2= Scale(root,from_=0,to=600)
cans = Canvas(root,width = 500,height = 500)
cans.create_line(600,50,0,50) #This has nothing to do with the actual program by my understanding
def creat():
cans.create_line(ar1,ar2,br1,br2)#< this is what causes the problem i don't understand
psy=Button(root,command=creat,text="karole")
psy.pack()
cans.pack()
ar1.pack()
ar2.pack()
br1.pack()
br2.pack()
mainloop()
also, if that helps, im using py345
cans.create_line(x0, y0, ...) takes an even number of integer coordinates as positional args. You passed widgets, which were turned into their string identifiers. In ".14855536.14855504", '.' represents root, '14855536' is the canvas, and '14855504' is the scale ar1. Instead you need to use the .get() method on the scales to get their integer values. The following works.
from tkinter import *
root = Tk()
root.geometry("1200x1200")
ar1 = Scale(root,from_=0,to=600)
ar2= Scale(root,from_=0, to=600)
br1= Scale(root,from_=0, to=600)
br2= Scale(root,from_=0, to=600)
cans = Canvas(root, width=500, height=500)
def creat():
cans.create_line(ar1.get(), ar2.get(), br1.get(), br2.get())
psy=Button(root, command=creat, text="karole")
ar1.pack()
ar2.pack()
br1.pack()
br2.pack()
psy.pack()
cans.pack()
root.mainloop()
A couple of other fixes: the defaultvar option is not valid and caused an error; mainloop() instead of root.mainloop() caused tk to create a second Tk object, which is a bad idea.
EDIT: added the code that works.

Resources