I encountered a problem as I tried to fill a tkinter grid with a loop
i=0
for category in categories:
self.image = PhotoImage(file=category[2]+".png")
imageLabel = Label(master, image=self.image)
imageLabel.grid(row=0, column=i)
i = i + 1
With this code I try to create a row with different pictures side by side.
But it shows only the last image which is in the categories array (this array was filled by a SQL-execute btw).
After a few researches I found out, that it seems that python overwrites the reference of the picture on each iteration.
So I tried to change the code and save the references in a array:
folderPictures = []
i = 0
for category in categories:
self.image = PhotoImage(file=category[2]+".png")
imageLabel = Label(master, image=self.image)
folderPictures.append(imageLabel)
for pictures in folderPictures:
pictures.grid(row=0, column=i)
i = +1
unfortunately this doesn't work either. What do I do wrong?
Thanks and best regards
Franz
Instead of overwriting self.image each time, keep a separate reference for each image. For instance, you could make self.image into an array (self.images[0,1,...]) and keep each image in a different slot.
Load images first and make a list of them, then put in label.
images=[]
for category in categories:
images.append(PhotoImage(file=category[2]+".png"))
for index,img in enumerate(images):
Label(master,image=img).grid(row=0,column=index)
I saved the reference of the label instead of the ref of the picture.
self.image = []
for category in categories:
self.image.append(PhotoImage(file=category[2]+".png"))
imageLabel = Label(master, image=self.image[i])
imageLabel.grid(row=0, column=i)
i = i + 1
this works now!
Related
I am trying to improve my code to make it more userfriendly using GUI. I have a simple code to select set of images and crop it. I have a code to that selects the folder directory containing images, now I want something similar using tkinter to select pixel range to crop images in the following code.
#Read images
root= tk.Tk()
var = tk.StringVar()
label = tk.Label( root, textvariable=var,relief = tk.RAISED,fg='peru',bg='white',font=('Helvetica',18,'bold'))
var.set("Choose image location")
label.pack()
img_list =[i for i in glob.glob(filedialog.askdirectory() +'/*.tif')] # choose the folder containing image list
images_read = np.array([(plt.imread(fname)) for fname in img_list]).astype(np.int32)
#crop_size=input()
images_crp =np.array([i[524:1024,275:775] for i in images_flp]) #crop the images to requried shape (or Pixel_row X pixel_column)
Here, I have manually selected pixel range, but I would love to have a pop up window asking me to enter the pixel range using GUI. Help in this regard is appreciated.
Thanks
I am trying to add a bunch of images from a folder using a for loop using tkinter and I want each image to be placed on row = 20, but change columns for each image. So , I will want an image on (20,10), (20,11), (20,12) and so on. This works when I use grid for individual images, but I cant get it to work in a for loop where I want to add 5 images. Instead my first image starts appearing in the first row and first column but follows the column increments. Please let me know what I am doing wrong here? Thanks!
game = tkinter.Tk()
game.geometry("500x500")
images = random.sample(deck, 5)
path = "C:/Users/jhbhb/Documents/"
MAX_ROWS = 4
current_row = 20
current_column = 10
for file in images:
im = Image.open(f"{path}/{file}.png")
photo = ImageTk.PhotoImage(im)
label = tkinter.Label(image=photo)
label.image = photo
label.grid(row=current_row, column=current_column)
current_column += 1
game.mainloop()
I'm trying to make a program to display a single color, fullscreen. The idea is to use it on a large screen to create environment in the room, the screen changing from color to color after certain time.
Displaying the color fullscreen is not a problem but how can I change said color smoothly?
For the fullscreen display I've used a Tkinter window with the same size as the screen: imagesprite = canvas.create_image(w/2, h/2, image=image) where image is a certain color. But to change the color I need to destroy the window using root.after(2000, root.destroy) and then create a new one. This is not smooth as the desktop can be seen for a brief moment.
How can I change the image displayed inside a Tkinter window on the go, or, how can I close one window and open another one smoothly?
An option you have is instead of using an image is to have a background for the Canvas object. Here is the minimum code to have a single colour background.
from tkinter import Tk, Canvas
root = Tk()
root.attributes("-fullscreen",True)#Makes the window fullscreen
canvas = Canvas(root, width=root.winfo_width(),height=root.winfo_height(), background="red") #Makes a canvas with a red coloured background
#The width and height of the Canvas are taken from the root object
canvas.pack()
root.mainloop()
From here, instead of deleting the window constantly, it is possible to just change the attributes of Tkinter widgets. This is done using the config method.
canvas.config(background="green")
A great thing about tkinter is that you can give it a hex code for the colour and it will draw use that. It needs to be in a string formatted like this:
"#RRGGBB" where each group is a hexadecimal number from 0 to FF.
With this in mind, you can increase the hexadecimal number each frame or however many frames you want between two colours. To have a good transition, you may want to use Hue,Saturation,Value (HSV) colours, and only change the Hue value.
You can store the HSV in a list:
hsv = [0,0.7,0.7]
To convert, you first want to convert to 0 to 255 RGB and then to Hexadecimal.
import colorsys
rgb = colorsys.hsv_to_rgb(*hsv) #Uses list unpacking to give it as arguments
Next, you use the rgb and turn it into Hexcode form.
def getHexCode(rgb):
r = hex(int(rgb[0]*255))[2:] #converts to hexadecimal
#With the hex() function, it returns a number in "0xFE" format (0x representing hex).
#To ignore this, we can take the substring using [2:]
if len(r) < 2: #If the value is a 1-digit number, then we want to add a zero at the front for hexcode form
r = "0"+r
g = hex(int(rgb[1]*255))[2:]
if len(g) < 2:
g = "0"+g
b = hex(int(rgb[2]*255))[2:]
if len(b) < 2:
b = "0"+b
return "#" + r + g + b
Finally, we actually call the change method.
changeSpeed = 200
def changeColor():
rgb = colorsys.hsv_to_rgb(*hsv)
hexCode = getHexCode(rgb)
canvas.config(background = hexCode)
hsv[0]+=0.01
root.after(changeSpeed,changeColor)
root.after(changeSpeed, changeColor)
(EDITED)
Two things that were previously a problem were the root.winfo_width() and root.winfo_height(), as well as the fullscreen giving a border.
To solve the first problem, we have to somehow update the root object, since by default it's 1x1. What we can do for that is make the Canvas object and then update it. It looks like this:
canvas = Canvas(root, width=100,height=100, background="white",highlightthickness=0) #Makes a canvas with a white coloured background
canvas.pack()
canvas.update()
canvas.config(width = root.winfo_width(), height = root.winfo_height())
The second problem is also solved by making the canvas object with a specific attribute, highlightthickness=0. If you notice, the canvas object initialization is now:
canvas = Canvas(root, width=100,height=100, background="white",highlightthickness=0)
Another thing that I thought was useful is if a button closes the program. I bound the "Escape" key to the closing using the following:
def quit(event):
root.destroy()
root.bind("<Escape>", quit)
As a full program, it looks like this:
import colorsys
from tkinter import Tk, Canvas
hsv = [0,1,0.8]
changeSpeed = 200
root = Tk()
root.attributes("-fullscreen",True)
canvas = Canvas(root, width=100,height=100, background="white",highlightthickness=0) #Makes a canvas with a white coloured background
canvas.pack()
canvas.update()
canvas.config(width = root.winfo_width(), height = root.winfo_height())
def getHexCode(rgb):
r = hex(int(rgb[0]*255))[2:]
if len(r) < 2:
r = "0"+r
g = hex(int(rgb[1]*255))[2:]
if len(g) < 2:
g = "0"+g
b = hex(int(rgb[2]*255))[2:]
if len(b) < 2:
b = "0"+b
return "#" + r + g + b
def changeColor():
rgb = colorsys.hsv_to_rgb(*hsv)
hexCode = getHexCode(rgb)
canvas.config(background = hexCode)
hsv[0]+=0.01
root.after(changeSpeed,changeColor)
def quit(event):
root.destroy()
root.after(changeSpeed, changeColor)
root.bind("<Escape>", quit)
root.mainloop()
Some variables you can change in this is the changeSpeed, the original hsv list, and the 0.01 that is added to the hue each increase
I was trying out something new on Tkinter (I am still a newbie), but it keeps failing...maybe someone could help out?
I wanted to create a window with several Frames, so that I can open and close them and show that way different content. However I am already stuck with not being able to "place" the, in this case a button, to the frame. Instead I get a blank frame with nothing inside...
The reason I want to use the place manager is so that I can easily choose the x and y coordinates. I don't want to create empty columns just in order to get a button appear in the middle of the screen.
Here the code:
from Tkinter import *
root = Tk()
root.title("Tkinter window")
root.geometry("800x600")
StartFrame = Frame(root)
StartFrame.pack()
Button1 = Button(StartFrame, command = StartTkinter, text = "Start", bg = "white", fg = "black", height = 2, width = 15)
Button1.place(x=0, y=50)
root.mainloop()
The problem is that you forgot to specify the dimensions of the frame. So, by default, it is created to be just 1 pixel high and 1 pixel wide. This means that its contents will not be visible on the window.
To fix the problem, you can either set exact values for these dimensions when you create the frame:
StartFrame = Frame(root, height=600, width=800)
or you can do:
StartFrame.pack(expand=True, fill="both")
to have the frame fill all available space.
Hi all I have to do a little script in Python.
In this script I have a variable (that represents a coordinate) that is continuously updated to a new value.
So I have to draw a red point over a image and update the point position every time the variable that contains the coordinate is updated.
I tried to explain what I need doing something like this but obviously it doesn't works:
import Tkinter, Image, ImageDraw, ImageTk
i=0
root = Tkinter.Tk()
im = Image.open("img.jpg")
root.geometry("%dx%d" % (im.size[0], im.size[1]))
while True:
draw = ImageDraw.Draw(im)
draw.ellipse((i, 0, 10, 10), fill=(255, 0, 0))
pi = ImageTk.PhotoImage(im)
label = Tkinter.Label(root, image=pi)
label.place(x=0, y=0, width=im.size[0], height=im.size[1])
i+=1
del draw
someone may help me please? thanks very much!
Your on the right track using a PhotoImage in a Label but instead of creating a new Label each loop, just create the label once and update its position in the loop.