Tkinter Canvas Image Not Displaying Even with Reference saved - python

So I have this code:
def addTux(self, h,w,g):
global root
cx = h/(2*g)
cy = w/(2*g)
img = Image.open("sprites/tux.png")
img.thumbnail((g,g))
print "The size of the Image is: "
print(img.format, img.size, img.mode)
# img.show()
self.p_sprite = ImageTk.PhotoImage(img)
root.p_sprite = self.p_sprite
self.tux = self.canvas.create_image(cx*g, cy*g, image=self.p_sprite)
c = self.canvas.coords(self.tux)
print c
print c prints coords...
img.show() opens my penguiny thumbnail (when it's not commented out)...
but Tkinter doesn't show squat.
self.canvas.pack() is called later, and I'm saving two references to the PhotoImage just to be double sure it's not garbage collected.
All I get is a white screen.
I'm sure it's a short in the wetware... just not sure where. Any ideas?
All Code below:
app.py:
from Tkinter import *
from PIL import Image, ImageTk
import constants
class Application(Frame):
def addTux(self, h,w,g):
global root
cx = h/(2*g)
cy = w/(2*g)
img = Image.open("sprites/tux.png")
root.img = img
img.thumbnail((g,g))
print "The size of the Image is: "
print(img.format, img.size, img.mode)
img.show()
self.p_sprite = ImageTk.PhotoImage(img)
root.p_sprite = self.p_sprite
self.tux = self.canvas.create_image(cx*g, cy*g, image=self.p_sprite)
self.canvas.pack()
c = self.canvas.coords(self.tux)
print c
def createTiles(self):
h = constants.bounds["y"][1]
w = constants.bounds["x"][1]
g = constants.grid_size
self.grid = []
# for i in range(0,(h/g)):
# # self.grid.append([])
# # print self.grid[i]
# for j in range(0,(w/g)):
# s = self.canvas.create_rectangle(j * g, i*g, (j+1)*g, (i+1)*g, fill="green")
# # self.grid[i].append(s)
self.addTux(h,w,g)
self.canvas.pack()
def createWidgets(self):
global root
self.frame = Frame(root)
self.frame.pack(fill=BOTH, expand=1)
self.canvas=Canvas(self.frame, height=constants.bounds["y"][1]+10, width=constants.bounds["x"][1]+10, background="red")
self.canvas.pack(fill=BOTH, expand=1)
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
self.createTiles()
print self.p_sprite
root = Tk()
app = Application(master=root)
app.mainloop()
root.destroy()
constants.py:
grid_size=40
bounds = {
"x": [0,1000],
"y": [0,720]
}

Related

How to get circles to appear over the video in canvas tkinter?

I have the below code:
import tkinter as tk, threading
from tkinter import *
import imageio
from PIL import Image, ImageTk
from random import *
video_name = "video.mp4" #This is your video file path
video = imageio.get_reader(video_name)
def stream(label):
for image in video.iter_data():
frame_image = ImageTk.PhotoImage(Image.fromarray(image))
label.config(image=frame_image)
label.image = frame_image
def circle():
global circ
x = randint(0, 299)
y = randint(0, 299)
diameter = randint(10, 100)
circ = canvas.create_oval(x, y, x + diameter, y + diameter, tags="circle")
canvas.tag_raise(circ)
if __name__ == "__main__":
root = tk.Tk()
canvas = Canvas(root, bg="green")
canvas.pack(expand=True, fill=BOTH)
my_label = tk.Label(canvas)
my_label.pack()
b = Button(canvas, text="Circle", command=circle)
b.pack()
thread = threading.Thread(target=stream, args=(my_label,))
thread.daemon = 1
thread.start()
root.mainloop()
It works fine, and the circles appear, but they go behind the video playing. How can I make the circles appear on top of the video?
Thanks!
You will need to use a text item on the canvas rather than a label. The canvas does not allow you to draw on top of widgets embedded in or on the canvas.

Trying to make image slideshow with Tkinter (Python3)

I was trying to make an image slideshow program with Tkinter and Python3. No errors, but not showing the images that are inside my chosen directory. The other libraries that I have use are: PIL, random and glob. Your help will be greatly appreciated.
My system:
Ubuntu 20.04 LTS
Here is the code:
import tkinter as Tk
from PIL import Image, ImageTk
import random
import glob
class gui:
def __init__(self, mainwin):
self.counter = 0
self.mainwin = mainwin
self.mainwin.title("Our Photos")
self.colour()
self.mainwin.configure(bg = "yellow")
self.Frame = Tk.Frame(mainwin)
self.img = Tk.Label(self.Frame)
self.Frame.place(relheight = 0.85, relwidth = 0.9, relx = 0.05, rely = 0.05 )
self.img.pack()
self.pic()
def colour(self):
self.colours =['gray47','gray48']
c = random.choice(self.colours)
self.mainwin.configure(bg = c)
root.after(4000, self.colour)
def pic(self):
for name in glob.glob(r"/home/maheswar/Pictures/*"):
self.pic_list = []
val = name
self.pic_list.append(val)
if self.counter == len(self.pic_list) - 1:
self.counter = 0
else:
self.counter == self.counter + 1
self.file = self.pic_list[self.counter]
self.load = Image.open(self.file)
self.pic_width = self.load.size[0]
self.pic_height = self.load.size[1]
self.real_aspect = self.pic_width/self.pic_height
self.calc_width = int(self.real_aspect * 800)
self.load2 = self.load.resize((self.calc_width, 800))
self.render = ImageTk.PhotoImage(self.load2)
self.img.config(image = self.render)
self.img.image = self.render
root.after(2000, self.pic)
root = Tk.Tk()
myprog = gui(root)
root.geometry("1000x1000")
root.mainloop()
I found two mistaces - which probably you could see if you would use print() to debug code
First: you create list self.pic_list = [] inside loop so you replace previous content and this way you can get only one list. But you don't event need this loop but directly
self.pic_list = glob.glob(r"/home/maheswar/Pictures/*")
Second: you need = instead of == in line self.counter = self.counter + 1 or even simpler
self.counter += 1
Full working code with small changes.
import tkinter as Tk
from PIL import Image, ImageTk
import random
import glob
class GUI: # PEP8: `CamelCaseNames` for classes
def __init__(self, mainwin):
self.mainwin = mainwin
self.mainwin.title("Our Photos")
self.mainwin.configure(bg="yellow") # PEP8: inside `()` use `=` without spaces
self.counter = 0
self.frame = Tk.Frame(mainwin) # PEP8: `lower_case_names` for variables
self.frame.place(relheight=0.85, relwidth=0.9, relx=0.05, rely=0.05)
self.img = Tk.Label(self.frame)
self.img.pack()
self.pic_list = glob.glob("/home/maheswar/Pictures/*") # no need prefix `r`
self.colours = ['gray47', 'gray48'] # PEP8: space after `,`
self.colour()
self.pic()
def colour(self):
selected = random.choice(self.colours)
self.mainwin.configure(bg=selected)
root.after(4000, self.colour)
def pic(self):
filename = self.pic_list[self.counter]
image = Image.open(filename)
real_aspect = image.size[0]/image.size[1]
width = int(real_aspect * 800)
image = image.resize((width, 800))
self.photo = ImageTk.PhotoImage(image)
self.img.config(image=self.photo)
#self.img.image = self.render no need if you use `self.` to keep PhotoImage
self.counter += 1
if self.counter >= len(self.pic_list):
self.counter = 0
root.after(2000, self.pic)
# --- main ---
root = Tk.Tk()
myprog = GUI(root)
root.geometry("1000x1000")
root.mainloop()
PEP 8 -- Style Guide for Python Code

Config Label In classes tkinter [duplicate]

This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 11 months ago.
Im trying to develop a GUI to capture images in a new window. In my work i'am trying to pass a directory of the image to be use on future functions, as of now im trying to configure a label to change its text to my image path
import tkinter as tk
from tkinter import *
import cv2
from PIL import Image, ImageTk
from tkinter.filedialog import askopenfilename
import os
from tkinter import messagebox
from pathlib import PosixPath
from numpy import result_type
class CamView():
def __init__(self, parent):
self.parent = parent
self.window = tk.Toplevel(parent)
self.lmain2 = tk.Label(self.window)
self.lmain2.pack()
self.window.protocol("WM_DELETE_WINDOW", self.close)
self.show_frame()
self.multiple()
self.btn2 = tk.Button(self.window,text="Close", command = lambda: self.close())
self.btn2.pack()
def multiple(self):
self.takePicture_button = tk.Button(self.window, text="Capture Signature",command = lambda: [Main.captureImage(self.parent),self.close()])
self.takePicture_button.pack(ipadx=5,ipady=5,pady=5)
def show_frame(self):
imgtk = ImageTk.PhotoImage(image=self.parent.img)
self.lmain2.imgtk = imgtk
self.lmain2.configure(image=imgtk)
def close(self):
self.parent.test_frame = None
self.window.destroy()
root = tk.Tk()
root.bind('<Escape>', lambda e: root.quit())
font_size = 14
window_width = 800
window_height = 400
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
center_x = int(screen_width/2 - window_width / 2)
center_y = int(screen_height/2 - window_height / 2)
root.geometry(f'{window_width}x{window_height}+{center_x}+{center_y}')
frame_dirpath = tk.Frame(root)
frame_dirpath.pack(ipadx=5,ipady=5)
class Main(tk.Frame):
def __init__(self, parent):
self.lmain = tk.Label(parent)
self.lmain.pack()
self.test_frame = None
frame = Frame.__init__(self,parent)
a = Label(text='Verify Signatures:').pack(ipadx=5,ipady=5)
self.c = tk.Label(text = "check").pack(ipadx=5,ipady=5)
b = tk.Button(frame, text='CAMERA', command=self.load_window)
b.pack()
self.image1_path_entry = tk.Entry(frame_dirpath, font=font_size,width=25).pack(ipadx = 5, ipady = 5)
width, height = 800, 600
self.cap = cv2.VideoCapture(0)
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
self.do_stuff()
def do_stuff(self):
_, frame = self.cap.read()
frame = cv2.flip(frame, 1)
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
self.img = Image.fromarray(cv2image)
if self.test_frame != None:
self.test_frame.show_frame()
self.lmain.after(10, self.do_stuff)
def captureImage(self):
image_to_write = self.cap.read()[1]
filetowrite = "D:/Downloads/c.jpeg"
print(str(filetowrite))
cv2.imwrite(str(filetowrite),image_to_write)
self.c.configure(text = filetowrite)
return
def load_window(self):
if self.test_frame == None:
self.test_frame = CamView(self)
control = Main(root)
root.mainloop()
As on the line self.c = tk.Label(text = "check").pack(ipadx=5,ipady=5) im trying to configure this label to the image path on the function when capturing an image. All i get is object is has no attribute
Changed this:
self.c = tk.Label(text = "check").pack(ipadx=5,ipady=5)
to:
self.c = tk.Label(frame, text = "check").pack(ipadx=5,ipady=5)
You did same as tk.Button(frame,

How to display image with upload button in and resize it with window resize (Dynamically)with Tkinter python, I need to add upload button

I need to add upload button so that I can upload the picture and display with this class. Everything working but when I am adding the upload button its giving me some error and my code is not wokring.
import tkinter as tk
from tkinter import *
from PIL import Image, ImageTk
from tkinter import filedialog
class Layout:
def __init__(self,master):
self.master = master
self.rootgeometry()
self.canvas = tk.Canvas(self.master)
self.canvas.pack()
self.background_image = Image.open(self.openfn())
self.image_copy = self.background_image.copy()
self.background = ImageTk.PhotoImage(self.background_image)
self.loadbackground()
def loadbackground(self):
self.label = tk.Label(self.canvas, image = self.background)
self.label.bind('<Configure>',self.resizeimage)
self.label.pack(fill='both', expand='yes')
def openfn(self):
filename = filedialog.askopenfilename(title='open')
return filename
def rootgeometry(self):
x=int(self.master.winfo_screenwidth()*0.7)
y=int(self.master.winfo_screenheight()*0.7)
z = str(x) +'x'+str(y)
self.master.geometry(z)
def resizeimage(self,event):
image = self.image_copy.resize((self.master.winfo_width(),self.master.winfo_height()))
self.image1 = ImageTk.PhotoImage(image)
self.label.config(image = self.image1)
root = tk.Tk()
a = Layout(root)
root.mainloop()
Create the Button widget within the class constructor and bind it with self.loadbackground. Also, you don't need to recreate the Label widget every time instead use label.configure(image=yourimage).
Here is the code:
import tkinter as tk
from tkinter import *
from PIL import Image, ImageTk
from tkinter import filedialog
class Layout:
def __init__(self,master):
self.master = master
self.rootgeometry()
self.button = Button(self.master, text='Upload', command=self.loadbackground)
self.button.pack()
self.canvas = tk.Canvas(self.master)
self.canvas.pack(fill=BOTH, expand=True)
self.background_image = None
self.image_copy = None
self.background = None
self.label = tk.Label(self.canvas)
self.label.pack(fill='both', expand=True)
def loadbackground(self):
self.background_image = Image.open(self.openfn())
self.image_copy = self.background_image.copy()
self.background = ImageTk.PhotoImage(self.background_image.resize((self.canvas.winfo_width(), self.canvas.winfo_height())))
self.label.configure(image=self.background)
self.label.bind('<Configure>',self.resizeimage)
def openfn(self):
filename = filedialog.askopenfilename(title='open')
return filename
def rootgeometry(self):
x=int(self.master.winfo_screenwidth()*0.7)
y=int(self.master.winfo_screenheight()*0.7)
z = str(x) +'x'+str(y)
self.master.geometry(z)
def resizeimage(self,event):
image = self.image_copy.resize((event.width, event.height))
self.image1 = ImageTk.PhotoImage(image)
self.label.config(image = self.image1)
root = tk.Tk()
a = Layout(root)
root.mainloop()

Why tkinter canvas doesn't update when used in a class

I am writing a small program, where I want to draw something on canvas. This code works for me;
import tkinter as tk
from PIL import Image, ImageTk
from l_systems import Lindenmayer
if __name__ == "__main__":
root = tk.Tk()
root.title("Draw Shapes with L-Equations")
cv = tk.Canvas(width=600, height=600, bg='white')
cv.pack()
image1 = Image.new("RGB", (600, 600), (255,255,255))
koch = Lindenmayer(image1)
koch.init(
iterations = 6,
angle = 25,
axiom = "---X",
rules = {"X":"2F-[1[X]+3X]4+F[3+FX]-X", "F":"FF"},
constants = "X") # This creates a drawing on PIL image
# Canvas.create_image expects a PhotoImage
photo = ImageTk.PhotoImage(image1)
cv.create_image((300,300), image=photo)
root.mainloop()
However, I want to organize my tkinter application as a class, therefore I have tried this code,
class main(tk.Frame):
w = 600
h = 600
def __init__(self,parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
self.cv = tk.Canvas(width=self.w, height=self.h, bg='white')
self.cv.pack()
self.render_image()
def render_image(self):
image1 = Image.new("RGB", (self.w, self.h), (255,255,255))
koch = Lindenmayer(image1)
koch.init(
iterations = 6,
angle = 25,
axiom = "---X",
rules = {"X":"2F-[1[X]+3X]4+F[3+FX]-X", "F":"FF"},
constants = "X"
)
photo = ImageTk.PhotoImage(image1)
self.cv.create_image((self.w/2,self.h/2), image=photo)
if __name__ == "__main__":
root = tk.Tk()
root.title("Draw Shapes with L-Equations")
app = main(root).pack()
root.mainloop()
In this second case, I don't see any drawing on canvas. It is just a white background. How can I fix this?
PhotoImage can have problem in classes and functions. Garbage collector can remove it from memory.
EDIT:
I could check this (because I have to Lindenmayer module)
but your class could look this:
Almost everything is in class.
Class names should normally use the CapWords convention. - see PEP 8 -- Style Guide for Python Code. Event SO use that rule to recognize classes in code and use light blue color.
import tkinter as tk
from PIL import Image, ImageTk
from l_systems import Lindenmayer
class Main(tk.Frame):
def __init__(self,parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.w = 600
self.h = 600
self.parent = parent
self.parent.title("Draw Shapes with L-Equations")
self.cv = tk.Canvas(width=self.w, height=self.h, bg='white')
self.cv.pack()
self.render_image()
self.parent.pack()
def render_image(self):
image1 = Image.new("RGB", (self.w, self.h), (255,255,255))
koch = Lindenmayer(image1)
koch.init(
iterations = 6,
angle = 25,
axiom = "---X",
rules = {"X":"2F-[1[X]+3X]4+F[3+FX]-X", "F":"FF"},
constants = "X"
)
self.photo = ImageTk.PhotoImage(image1)
self.cv.create_image((self.w/2,self.h/2), image=self.photo)
def run(self):
self.parent.mainloop()
if __name__ == "__main__":
Main(tk.Tk()).run()

Categories

Resources