I am trying to put an image into a window with ImageTk and PhotoImage. Below is the code:
import tkinter as tk
import random as r
from PIL import ImageTk, Image
window = tk.Tk()
HEIGHT = window.winfo_screenwidth()
WIDTH = window.winfo_screenheight()
RESOL = str(str(HEIGHT) + "x" + str(WIDTH+7) + "+" + str(-7) + "+" + str(0))
window.geometry(RESOL)
x = int(HEIGHT)/2
y = int(WIDTH)/2
updatex = HEIGHT + (0.6 * HEIGHT)
main = tk.Frame(window, height = WIDTH, width = HEIGHT)
main.configure(bg = "white", highlightthickness = 0)
main.place(x = x, y = y, anchor = "center")
Map = tk.Canvas(window, height = int((900 - int(x))) + int(900), width = int((900 - int(y))) + int(900), bg = "#44b863", highlightthickness = 0)
Map.place(x = updatex, y = int(y), anchor = "center")
p = tk.PhotoImage(file = "TitleForGameReal.png")
play_solo_image = tk.PhotoImage(file = "PlaySoloButton.png")
play_duo_image = tk.PhotoImage(file = "PlayDuoButton.png")
title = tk.Label(main, image = p, highlightthickness = 0, bd = 0)
title.place(relx = 0.5, rely = 0.35, anchor = "center")
class CustomButton:
def __init__(self, image, master, height, width, bordercolor):
self.master = master
self.frame = tk.Frame(master, height = height, width = width, highlightthickness = 0)
self.image = tk.Label(self.frame, image = image, borderwidth = 0, bg = "dark grey")
self.bordercolor = bordercolor
def put(self, x, y, command):
self.x, self.y = x, y
self.frame.place(relx = x, rely = y, anchor = "center")
self.image.pack()
def enter(event = "<Enter>"):
self.image.config(borderwidth = 3)
self.image.bind("<Enter>", enter)
def leave(event = "<Leave>"):
self.image.config(borderwidth = 0)
self.image.bind("<Leave>", leave)
def bind_command(event = "<Button-1>"):
command()
self.image.bind("<Button -1>", bind_command)
def solo():
global x, y, updatex
for i in range(int(int(int(HEIGHT/9))/2)):
x -= 20
updatex -= 20
main.place(x = x, y = y, anchor = "center")
Map.place(x = updatex, y = y, anchor = "center")
main.update()
Map.update()
player_image = Image.open("Connector.png")
player_image2 = ImageTk.PhotoImage(player_image)
class Player:
def __init__(self, hp, image):
self.hp = hp
self.image = tk.Label(Map, image = image)
self.image.place(relx = 0.5, rely = 0.5, anchor = "center")
def spawn(self):
Map.create_image(updatex, y, image = self.image)
player = Player(100, player_image2)
player.spawn()
def duo():
print("duo")
play_solo_image = tk.PhotoImage(file = "PlaySoloButton.png")
play_solo_button = CustomButton(image = play_solo_image, master = main, height = play_solo_image.height(), width = play_solo_image.width(), bordercolor = "grey")
play_solo_button.put(x = 0.39, y = 0.47, command = solo)
play_duo_button = CustomButton(image = play_duo_image, master = main, height = play_duo_image.height(), width = play_duo_image.width(), bordercolor = "grey")
play_duo_button.put(x = 0.61, y = 0.47, command = duo)
I will also leave the image as a reference, because I edited the photo to strictly have a transparent background in PhotoShop:
But this is the output I see:
Later I realized that I was also receiving an error, which may or may not have something to do with my issue:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\offcampus\AppData\Local\Programs\Python\Python35\lib\idlelib\run.py", line 125, in main
seq, request = rpc.request_queue.get(block=True, timeout=0.05)
File "C:\Users\offcampus\AppData\Local\Programs\Python\Python35\lib\queue.py", line 172, in get
raise Empty
queue.Empty
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\offcampus\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 1559, in __call__
return self.func(*args)
File "C:\Users\offcampus\Desktop\New folder\SurvivalGame.py", line 50, in bind_command
command()
File "C:\Users\offcampus\Desktop\New folder\SurvivalGame.py", line 75, in solo
player.spawn()
File "C:\Users\offcampus\Desktop\New folder\SurvivalGame.py", line 73, in spawn
Map.create_image(updatex, y, image = self.image)
File "C:\Users\offcampus\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 2338, in create_image
return self._create('image', args, kw)
File "C:\Users\offcampus\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 2329, in _create
*(args + self._options(cnf, kw))))
_tkinter.TclError: image ".2469091717696.2469132063968" doesn't exist
I know this may have something to do with garbage collection, and I would normally save a reference of it, but the problem is I can't do that since it will tell me "you can't pack a PhotoImage".
This is the tutorial I used to make the image background transparent. It's not my video, so don't flag it as spam.
The problem is image option of Map.create_image(updatex, y, image = self.image) requires a PhotoImage instance but you're giving it a label, so to fix it just say.
class Player:
def __init__(self, hp, image):
self.hp = hp
self.image = image #creating an instance variable
self.pic = ImageTk.PhotoImage(self.image) #making an photoimage instance
self.cv = Map.create_image(updatex, y, image = self.pic) #passing the photo image instance
self.pic.image = self.pic #keeping a reference to the image
Hope this has solved the error, do let me know if any errors or doubts.
Related
from keras.models import load_model
from tkinter import *
import tkinter as tk
import appscript
#import win32gui
from PIL import ImageGrab, Image
import numpy as np
model = load_model('mnist.h5')
def predict_digit(img):
#resize image to 28x28 pixels
img = img.resize((28,28))
#convert rgb to grayscale
img = img.convert('L')
img = np.array(img)
#reshaping to support our model input and normalizing
img = img.reshape(1,28,28,1)
img = img/255.0
#predicting the class
res = model.predict([img])[0]
return np.argmax(res), max(res)
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.x = self.y = 0
# Creating elements
self.canvas = tk.Canvas(self, width=300, height=300, bg = "white", cursor="cross")
self.label = tk.Label(self, text="Draw..", font=("Helvetica", 48))
self.classify_btn = tk.Button(self, text = "Recognise", command = self.classify_handwriting)
self.button_clear = tk.Button(self, text = "Clear", command = self.clear_all)
# Grid structure
self.canvas.grid(row=0, column=0, pady=2, sticky=W, )
self.label.grid(row=0, column=1,pady=2, padx=2)
self.classify_btn.grid(row=1, column=1, pady=2, padx=2)
self.button_clear.grid(row=1, column=0, pady=2)
#self.canvas.bind("<Motion>", self.start_pos)
self.canvas.bind("<B1-Motion>", self.draw_lines)
def clear_all(self):
self.canvas.delete("all")
def classify_handwriting(self):
HWND = self.canvas.winfo_id() # get the handle of the canvas
rect=self.canvas.coords(HWND)
#rect = win32gui.GetWindowRect(HWND) # get the coordinate of the canvas
a,b,c,d = rect
rect=(a+4,b+4,c-4,d-4)
im = ImageGrab.grab(rect)
digit, acc = predict_digit(im)
self.label.configure(text= str(digit)+', '+ str(int(acc*100))+'%')
def draw_lines(self, event):
self.x = event.x
self.y = event.y
r=8
HWND=self.canvas.create_oval(self.x-r, self.y-r, self.x + r, self.y + r, fill='black')
app = App()
mainloop()
Can anyone help me especially with this part :
HWND = self.canvas.winfo_id() # get the handle of the canvas
rect=self.canvas.coords(HWND)
#rect = win32gui.GetWindowRect(HWND) # get the coordinate of the canvas
a,b,c,d = rect
rect=(a+4,b+4,c-4,d-4)
im = ImageGrab.grab(rect)
This is the error that appears :
Exception in Tkinter callback
Traceback (most recent call last):
File "/Users/xxx/opt/anaconda3/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
return self.func(*args)
File "<ipython-input-4-28fb2cc31a85>", line 52, in classify_handwriting
a,b,c,d = rect
ValueError: not enough values to unpack (expected 4, got 0)
I am trying to create an ocr program to identify handwriting by letting the user draw a number and return the current value with high accuracy .
But the problem faced was with the canvas and how to get the coordinates without using the win32gui module (Since im a mac user) so I'm looking for a solution or an alternative for win32gui method GetWindowRect
self.canvas.coords(HWND) is going to return the coordinates of an object on the canvas with the id or tag of whatever is in HWND. It does not return the coordinates of the canvas itself.
Since HWND doesn't represent an item on the canvas, self.canvas.coords(HWND) returns an empty list. That is why you get the error not enough values to unpack - your code requires four values but the list has zero.
If you are wanting the coordinates of the canvas on the physical screen there are other methods you can use. See the following code:
x, y = (self.canvas.winfo_rootx(), self.canvas.winfo_rooty())
width, height = (self.canvas.winfo_width(), self.canvas.winfo_height())
a, b, c, d = (x, y, x+width, y+height)
Correct! It works fine on MACOS. comment the "import win32gui" line. Modify "classify_handwriting" function as below:
def classify_handwriting(self):
x, y = (self.canvas.winfo_rootx(), self.canvas.winfo_rooty())
width, height = (self.canvas.winfo_width(),
self.canvas.winfo_height())
a, b, c, d = (x, y, x+width, y+height)
im = ImageGrab.grab(bbox=(a,b,c,d))
Hope it works in your local setting!
So I was trying to figure out who my coordinates were messed up when adding text to an image using canvas coordinates , until I noticed that (0, 0) is off:
How would I put the origin of the canvas in the same place as Pillow does(or at least account for this when adding the text)?
class PictureWindow(tk.Toplevel):
def __init__(self, parent):
tk.Toplevel.__init__(self, parent)
self.parent = parent
self.x = self.y = 0
self.rect = None
self.tex = None
self.start_x = None
self.start_y = None
image = Image.open(file)
smaller_image = image.resize((round(image.size[0]/2), round(image.size[1]/2)))
img = ImageTk.PhotoImage(smaller_image)
self.canvas = tk.Canvas(self, width=img.width(), height=img.height())
self.canvas.img = img
self.canvas.create_image(0, 0, image=img, anchor=tk.NW)
self.canvas.pack(expand=True)
self.canvas.create_text((0, 0), text="(0, 0)", fill=self._from_rgb((225, 225, 225)))
self.canvas.bind("<ButtonPress-1>", self.on_button_press)
self.canvas.bind("<B1-Motion>", self.on_move_press)
self.canvas.bind("<ButtonRelease-1>", self.on_button_release)
self.finished = tk.Button(self, text="Add Watermark", command=self.Watermark)
self.finished.pack()
self.go_back = tk.Button(self, text="Go back to change settings", command=self.go_away)
self.go_back.pack()
def _from_rgb(self, rgb):
r, g, b = rgb
return f'#{r:02x}{g:02x}{b:02x}'
def go_away(self):
self.withdraw()
def on_button_press(self, event):
self.start_x = event.x
self.start_y = event.y
self.canvas.delete(self.tex)
self.tex = None
if not self.rect:
self.rect = self.canvas.create_rectangle(self.x, self.y, 1, 1, fill=self._from_rgb((249, 0, 0)), stipple='gray12')
def on_move_press(self, event):
self.curX, self.curY = (event.x, event.y)
self.text_x = ((self.start_x + self.curX) / 2)
self.text_y = ((self.start_y + self.curY) / 2)
self.canvas.coords(self.rect, self.start_x, self.start_y, self.curX, self.curY)
def on_button_release(self, event):
font_preview_size = int(font_size)
font_preview_almost = (font_preview_size)
font_preview = int(font_preview_almost)
if not self.tex:
self.tex = self.canvas.create_text((self.text_x, self.text_y), text=watermark_text, font=('Gotham Medium', font_preview), fill=self._from_rgb((color)))
def Watermark(self):
self.font_size_var = font_size
Font_Size = int(self.font_size_var)
A = alpha
R = int(color[0])
B = int(color[1])
G = int(color[2])
img = Image.open(file).convert("RGBA")
img_down = img.resize((int(img.width/2), int(img.height/2)), resample=Image.NEAREST)
img_down.x, img_down.y = img_down.size
txt = Image.new('RGBA', img_down.size, (225,225,225,0))
if custom_font == "yes":
font = ImageFont.truetype(font_file, Font_Size)
draw = ImageDraw.Draw(txt)
text = watermark_text
if custom_font == "no":
font = ImageFont.truetype('arial.ttf', Font_Size)
draw = ImageDraw.Draw(txt)
text = watermark_text
self.final_x = self.canvas.canvasx(self.text_x)
self.final_y = self.canvas.canvasx(self.text_x)
draw.text((self.final_x, self.final_y), text, font=font, fill=(R, G, B, A))
comp = Image.alpha_composite(img_down, txt)
img_up = comp.resize((int(comp.width*2), int(comp.height*2)), resample=Image.NEAREST)
img_up.save(save_file)
img_up.show()
p.s. if anyone knows why when the pillow text alpha is set to 0, the text is never added, please let me know!
I'll just post Bryan Oakley's comment as an answer. Pillow has an anchor option and all I needed to do was set it to mm
I am trying to create a login page, when the user clicks the login button it is supposed to display a new page (not Toplevel, and create a new window), but it doesn't seem to work.
root = Tk()
root.geometry('670x466')
accounts = []
class Goode_brothers:
def __init__(self, parent):
self.myFrame = Frame(parent)
self.myFrame.pack()
self.load = Image.open('new-dip-project\\food.jpg')
self.render = ImageTk.PhotoImage(self.load)
self.img = Label(parent, image = self.render)
self.img.place(x = -26, y =0)
self.img_login = PhotoImage(file = 'new-dip-project\\button (3).png')
self.b1 = Button(parent,image = self.img_login, command = self.read_info, bd = 0, bg = '#3b353b', activebackground = '#3b353b')
self.b1.place(x = 275, y = 340)
self.img_register = PhotoImage(file = 'new-dip-project\\register.png')
self.b2 = Button(parent,image = self.img_register, command = self.openNewWindow, bd = 0, bg = '#3b353b', activebackground = '#3b353b')
self.b2.place(x = 265, y = 400)
self.canvas = Canvas(parent, width = 400, height = 120)
self.canvas.pack()
self.img4 = ImageTk.PhotoImage(Image.open('new-dip-project\\goode.png'))
self.canvas.create_image(20, 20, anchor=NW, image=self.img4)
self.email = Entry(parent)
self.email.place(x = 340, y = 180)
self.password = Entry(parent)
self.password.place(x = 354, y = 250)
self.img_label = PhotoImage(file = 'new-dip-project\\label-image.png')
self.name = Label(parent, image = self.img_label, text = "Email:", bg = '#3c3a3b').place(x = 197,y = 178)
self.img_label_pass = PhotoImage(file = 'new-dip-project\\label_pass.png')
self.name = Label(parent, image = self.img_label_pass, text = "Password:", bg = '#3c3a3b').place(x = 177,y = 245)
def openMenu(self):
self.myFrame.destroy
self.myFrame2 = Frame()
self.myFrame2.pack()
def read_info(self):
with open("emails.txt") as read_ep:
for line in read_ep:
accounts.append(line.strip().split(", "))
credential = [self.email.get(), self.password.get()]
if credential in accounts:
self.openMenu()
else:
self.ep_notexist = Label(root, text = "Your Email or Password is incorrect, Please try again", font=("open sans", "8"))
self.ep_notexist.place(x = 210, y = 300)
self.ep_notexist.after(4000, self.ep_notexist.destroy)
First destroy all the widgets placed of login page by using
for wid in root.winfo_children():
wid.destroy()
and then pack your new frame. It will work.
(if you don't want to destroy widgets you can also use wid.pack_forget() if you have used pack to place widgets)
You actually do not destroy the frame in the below line:
def openMenu(self):
self.myFrame.destroy # <--- frame is not destroyed actually
It should be:
def openMenu(self):
self.myFrame.destroy()
I'm trying to move a frame on my GUI, but I am unable to do so because of my classes. How can I move the frame2 with a
Slider1.SetVal(x=20, y=30)
while keeping my classes.
My Code
class Slider:
def __init__ (self,Name, x, y, Height, Width, KnobHeight, KnobWidth, LowVal, HighVal, BgColor, FgColor):
self.Name = Name
self.x = x
self.y = y
self.Height = Height
self.Width = Width
self.KnobHeight = KnobHeight
self.KnobWidth = KnobWidth
self.LowVal = LowVal
self.HighVal = HighVal
self.BgColor = BgColor
self.FgColor = FgColor
def Display(self):
frame = Frame(self.Name, width=self.Width, height=self.Height, colormap="new", bg=self.BgColor)
frame.place(x=self.x, y=self.y)
frame2 = Frame(self.Name, width=self.KnobWidth, height=self.KnobHeight, colormap="new", bg=self.FgColor)
frame2.place(x=(self.x + self.Width/2 - self.KnobWidth/2), y=(self.Height - self.KnobHeight/2 + self.y))
def SetVal(self):
Main.update()
frame2.place(x=33, y=5)
window1 = Window(Main)
Slider1 = Slider(Main,100,60,200,15,15,35,0,80,"White","Green")
Slider1.Display()
Slider1.SetVal(3,30)
Main.mainloop()
I want to display the values in the text boxes, but i'm getting this error:
blue.set(B_mean1)
AttributeError: 'numpy.ndarray' object has no attribute 'set'
and my code is:
from Tkinter import Tk, Frame, BOTH
from Tkinter import *
import cv2
from collections import *
from CBIR import *
from experiment import *
from scipy.spatial import distance
import Tkinter,tkFileDialog
from PIL import Image, ImageTk
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent,background="light grey")
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("PISE")
self.pack(fill=BOTH, expand=1)
def open():
path=tkFileDialog.askopenfilename(filetypes=[("Image File",'.jpg')])
custName.set(path)
im = Image.open(path)
tkimage = ImageTk.PhotoImage(im)
myvar=Label(root,image = tkimage)
myvar.image = tkimage
myvar.pack()
myvar.place(x = 100, y = 100)
graylist1 = list()
resizelist1 = list()
eq_graylist1 = list()
cont_list1 = list()
ene_list1 = list()
homo_list1 = list()
cor_list1 = list()
B_mean1 = list()
G_mean1 = list()
R_mean1 = list()
dis_list1 = list()
imge = cv2.imread(path)
arr = array(imge)
g_img = cv2.imread(path,0)
gray_re_img = cv2.resize(g_img,(256,256))
graylist1.append(gray_re_img)
equ = cv2.equalizeHist(gray_re_img)
eq_graylist1.append(equ)
re_img = cv2.resize(imge,(256,256))
resizelist1.append(re_img)
blue, green, red = cv2.split(re_img)
total = re_img.size
B = sum(blue) / total
G = sum(green) / total
R = sum(red) / total
B_mean1.append(B)
G_mean1.append(G)
R_mean1.append(R)
im = skimage.io.imread(path, as_grey=True)
im = skimage.img_as_ubyte(im)
im /= 32
g = skimage.feature.greycomatrix(im, [1], [0], levels=8, symmetric=False, normed=True)
cont = skimage.feature.greycoprops(g, 'contrast')[0][0]
cont_list1.append(cont)
ene = skimage.feature.greycoprops(g, 'energy')[0][0]
ene_list1.append(ene)
homo = skimage.feature.greycoprops(g, 'homogeneity')[0][0]
homo_list1.append(homo)
cor = skimage.feature.greycoprops(g, 'correlation')[0][0]
cor_list1.append(cor)
dis = skimage.feature.greycoprops(g, 'dissimilarity')[0][0]
dis_list1.append(dis)
feature_matrix_ip = zip( B_mean1 , G_mean1 , R_mean1, cont_list1 , ene_list1 , homo_list1 , cor_list1 , dis_list1)
blue.set(B_mean1)
root = Tk()
root.geometry("1105x605+300+300")
app = Example(root)
label = Label(app, text='Python Image Search', fg = 'black',font = 'PoorRichard 24')
label.pack()
label.place(y = 5, x = 0)
img = Image.open('logo.png')
bg_img = ImageTk.PhotoImage(img)
label1 = Label(app, image = bg_img)
label1.place(y = 5, x = 1225)
custName = StringVar(None)
yourName = Entry(app, textvariable=custName)
yourName.grid(column=0,row=0,sticky='EW')
yourName.update()
yourName.focus_set()
yourName.pack(padx = 20, pady = 20,anchor='n')
yourName.place(y = 60, x = 100, width = 525, height = 25)
blue_label = Label(app,text = 'Blue Mean')
blue_label.place(x = 850,y = 140)
blue = IntVar()
blue_text = Entry(app,textvariable = blue)
blue_text.place(x = 1000,y = 140)
button = Button(app, text='Select an Image',command = open)
button.pack(padx = 1, pady = 1,anchor='ne')
button.place( x = 650, y = 60)
root.mainloop()
All I want to know is how to display the values into the textbox. Any suggestions are welcome.
Thanks in advance!
Your problem is that you are using the variable name blue for two different things. At one point it's a numpy array and at another it is an IntVar. When you call blue.set(...), you are doing that at the point where blue references a numpy array, hence the error message 'numpy.ndarray' object has no attribute 'set'
Try changing the name of your IntVar to something else, such as blue_var, and make sure you change it everywhere.