I'm trying to implement simple image viewer, where you can choose from 2 pictures. I have one menubutton which offers these pictures. After choosing one of the images, the program creates 3 or 5 buttons. I would like to append to each of these buttons different images, so the first button would have one image and the second button would have another image and so on. I've created a function with for loop to create these buttons, but can't move on from that point. I can append one image to all of them, but can't do that one by one with different images.
Thanks for help
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
from functools import partial
from PIL import Image, ImageTk
class Halabala():
def __init__(self):
self.master = tk.Tk()
self.master.geometry("1100x700")
self.lists_labels = []
self.rbutton = tk.Menubutton(self.master, text = "Choose picture")
self.picks2 = tk.Menu(self.rbutton)
self.rbutton.config(menu=self.picks2)
self.picks2.add_command(label = "Spider", command = partial(self.create_labels,3))
self.picks2.add_command(label = "Sugar", command = partial(self.create_labels,5))
self.rbutton.config(width = 30, bg = "white", bd = 5, relief = tk.RAISED)
self.rbutton.place(x = 900, y = 30)
self.master.mainloop()
def create_labels(self, num):
self.picture = Image.open("blue.gif")
self.picture.thumbnail((130,130))
self.tkim = ImageTk.PhotoImage(self.picture)
for label in self.lists_labels:
label.destroy()
self.lists_labels=[]
for i in range(num):
but = tk.Button(self.master, image = self.tkim)
but.grid(row = i + 1, column = 0)
self.lists_labels.append(but)
myapp = Halabala()
This is the code relevant for your question:
class Halabala():
def __init__(self):
.............
self.pictures = ["pavuk1", "pavuk2", "pavuk3"]
self.lists_labels = []
self.lists_images = []
self.init_image_list()
............
def init_image_list(self):
for i in self.pictures:
picture = Image.open(i)
picture.thumbnail((130, 130))
self.lists_images.append(ImageTk.PhotoImage(picture))
def create_labels(self, num):
for label in self.lists_labels:
label.destroy()
self.lists_labels=[]
for i in range(num):
but = tk.Button(self.master, image = self.lists_images[i])
but.grid(row = i + 1, column = 0)
self.lists_labels.append(but)
Related
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
I have been working on a project where I use labels that I want to disappear on click, but it only deletes the last label that was created. Here's my code:
from tkinter import *
import tkinter
import random
from PIL import Image, ImageTk
from functools import partial
width1=1280
height1=720
canvas = tkinter.Canvas(width=width1,height=height1, bg = 'white')
canvas.pack()
def clicked(*args):
label.destroy()
def square():
global label
global img
sq_time = random.randrange(4000,6000)
x = random.randrange(100,width1-40,40)
y = random.randrange(40,height1-40,40)
label = Label(canvas, image = img)
label.place(x = x , y = y)
label.bind("<Button-1>",partial(clicked))
canvas.after(sq_time, square)
img = ImageTk.PhotoImage(Image.open('froggy.png'))
square()
mainloop()
froggy.png is a image that I have saved in the same folder as the code. Can someone tell me how do I delete the label that was clicked?
In tkinter event handler functions are automatically passed an event object argument that, among other things, has an attribute that identifies the widget that triggered them. This means you can use that instead of creating a partial to get the information needed.
from tkinter import *
import tkinter
import random
from PIL import Image, ImageTk
width1 = 1280
height1 = 720
canvas = tkinter.Canvas(width=width1, height=height1, bg='white')
canvas.pack()
def clicked(event):
event.widget.destroy()
def square():
global label
global img
sq_time = random.randrange(4000, 6000)
x = random.randrange(100, width1-40, 40)
y = random.randrange(40, height1-40, 40)
label = Label(canvas, image = img)
label.place(x=x, y=y)
label.bind("<Button-1>", clicked)
canvas.after(sq_time, square)
img = ImageTk.PhotoImage(Image.open('froggy.png'))
square()
mainloop()
def on_click():
label.after(1000, label.destroy)
Button(win, text="Delete", command=on_click).pack()
This question already has answers here:
Why does Tkinter image not show up if created in a function?
(5 answers)
Closed 2 years ago.
I am starting to program, in which I have to make a python graphical interface, in which by means of a button the jpg file is chosen and it is displayed in the interface, but I have had a problem, since the image is not displayed and in the terminal it does not detect any error and practically I go crazy here I leave the code
from PIL import Image, ImageTk
from tkinter import Tk, Frame, Button, Label, Text, filedialog, PhotoImage
class Application_BotonPath(Frame):
def __init__(self, master = None):
super().__init__(master, width = "1300", height = "950", bg = "old lace")
self.master = master
self.pack()
self.Panel()
self.widget()
def Panel(self):
self.frame_side = Frame(self, width = '300', height = '850', bg = 'sky blue').place(x = 20, y = 50)
self.frame_show = Frame(self, width = '900', height = '850').place(x = 360, y = 50)
def widget(self):
boton = Button(self.frame_side, text = "Abrir Imagen", command = self.cargar_imagen).place(x = 85, y = 60, width = 150, height = 30)
salida = Text(self.frame_side, state = "disable").place(x = 43, y = 110, width = 250, height = 700)
def cargar_imagen(self):
self.ruta_imagen = filedialog.askopenfilename(title = "Abrir", filetypes = [('Archivo png', '*.png'), ('Archivo jpeg', '*.jpg')])
load = Image.open(self.ruta_imagen)
imagen = ImageTk.PhotoImage(load)
label = Label(self.frame_show, image = imagen)
label.place(x=0, y=0)
root = Tk()
root.wm_title("Detector de Caracteres")
app = Application_BotonPath(root)
app.mainloop()
image
This is what I get, the gray box that is in the upper right I suppose it is the image, but it does not show it. please help
Welcome to SO.
The image is created in a function, and when the function ends the reference to the image is garbage collected. Therefore the Label can not find any image.
You can save a reference to the image in the label object:
label = Label(self.frame_show, image = imagen)
label.image = imagen # Save reference to image
or you can make the reference an attribute of the instance:
self.imagen = ImageTk.PhotoImage(load)
label = Label(self.frame_show, image = self.imagen)
I am trying to update some buttons at the for loop in the end, which buttons I don't want to create individually.
I tried using:
While True:
root.update()
and the other type of update and also each one individually but no luck.
This is the code:
from tkinter import *
from tkinter.ttk import *
from PIL import Image
from functools import partial
import random
#define variables
#main_window_width = 500
#main_window_height = 500
#def functions
buttons_list = []
def InitButtons(n, k):
if k == 0:
k = n
for i in range(n):
InitButtons_column = i
if i//k > 0:
InitButtons_column = i%k
buttons_list.append(Label(main_window, image=button_img))
buttons_list[i].grid(row=(i//k), column=InitButtons_column)
def Hovering(e):
button_img = PhotoImage(file = '/home/klet/Desktop/projects/Python/GUI/button2.png')
buttons_list_button.config(image = button_img)
buttons_list_button.image = button_img
def Clicking(e):
button_img = PhotoImage(file = '/home/klet/Desktop/projects/Python/GUI/button3.png')
buttons_list_button.config(image = button_img)
buttons_list_button.image = button_img
def NotHovering(e):
button_img = PhotoImage(file = '/home/klet/Desktop/projects/Python/GUI/button1.png')
buttons_list_button.config(image = button_img)
buttons_list_button.image = button_img
def UpdatingButtons(n):
n.bind("<Enter>", Hovering)
n.bind("<Leave>", NotHovering)
n.bind("<Button-1>", Clicking)
n.bind("<ButtonRelease-1>", Hovering)
root = Tk()
button_img = PhotoImage(file = "/home/klet/Desktop/projects/Python/GUI/button1.png")
main_window = Frame(root)
main_window.place(relx=0.1, rely=0.1, relwidth=0.8, relheight=0.8)
InitButtons(10, 5)
#buttons_list_tmp1 = 0
#buttons_list_tmp1 += 1
#buttons_list_button =
#UpdatingButtons(buttons_list_tmp1)
#print(buttons_list_tmp1)
for i in range(len(buttons_list)):
buttons_list_button = buttons_list[i]
UpdatingButtons(buttons_list_button)
print(i)
root.mainloop()
The for loop above is only repeating once and i want it to be constantly updating, I also tried putting the whole code (within root and root.mainloop()) in a while loop but didnt work. I also searched some questions asked but they didnt seem to help.
I want to update the buttons(labels in this case) when I enter the button and when i click. Heres an example of what currently happening:
Link to vid
I made this account just to ask this question because I really dont like asking questions.
I'm new to tkinter and am running python 3.4.2 with Tk version 8.5.17 using IDLE 3.4.2 under Yosemite. This is a modified demo from Liang's book Introduction to Programming Using Python 3. I was expecting the following code to display four buttons:
from tkinter import *
class ButtonsDemo:
def __init__(self):
window = Tk()
window.title("Buttons Demo")
frame0 = Frame(window)
frame0.pack()
plusImage = PhotoImage(file = "image/plus.gif")
minusImage = PhotoImage(file = "image/minus.gif")
timesImage = PhotoImage(file = "image/times.gif")
divideImage = PhotoImage(file = "image/divide.gif")
Button(frame0, image = plusImage, command =
self.add).grid(row = 1, column = 1, sticky = W)
Button(frame0, image = minusImage, command =
self.subtract).grid(row = 1, column =2)
Button(frame0, image = timesImage, command =
self.multiply).grid(row = 1, column = 3)
Button(frame0, image = divideImage, command =
self.divide).grid(row = 1, column = 4)
window.mainloop()
def add(self):
print("add pressed")
def subtract(self):
print("subtract pressed")
def multiply(self):
print("multiply pressed")
def divide(self):
print("divide pressed")
ButtonsDemo()
When I run the code, only the first three buttons are displayed. The button with divideImage on it does not appear.
If I click where the divide button should be, I do get the message "divide pressed". It's as if the button is there, but it's invisible.
I see the same behavior running the program from the command line
instead of from IDLE.
There's nothing wrong with the gif. If I use divide.gif for plusImage, I can see divide.gif in the first button position. Also, when I put text = "Divide" on the divide button instead of image = DivideImage, the button becomes visible.
Why is the divide button invisible when I use an image? How can I fix it?
EDIT: Here's the code with everything moved to the main program. I think this should have fixed a garbage collection problem if there were one. Is this correct?
from tkinter import *
def add():
print("add pressed")
def subtract():
print("subtract pressed")
def multiply():
print("multiply pressed")
def divide():
print("divide pressed")
window = Tk()
window.title("Buttons Demo")
frame0 = Frame(window)
frame0.pack()
plusImage = PhotoImage(file = "image/plus.gif")
minusImage = PhotoImage(file = "image/minus.gif")
timesImage = PhotoImage(file = "image/times.gif")
divideImage = PhotoImage(file = "image/divide.gif")
Button(frame0, image = plusImage, command =
add).grid(row = 0, column = 0, sticky = W)
Button(frame0, image = minusImage, command =
subtract).grid(row = 0, column = 1)
Button(frame0, image = timesImage, command =
multiply).grid(row = 0, column = 2)
Button(frame0, image = divideImage, command =
divide).grid(row = 0, column = 3)
window.mainloop()