This is the first program I'm writing utilizing Tkinter, so I apologize in advance if my questions are a bit naive.
I have the following:
class Example(Frame):
def __init__(self, master=None):
Frame.__init__(self,master)
menubar = Menu(self)
master.config(menu=menubar)
self.centerWindow(master)
self.Top_Bar(menubar,master)
self.pack(fill = BOTH, expand = 1)
def Top_Bar(self,menubar,master):
fileMenu = Menu(menubar,tearoff=False)
menubar.add_cascade(label="File",menu=fileMenu)
fileMenu.add_command(label="Open",command = self.open_file)
fileMenu.add_command(label="Exit",command = self.quit)
fileMenu = Menu(menubar,tearoff=False)
menubar.add_cascade(label="Edit",menu=fileMenu)
fileMenu = Menu(menubar,tearoff=False)
menubar.add_cascade(label="Shortcuts",menu=fileMenu)
fileMenu = Menu(menubar,tearoff=False)
menubar.add_command(label="About",command = Message_About)
Notice that I have self.open_file as a command, which is itself a function:
def open_file(self):
""" A function that opens the file dialog and allows a user to select a single file, displaying it on the page """
global filename
filename = []
filename.append(str(unicodedata.normalize("NFKD",tkFileDialog.askopenfilename(filetypes=[("Astronomical Data","*.fit;*fits")])).encode("ascii","ignore")))
for i in filename:
stretch_type = "linear"
image_manipulation_pyfits.create_png(i,stretch_type)
x = Image.open("file.png")
Label(image = x).pack()
I'm certain there's a shorter, more efficient way of writing this function, but that isn't my primary goal at this point -- it's just to get everything to work. My goal is to take this image x and display it in the Tkinter window. It gives me the error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\python27\lib\lib-tk\Tkinter.py", line 1486, in __call__
return self.func(*args)
File "tkinter1.py", line 125, in open_file
Label(image = x).pack()
File "C:\python27\lib\lib-tk\ttk.py", line 766, in __init__
Widget.__init__(self, master, "ttk::label", kw)
File "C:\python27\lib\lib-tk\ttk.py", line 564, in __init__
Tkinter.Widget.__init__(self, master, widgetname, kw=kw)
File "C:\python27\lib\lib-tk\Tkinter.py", line 2055, in __init__
(widgetName, self._w) + extra + self._options(cnf))
TclError: image specification must contain an odd number of elements
For clarity, the prior function simply takes an input .fits image (selected from the dialog box that pops up) and applies the linear stretch, then saves it as a .png image to the same directory under the name "file.png".
I've Googled for the past day or so and haven't been able to find any threads on this error.
One solution I have found:
x = Image.open("file.gif")
x = ImageTk.PhotoImage(x)
label = Label(image = x)
label.image = x
label.pack()
Save the image as a .gif and open
Need to use PhotoImage from ImageTk.
I would comment if I could, but just a note about #bjd2385's answer. In his case, label.image = x saves a reference of the image, however if this line of code is omitted, then you would need to save a reference by using self, if using classes in your design pattern. Instead of im = ImageTk.PhotoImage("...") it would then be self.im = ImageTk.PhotoImage("...") otherwise it can get garbage collected and still display an outline of where the image would be, but not actually have an image present.
Also, you can directly open an image from the PhotoImage call. I'm not sure of the complete limitations of image files possible to be used, but I know you can use .gif and .png. Here's his answer reworked for Python3.4:
import tkinter
self.img = ImageTk.PhotoImage(file = "./images/file.png")
label = Label(image = self.img)
label.image = self.img # this line can be omitted if using the 'self' method to save a reference
label.pack()
Related
When running the code, I receive this error:
[(<memory at 0x000001ADB67D2040>,)]
1
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=592x1052 at 0x1ADB67FF280>
=-----------------------------------=
pyimage1
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Player 1\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "c:\Users\Player 1\OneDrive\Documents\Year 13\Computer Science\NEA\Code\windows.py", line 373, in <lambda>
images_button = tkinter.Button(self, text="View {} Images".format(listingname), font=('calibre', 20, 'bold'), command=lambda: self.create_command_for_Nav_Buttons("Pictures", condition=listing_id)).grid(column=0, row=0, rowspan=7)
File "c:\Users\Player 1\OneDrive\Documents\Year 13\Computer Science\NEA\Code\windows.py", line 77, in create_command_for_Nav_Buttons
start_window.create_page(condition)
File "c:\Users\Player 1\OneDrive\Documents\Year 13\Computer Science\NEA\Code\windows.py", line 412, in create_page
images = tkinter.Label(master=self, image=photo, width=300, height=300)
File "C:\Users\Player 1\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 3148, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "C:\Users\Player 1\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 2572, in __init__
self.tk.call(
_tkinter.TclError: image "pyimage1" doesn't exist
This is the part of the code that doesn't work.
class picture_page(Window):
def __init__(self, current_window="Pictures!") -> None:
super().__init__(current_window)
def create_page(self, listing_id):
imagesMView_list = dbm.getImagesForListing(listing_id)
print(imagesMView_list)
print(len(imagesMView_list))
if len(imagesMView_list) == 0:
self.create_Label("There are no images!", ('calibre', 20, 'bold'), 0, 0)
else:
processedImage_list = []
for i in range(len(imagesMView_list[0])):
processedImage_list.append(bytes(imagesMView_list[0][i]))
# for i in range(len(processedImage_list)):
# img = Image.open(io.BytesIO(processedImage_list[i]))
# photo = ImageTk.PhotoImage(img)
# print(img)
# print(photo)
# tkinter.Label(master=self, image=photo).pack()
for i in range(len(processedImage_list)):
img = Image.open(io.BytesIO(processedImage_list[i]))
print(img)
print("=-----------------------------------=")
photo = ImageTk.PhotoImage(img)
print(photo)
images = tkinter.Label(master=self, image=photo, width=300, height=300)
images.grid(column=i, row=0)
The commented part that looks like code was another fix I tried.
I also looked through these other stackoverflow questions (Tkinter OOP "PyImage1" doesn't exist, error and Tkinter create image function error (pyimage1 does not exist))
Thank you in advance!
EDIT: I have tried to put Global photo into my code to keep it as a reference, however that still causes the same issue to occur. I also wanted to say that this photo_page subclass inherits from the Windows Class and the Windows class inherits from Tk. This hasn't caused me any issues other than with putting an image in the label. The image comes from a database and in the database is stored as a byte Array and I convert it back into bytes and then into JPEG form (which I know is successful because I printed out the variables I assigned it to and they look fine).
The way I fixed my error was changing what my main class inherited. Initially, it was Windows(Tk): , however I changed it to Windows(Toplevel) and it fixed the issue.
have you by chance accidentally created two or more root windows? Objects in one root window cant see or interact with things
in the second root window
This question already has an answer here:
AttributeError: object has no attribute 'tk'
(1 answer)
Closed 2 years ago.
I've looked around for a bit, but might of got off track trying to fix the issue.
Trying to scan selected folder for extensions, then populate checkboxes with found extensions for user to select what extensions to move forward with. the amount of checkboxes can change source to source, tried using the super() but don't believe to be using it right.
import os
from tkinter import *
import tkinter #as tk
from tkinter import filedialog
root = tkinter.Tk()
root.withdraw()
file_path = filedialog.askdirectory()
print(file_path)
#src_folder = "../../"
src_folder = file_path
ListFiles = os.walk(src_folder)
SplitTypes = []
for walk_output in ListFiles:
for file_name in walk_output[-1]:
SplitTypes.append(file_name.split(".")[-1])
#print(SplitTypes)
extensions = []
for i in SplitTypes:
if i not in extensions:
extensions.append(i)
extensions = str(extensions)
#print(str(extensions))
print(extensions)
class CheckBox(tkinter.Checkbutton):
boxes = [] # Storage for all buttons
def __init__(self, master, *args, **options):
super(CheckBox, self).__init__()
tkinter.Checkbutton.__init__(self, *args, options) # Subclass checkbutton to keep other methods
self.boxes.append(self)
self.var = tkinter.BooleanVar() # var used to store checkbox state (on/off)
self.text = self.cget('text') # store the text for later
self.configure(variable=self.var) # set the checkbox to use our var
a=0
while a<len(extensions):
button=CheckBox(tkinter, text=extensions[a], command=print(extensions[a])) # Replace Checkbutton
a=a+1
button.pack()
extensions_check = []
for box in CheckBox.boxes:
if box.var.get(): # Checks if the button is ticked
extensions_check.append(box.text)
print(extensions_check)
error that i am getting is
C:\Users\Python\Projects\filescanner\Scripts\python.exe C:/Users/Python/Projects/filescanner/extensionfinder.py
F:/TestFolder
['xlsx', 'txt', 'avi', 'nxt']
[
Traceback (most recent call last):
File "C:/Users/Python/Projects/filescanner/extensionfinder.py", line 45, in <module>
button=CheckBox(tkinter, text=extensions[a], command=print(extensions[a])) # Replace Checkbutton
File "C:/Users/Python/Projects/filescanner/extensionfinder.py", line 36, in __init__
tkinter.Checkbutton.__init__(self, *args, options) # Subclass checkbutton to keep other methods
File "C:\Python\Current Install\lib\tkinter\__init__.py", line 2993, in __init__
Widget.__init__(self, master, 'checkbutton', cnf, kw)
File "C:\Python\Current Install\lib\tkinter\__init__.py", line 2561, in __init__
BaseWidget._setup(self, master, cnf)
File "C:\Python\Current Install\lib\tkinter\__init__.py", line 2530, in _setup
self.tk = master.tk
AttributeError: 'dict' object has no attribute 'tk'
Process finished with exit code 1
I am new to the python world and up for any advise, thank you all in advance
There are two errors (at least, two that cause the error you describe):
button=CheckBox(tkinter, text=extensions[a], command=print(extensions[a]))
Should be:
button=CheckBox(root, text=extensions[a], command=print(extensions[a]))
And:
tkinter.Checkbutton.__init__(self, *args, options)
Should be:
tkinter.Checkbutton.__init__(self, master, *args, options)
You should either use one of the two lines below:
super().__init__(master, *args, options)
tkinter.Checkbutton.__init__(self, master, *args, options) # Subclass checkbutton to keep other methods
Both are equivalent though most people prefer to use super()
So I am trying to put some pictures into my window and whenever I run the program it gives me this error:
_tkinter.TclError: encountered an unsupported criticial chunk type "exIf"
I tried putting it into other formats, such as .jpg, .png and .gif, but they don't work. Can you please help me?
This is my code:
from tkinter import *
from tkinter import ttk
class Window:
def __init__(self, master):
self.master = master
master.iconbitmap('ta.ico')
master.title('Tamagochi')
master.minsize(width=480, height=240)
master.maxsize(width=480, height=240)
self.pic1 = PhotoImage(file='pic1.png')
self.pic2 = PhotoImage(file='pic2.png')
self.pic3 = PhotoImage(file='pic3.png')
self.pic4 = PhotoImage(file='pic4.png')
self.smFrame = ttk.Frame(master)
self.smButton1 = ttk.Button(self.smFrame, text='Start', command=self.start)
self.smButton2 = ttk.Button(self.smFrame, text='Options', command=self.options)
self.smButton3 = ttk.Button(self.smFrame, text='Quit', command=self.quit)
self.smPhoto1 = ttk.Label(self.smFrame, image=self.pic1)
self.smFrame.pack()
self.smPhoto1.grid()
self.smButton1.grid(pady=40, padx=200)
self.smButton2.grid(pady=0, padx=200)
self.smButton3.grid(pady=40, padx=200)
def start(self):
pass
def options(self):
pass
def quit(self):
exit()
root = Tk()
Window(root)
root.mainloop()
This is the full error:
Traceback (most recent call last):
File "C:/Users/NemPl/Desktop/ProLan/Python/Python programi/Tamagochi/Tamagochi.py", line 35, in <module>
Window(root)
File "C:/Users/NemPl/Desktop/ProLan/Python/Python programi/Tamagochi/Tamagochi.py", line 14, in __init__
self.pic3 = PhotoImage(file='pic3.png')
File "C:\Users\NemPl\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 3539, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "C:\Users\NemPl\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 3495, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: encountered an unsupported criticial chunk type "exIf"
PhotoImage is a tkinter class which, unfortunately, can not deal with .png files.
The solution is to rely on the Python Imaging Library1 which offers support to several image formats and transforms them to image objects that can be "understood" by tkinter:
from PIL import Image, ImageTk
self.img1 = Image.open("pic1.png")
self.pic1 = ImageTk.PhotoImage(self.img1)
1. You can install PIL as described here.
Just wanted to share a solution that solved for me!
I figured out that other '.png' images were working with the same code, so the problem was happening with the image file.
What solved my problem was simply modifying the image (just saved it from a image editor).
I have a listbox that I want to update every minute or so. It pulls XML data, parses it and put it into the list box automatically. I have figured out to use the .after method but upon implementing it outside of the class I run into bug after bug trying to make it run. I believe my main issue is just not calling the application correctly but I could be wrong. Here is some of the relevent code.
This is all outside the main class
def refresher(frame):
subreddit=Application.entryVar(Application)
Application.getXML(subreddit)
frame.after(1000,refresher,frame)
main = tk.Tk()
main.wm_title("Readdit")
# main.geometry("350x400")
app = Application(master=main)
# Begins the applications GUI loop
# app.__init__()
refresher(main)
app.mainloop()
Here is the beginning of the program and this is where it ultimately falls back upon with all the bugs.
class Application(tk.Frame):
print("what about this?")
def __init__(self, master=None):
self.threadTitle = tk.StringVar()
self.threadAuth = tk.StringVar()
self.threadPub = tk.StringVar()
self.threadArtLink = tk.StringVar()
self.threadLink = tk.StringVar()
self.threadImg = tk.StringVar()
self.threadArtLink.set('Click something to display thread info')
self.photo = Image.open("temp.png")
self.photo = self.photo.resize((250,250), Image.ANTIALIAS)
self.threadImage = ImageTk.PhotoImage(self.photo)
self.errMes = tk.StringVar()
if not os.path.exists('Pics'):
os.makedirs('Pics')
# print('Something')
# Intializes tkinter gui framework
tk.Frame.__init__(self, master)
# Packs widgets needed
self.grid()
# Creates the widgets functions
self.createWidgets()
# Intializes the man rss.xml
self.initial()
def createWidgets(self):
# Create entrybox and align to grid
self.send_entry = tk.Entry(self)
self.send_entry.grid(row=0,column=0)
# Create button,allign to grid, get xml
self.change_sub = tk.Button(self,text='Change Subreddit',padx=5, pady=5, command=lambda :self.entryVar())
And here is the full error
Traceback (most recent call last):
File "S:/Projects/xmlParser.py", line 306, in <module>
refresher(main)
File "S:/Projects/xmlParser.py", line 296, in refresher
subreddit=Application.entryVar(Application)
File "S:/Projects/xmlParser.py", line 290, in entryVar
rawInput=self.createWidgets(self).send_entry.get()
File "S:/Projects/xmlParser.py", line 40, in createWidgets
self.send_entry = tk.Entry(self)
File "C:\Python33\lib\tkinter\__init__.py", line 2506, in __init__
Widget.__init__(self, master, 'entry', cnf, kw)
File "C:\Python33\lib\tkinter\__init__.py", line 2068, in __init__
BaseWidget._setup(self, master, cnf)
File "C:\Python33\lib\tkinter\__init__.py", line 2046, in _setup
self.tk = master.tk
AttributeError: type object 'Application' has no attribute 'tk'
I think you should use your app directly in the function call to refresher:
def refresher(frame):
frame.getXML()# I Don`t know what do this function, just an example
frame.after(1000,refresher,frame)
main = tk.Tk()
main.wm_title("Readdit")
# main.geometry("350x400")
app = Application(master=main)
# Begins the applications GUI loop
# app.__init__()
refresher(app) #use app here
app.mainloop()
It looks like the problem is here:
Application.entryVar(Application)
Application is a class rather than an object, so my guess is that you should be using an instance of Application both places in that code.
I am trying to simultaneously read data from a HID with pywinusb and then update a tkinter window with that data. When something happens on the HID side, I want my tkinter window to immediately reflect that change.
Here is the code:
import pywinusb.hid as hid
from tkinter import *
class MyApp(Frame):
def __init__(self, master):
super(MyApp, self).__init__(master)
self.grid()
self.setupWidgets()
self.receive_data()
def setupWidgets(self):
self.data1 = StringVar()
self.data1_Var = Label(self, textvariable = self.data1)
self.data1_Var.grid(row = 0, column = 0, sticky = W)
def update_data1(self, data):
self.data1.set(data)
self.data1_Var.after(200, self.update_data1)
def update_all_data(self, data):
self.update_data1(data[1])
#self.update_data2(data[2]), all points updated here...
def receive_data(self):
self.all_hids = hid.find_all_hid_devices()
self.device = self.all_hids[0]
self.device.open()
#sets update_all_data as data handler
self.device.set_raw_data_handler(self.update_all_data)
root = Tk()
root.title("Application")
root.geometry("600x250")
window = MyApp(root)
window.mainloop()
When I run the code and make the device send data, I get this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python 3.3\lib\tkinter\__init__.py", line 1442, in __call__
return self.func(*args)
File "C:\Program Files\Python 3.3\lib\tkinter\__init__.py", line 501, in callit
func(*args)
TypeError: update_data1() missing 1 required positional argument: 'data'
I guess my question is:
How do I continually update the label with the current data from the HID?
How can I pass the new data to update_data1()?
Edit: Should I be using threading, so that I have one thread receiving data and the mainloop() thread periodically checking for new data? I haven't used threading before, but could this be a solution?
If there is a better way to do this, please let my know.
Thanks!
self.data1_Var.after(200, self.update_data1) is the problem. You need to pass self.update_data1's parameter to self.data1_Var.after (e.g. self.data1_Var.after(200, self.update_data1, some_data)). Otherwise after 200 milliseconds, self.update_data1 will be called without the parameter, causing the error you are seeing.
BTW, why don't directly edit the label's text instead of putting the code in self.update_all_data. It's not clear to me why self.data1_Var.after(200, self.update_data1) is required, because whenever new data is received, update_all_data is called, which calls update_data1 which updates the text.