How store event.width in a variable in python? - python

I have a script that displays the dimensions of the tkinter window and I was wondering how I can set those values into a variable?
Here is the code:
import tkinter as tk
from tkinter import PhotoImage
root = tk.Tk()
canvas = tk.Canvas(root)
canvas.pack(fill="both", expand=True)
def canvas_changed(event):
global WW
WW = event.width
global HH
HH = event.height
img = PhotoImage(file="competeButton.png")
foo = canvas.create_image(image=img, width=WW, height=HH)
foo.pack(fill="both", expand=True)
root.mainloop()
Many thanks in advance for any help.

There's nothing special you have to do. Data is data, whether it comes from a widget or a database or anything else.
Here's an example that saves the value to a global variable:
def canvas_changed(event):
global canvas_width
canvas_width = event.width

Create a class with all your image and the resizing of it. Then issue an if statement to call those values every time it changes. Here is an example of what you might do:
import tkinter as tk
from PIL import Image, ImageTk
class MainFrame(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.canvas = tk.Canvas(self)
self.canvas.pack(fill=tk.BOTH, expand=1)
self.canvas.bind("<Configure>", self.resize)
self.img = ImageTk.PhotoImage(Image.open(r"competeButton.png"))
self.canvas_img = self.canvas.create_image(0, 0, anchor="nw", image=self.img)
def resize(self, event):
img = Image.open(r"competeButton.png").resize((event.width, event.height), Image.ANTIALIAS)
self.img = ImageTk.PhotoImage(img)
self.canvas.itemconfig(self.canvas_img, image=self.img)
if __name__ == "__main__":
main_frame = MainFrame()
main_frame.mainloop()

Related

Tkinter resize frame inside canvas does not work

I want to resize a frame inside my canvas, so that the frame covers the whole window.
I did some googleing and saw some people are using a resize function, but this doesn't work for me.
I get the following error message:
_tkinter.TclError: invalid boolean operator in tag search expression
This is my code:
import tkinter as tk
from tkinter import ttk
class MainGUI:
def __init__(self):
self.root = tk.Tk()
self.root.geometry('400x400')
self.root.title("A simple GUI")
self.canvas = tk.Canvas(self.root, background='GREEN',width=900,height=300,scrollregion=(0,0,500,2000))
self.scrollbar=tk.Scrollbar(self.canvas,orient="vertical",command=self.canvas.yview)
self.scrollbar.pack(side="right",fill="y")
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.canvas.bind('<Configure>', lambda e: self.canvas.configure(scrollregion = self.canvas.bbox("all")))
self.main = tk.Frame(self.canvas,bg='BLUE')
self.canvas.create_window((0,0), window=self.main, anchor="nw")
self.canvas.pack(side=tk.TOP,fill=tk.BOTH,expand=True)
self.canvas.bind("<Configure>", self.resize_frame)
for _ in range(30):
MyCoolFrame(self.main)
def resize_frame(self, e):
canvas_width = e.width
self.canvas.itemconfig(self.main, width = canvas_width)
class MyCoolFrame:
def __init__(self,master):
self.master = master
self.frame = tk.Frame(self.master,bg='RED')
for i in range(5):
tk.Label(self.frame,text=f'Cool Label {i}').pack(side=tk.LEFT,padx=2,pady=10)
self.frame.pack(side=tk.TOP,pady=10)
a = MainGUI()
a.root.mainloop()

How Can I use this code to directly change my image more than one time by using after command

I really not sure where i do blunders but I try it many time but not get result, actually I wanted to change my image in tkinter window after sometime without creating a button, I find some code from here and do changes on it but I am not able to change image after once, the image is change only once, after second image is static and not change in visible, please help to find a solution.
val = 2000 #milisecond
val1 = 1000 #milisecond
val2 = 5000 #milisecond
from tkinter import *
from PIL import Image, ImageTk
class myGUI(object):
def __init__(self):
self.root = Tk()
self.canvas = Canvas(width=800, height=800, bg='white')
self.canvas.pack()
filename="image1.png"
image = Image.open(filename)
self.photo = ImageTk.PhotoImage(image)
self.img = self.canvas.create_image(250, 250, image=self.photo)
self.root.after(val, self.change_photo)
self.root.mainloop()
def change_photo(self):
filename = "image2.png"
image = Image.open(filename)
self.photo = ImageTk.PhotoImage(image)
self.canvas.itemconfig(self.img, image=self.photo)
# From Here I will not achieve my goal
def __init__(self):
self.root.after(val1, self.change_photo1)
def change_photo1(self):
filename = "image1.png"
image = Image.open(filename)
self.photo = ImageTk.PhotoImage(image)
self.canvas.itemconfig(self.img, image=self.photo)
if __name__ == "__main__":
gui = myGUI()
You need to call .after() inside change_photo() function. As you want to cycle the images, suggest to use itertools.cycle() as below:
from tkinter import *
from PIL import ImageTk
from itertools import cycle
class myGUI(object):
def __init__(self):
self.root = Tk()
self.canvas = Canvas(width=800, height=800, bg='white')
self.canvas.pack()
self.val = 1000
filenames = ("image1.png", "image2.png")
self.images = cycle(filenames)
self.photo = ImageTk.PhotoImage(file=next(self.images))
self.img = self.canvas.create_image(250, 250, image=self.photo)
self.root.after(self.val, self.change_photo)
self.root.mainloop()
def change_photo(self):
self.photo = ImageTk.PhotoImage(file=next(self.images))
self.canvas.itemconfig(self.img, image=self.photo)
self.root.after(self.val, self.change_photo)
if __name__ == "__main__":
gui = myGUI()
Example without using cycle:
from tkinter import *
from PIL import ImageTk
class myGUI(object):
def __init__(self):
self.root = Tk()
self.canvas = Canvas(width=800, height=800, bg='orange')
self.canvas.pack()
self.val = 1000
self.images = ("image1.png", "image2.png")
self.img = self.canvas.create_image(250, 250)
self.change_photo()
self.root.mainloop()
def change_photo(self, index=0):
if index < len(self.images):
self.photo = ImageTk.PhotoImage(file=self.images[index])
self.canvas.itemconfig(self.img, image=self.photo)
self.root.after(self.val, self.change_photo, index+1)
else:
print("No more image")
if __name__ == "__main__":
gui = myGUI()

Can I add multiple images as canvas items and rotate them simultaneously?

I am trying to rotate images using canvas items. I was successful in doing it with one image. But if I want to perform rotations on multiple canvas items how can I do that? Can someone help? Thanks in advance.
Here is my code:
import tkinter as tk
from PIL import ImageTk
from PIL import Image
import time
class SimpleApp(object):
def __init__(self, master, filename, **kwargs):
self.master = master
self.filename = filename
self.canvas = tk.Canvas(master, width=500, height=500)
self.canvas.pack()
self.update = self.draw().__next__
master.after(100, self.update)
def draw(self):
image = Image.open(self.filename)
angle = 0
while (angle<90):
tkimage = ImageTk.PhotoImage(image.rotate(angle))
canvas_obj = self.canvas.create_image(
250, 250, image=tkimage)
self.master.after_idle(self.update)
yield
angle += 5
time.sleep(0.1)
else
yield
root = tk.Tk()
app = SimpleApp(root, 'cat.jpg')
root.mainloop()

What is the function used to update frame image automatically in python?

I asked this question before and the previous one linked to another question but it didn't solve the problem.
I have a number of images, which are updated frequently in a file.
The names of images are on the same pattern (e.g: img1.jpg , img2.jpg ...)
I am programming a GUI on python tkinter to start from the first image and automatically update after 30 second.
after many tries, I have no idea how to achieve that because mainloop()function freezes the GUI and the problem is that I need them in one GUI.
Here is the code I used to open and resize images:
from PIL import Image, ImageTk
x=1
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack(fill=BOTH, expand=1)
load = Image.open("./images/img%s.jpg"%x)
load=load.resize((1350,800))
render = ImageTk.PhotoImage(load)
img = Label(self, image=render)
img.image = render
img.place(x=0, y=0)
root = Tk()
app = Window(root)
root.wm_title("Tkinter window")
root.geometry("1350x800")
root.mainloop()
I tried to use label.after(3000,function) but no results came up so I deleted it from the code.
Is there any way to solve this problem?
Thanks in advance
Too big for the comments, But this is a working version of your code:
from tkinter import *
from PIL import Image, ImageTk
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack(fill=BOTH, expand=1)
self.x = 1 #assigning x to 1 to start with img1
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS) #loading first img
self.render = ImageTk.PhotoImage(self.load) #instantiating first img
self.img = Label(self, image=self.render) #labelizing it
self.img.image = self.render #keeping reference
self.img.pack() #packing it because place(x=0,y=0) will lead to overwriting of image
self.master.after(3000,self.update) #calling the function continoursly
def update(self):
self.x+=1 #increasing the x by 1 over each call to function
if self.x < 9:
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS)
self.render = ImageTk.PhotoImage(self.load)
self.img.config(image=self.render) #changing the image of label
self.master.after(3000,self.update)
root = Tk()
app = Window(root)
root.wm_title("Tkinter window")
root.geometry("1350x800")
root.mainloop()
Hope this helped, do let me know if any errors or doubts.
Cheers
This code solved my problem:
#from tkinter import *
from PIL import Image, ImageTk
import os
from tkinter import Frame,Label,BOTH,Tk
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack(fill=BOTH, expand=1)
self.x = 1
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS)
self.render = ImageTk.PhotoImage(self.load)
self.img = Label(self, image=self.render)
self.img.image = self.render
self.img.pack()
self.master.after(3000,self.update)
def update(self):
if self.x<len(os.listdir("./images/")):
self.x+=1
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS)
self.render = ImageTk.PhotoImage(self.load)
self.img.config(image=self.render)
self.master.after(3000,self.update)
else:
self.x=1
self.master.after(1,self.update)
root = Tk()
app = Window(root)
root.wm_title("Tkinter window")
root.geometry("1350x800")
root.mainloop()

How to update the image of a Tkinter Label widget?

I would like to be able to swap out an image on a Tkinter label, but I'm not sure how to do it, except for replacing the widget itself.
Currently, I can display an image like so:
import Tkinter as tk
import ImageTk
root = tk.Tk()
img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
root.mainloop()
However, when the user hits, say the ENTER key, I'd like to change the image.
import Tkinter as tk
import ImageTk
root = tk.Tk()
img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
def callback(e):
# change image
root.bind("<Return>", callback)
root.mainloop()
Is this possible?
The method label.configure does work in panel.configure(image=img).
What I forgot to do was include the panel.image=img, to prevent garbage collection from deleting the image.
The following is the new version:
import Tkinter as tk
import ImageTk
root = tk.Tk()
img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(root, image=img)
panel.pack(side="bottom", fill="both", expand="yes")
def callback(e):
img2 = ImageTk.PhotoImage(Image.open(path2))
panel.configure(image=img2)
panel.image = img2
root.bind("<Return>", callback)
root.mainloop()
The original code works because the image is stored in the global variable img.
Another option to do it.
Using object-oriented programming and with an interactive interface to update the image.
from Tkinter import *
import tkFileDialog
from tkFileDialog import askdirectory
from PIL import Image
class GUI(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
w,h = 650, 650
master.minsize(width=w, height=h)
master.maxsize(width=w, height=h)
self.pack()
self.file = Button(self, text='Browse', command=self.choose)
self.choose = Label(self, text="Choose file").pack()
self.image = PhotoImage(file='cualitativa.gif')
self.label = Label(image=self.image)
self.file.pack()
self.label.pack()
def choose(self):
ifile = tkFileDialog.askopenfile(parent=self,mode='rb',title='Choose a file')
path = ifile.name
self.image2 = PhotoImage(file=path)
self.label.configure(image=self.image2)
self.label.image=self.image2
root = Tk()
app = GUI(master=root)
app.mainloop()
root.destroy()
Replace 'cualitativa.jpg' for the default image you want to use.
Another solution that might be of help.
In my case, I had two tk.Tk() windows. When using ImageTk.PhotoImage(), the object defaults to setting its tk window to being the first one created. A simple fix to this is to pass the tk window that you want as such ImageTk.PhotoImage(img, master=your_window)
import tkinter as tk
from PIL import ImageTk, Image
if __name__ == '__main__':
main_window = tk.Tk()
second_window = tk.Tk()
main_canvas = Canvas(second_window)
main_canvas.pack()
filename = 'test.png'
img = Image.open(filename)
img = img.resize((300, 100), Image.ANTIALIAS)
logo = ImageTk.PhotoImage(img, master=second_window)
logo_label = Label(master=main_canvas, image=logo)
logo_label.image = logo
logo_label.pack()
main_window.mainloop()

Categories