Python-Tkinter, for-loop to create pictured button - python

I'm still quiet new to programming, so maybe my question in pretty easy or even stupid. As said in the title I'm trying to programm a for loop, which creates a pictured button widget for each picuture in a certain folder. This is what I have so far:
import tkinter
from tkinter import ttk
from tkinter import PhotoImage
import os
root = tkinter.Tk()
list_files = os.listdir(".")
for file in list_files:
if file.endswith(".gif"):
drink = PhotoImage(file)
print(drink)
b1 = ttk.Button(image=drink, text="Hello", compound="right").pack()
l1 = ttk.Label(image=drink).pack()
root.mainloop()
Now what I get is two widgets, one label displaying nothing and a button displaying Hello. In the shell it says drink1.gif, which is correct, because that's the only gif file in my standard python folder...
what have I done wrong?

Use PhotoImage(file='path_to_file') to create image from path.
When PhotoImage object is garbage-collected by Python, the label is cleared. You must save reference to drink object somewhere: l1.image = drink:
http://effbot.org/pyfaq/why-do-my-tkinter-images-not-appear.htm
widget.pack() method return nothing.
import tkinter
from tkinter import ttk
from tkinter import PhotoImage
import os
root = tkinter.Tk()
list_files = os.listdir(".")
for path in list_files:
if path.endswith(".gif"):
drink = PhotoImage(file=path)
b1 = ttk.Button(root, image=drink, text="Hello", compound="right")
b1.pack()
l1 = ttk.Label(root, image=drink)
l1.image = drink
l1.pack()
root.mainloop()

PhotoImage(file) creates an image and gives it the name "drink1.gif", which is returned. If you actually want to load the file into the image, you need PhotoImage(file = file).

I believe you are supposed to run self.pack, according to the Zetcode tutorial.

Related

I am trying to make a exe similar to windows file explorer with python using os.path and tkinter

from PIL import Image
from tkinter import filedialog as fd
import os
import ctypes
import tkinter
class ImageList:
path = ""
dir = ""
top = tkinter.Tk()
canvas = tkinter.Canvas()
canvas.pack()
def __init__(self):
self.path = os.path.expanduser('~/')
def findImage(self):
image = Image.open(self.dir, "rb")
image.show()
def fileExplorer(self, path):
self.canvas.destroy()
self.canvas = tkinter.Canvas()
self.canvas.pack()
obj = os.scandir(path)
for entry in obj:
if entry.is_dir():
#self.path = os.path.abspath(self.path)
b = tkinter.Button(self.canvas, text=entry.name, command=lambda: self.fileExplorer(os.path.abspath(entry).replace('//', '\\')))
b.pack()
elif entry.is_file():
b = tkinter.Button(self.canvas, text=entry.name, command=lambda: print(entry.name))
b.pack()
else:
obj.close()
self.top.mainloop()
As shown in the code above, I am trying to make exe that shows the subdirs and files after C:\Users using buttons in tkinter and repeating it by using recursion.
The first error is that in "os.path.abspath(entry).replace('//', '\')" shows path in a format of "C://Users" and I intended to change that to "C:\Users" using the replace method. However, using "\" doesn't replace "//" and still shows as the original format.
The second error is that after running the code, when I press any button it acts as if I pressed the last button in the tkinter window, meaning that it recursively called the last subdir or the file below "C:\Users".
I'm just getting used to python and this is my first time using stackoverflow. I'm sorry if I did not abide by any of the rules in stackoverflow. Thanks for anyone helping.

How show vertical list on Tkinter

I am starting in tkinter and I have generated a list with the elements that are in a certain folder and I need to show them in the interface.
I put it in a label but it shows me the elements horizontally and I need it to show one below the other, is there a way to do this?
from tkinter import *
from os import listdir
raiz = Tk()
ruta = './imagenes'
fotos = Frame()
fotos.place(x=0,y=0)
fotos.config(bd=10,relief="groove",width="500", height="200")
fotografias = StringVar()
lblfotos = Entry(fotos, textvariable=fotografias)
lblfotos.config(width="75")
lblfotos.place(x=10,y=0)
fotografias.set(listdir(ruta))
raiz.mainloop()
https://i.stack.imgur.com/JaEek.png
[1]: P.S. The original idea is that the files in the folder are displayed in the interface and you can interact with them, such as opening or deleting, but I didn't find how, could that be done in tkinter? or maybe in another library?. Thank you for your answer.
An Entry widget can only hold single line of string. Use Listbox widget instead. Also avoid using wildcard import and it is better to use pack() or grid() instead of place() in normal case.
Below is an example based on your code:
import tkinter as tk
from os import listdir
raiz = tk.Tk()
ruta = './imagenes'
fotos = tk.Frame(raiz, bd=10, relief="groove")
fotos.pack(fill="both", expand=1)
lblfotos = tk.Listbox(fotos, width=30, height=20)
lblfotos.pack(fill="both", expand=1)
for imgfile in listdir(ruta):
lblfotos.insert("end", imgfile)
raiz.mainloop()

how to run multiple lines with variables in tkinter

Using Tkinter, os, and, pygame modules im finding all files and making a button to play the file because it will be an mp3 file but every time the function overwrites itself so I want to be able to write a function but inside the command parameter in the Tkinter button so it isn't a function but it operates like one
the code i already have:
import os
import pygame
import tkinter as tk
dir_path = os.path.dirname(os.path.realpath(__file__))
d = dir_path+"\\mp3s"
root = tk.Tk()
frame=tk.Frame(root)
root.title("title")
frame.pack()
for path in os.listdir(d):
full_path = os.path.join(d, path)
full_name = os.path.basename(full_path)
def playsong():
pygame.init()
pygame.mixer.music.load(full_path)
pygame.mixer.music.play()
play = tk.Button(frame,
text=full_name,
command=playsong)
play.pack()
root.mainloop()
the function inside the for statement is getting overwritten and I knew this would happen but I was still going to try this works for one file but I want a bunch of different files inside of the folder named "mp3s"
the rest of the code works this is the part that does not
def playsong():
pygame.init()
pygame.mixer.music.load(full_path)
pygame.mixer.music.play(
I wanted to run multiple functions in a line more specifically than lines and I figured out how to do this using lambda
import tkinter as tk
root = tk.Tk()
frame=tk.frame(root)
button = tk.Button(frame, text="name", command= lambda: [func1(), func2()])

Tkinter not changing image on button press

I have loaded an image to tkinter label and that image is diplayed in that label.When i press the button i need to change that image.When the button is pressed older image is gone but the new image is not displayed
My code is
import Tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
def change_pic(labelname):
photo1 = ImageTk.PhotoImage(Image.open("demo.jpg"))
labelname.configure(image=photo1)
print "updated"
vlabel=tk.Label(root)
photo = ImageTk.PhotoImage(Image.open('cardframe.jpg'))
vlabel.configure(image=photo)
vlabel.pack()
b2=tk.Button(root,text="Capture",command=lambda:change_pic(vlabel))
b2.pack()
root.mainloop()
In def change_pic(labelname), you need to add labelname.photo = photo1 to make sure photo1 not being garbage collected.
def change_pic(labelname):
photo1 = ImageTk.PhotoImage(Image.open("demo.jpg"))
labelname.configure(image=photo1)
labelname.photo = photo1
print "updated"
P.S. Looks like both labelname.photo = photo1 and labelname.image = photo1 work.
Check this out for more details: http://effbot.org/tkinterbook/label.htm
You can use the label to display PhotoImage and BitmapImage objects.
When doing this, make sure you keep a reference to the image object,
to prevent it from being garbage collected by Python’s memory
allocator. You can use a global variable or an instance attribute, or
easier, just add an attribute to the widget instance.
The following edits were made:
I have organised your code layout and simplified its
syntax where possible. These are to make your code easier to read.
Commonly we make the PIL objects a subset/children of tk.
So long it is a part of root (i.e. it is a child of the root
or any of its child widgets), your PIL objects will work.
Your working code is shown below:
import Tkinter as tk
from PIL import Image, ImageTk
def change_pic():
vlabel.configure(image=root.photo1)
print "updated"
root = tk.Tk()
photo = 'cardframe.jpg'
photo1 = "demo.jpg"
root.photo = ImageTk.PhotoImage(Image.open(photo))
root.photo1 = ImageTk.PhotoImage(Image.open(photo1))
vlabel=tk.Label(root,image=root.photo)
vlabel.pack()
b2=tk.Button(root,text="Capture",command=change_pic)
b2.pack()
root.mainloop()
I got it working with one more line of code:
import tkinter as tk # I am using python 3 on windows so the tkinter is lowercased
from PIL import Image, ImageTk
root = tk.Tk()
def change_pic(labelname):
global photo1 # This is the only new line you need, I believe
photo1 = ImageTk.PhotoImage(Image.open("demo.jpg"))
labelname.configure(image=photo1)
print("updated") # Again I'm using python 3 on windows so syntax may differ.
root.update() # You don't need this statement in this case, but it never hurts
vlabel=tk.Label(root)
photo = ImageTk.PhotoImage(Image.open('cardframe.jpg'))
vlabel.configure(image=photo)
vlabel.pack()
b2=tk.Button(root,text="Capture",command=lambda:change_pic(vlabel))
b2.pack()
root.mainloop()
I believe that the code changes the image locally, so the global statement will change it on the project scope.

Adding and removing image Tkinter / root

Below is my code. The code is from within a different program, so a button would be clicked
on another program and initiate this code.I have been struggling with this a while, in short i am trying to a) take an image, save it to a directory, b) display the image on canvas or root a long with a button named "refresh". When refresh is clicked then remove is called deleting the 'file' first taken, takes another picture and refreshes the canvas with the second picture taken and so on and on. I am not seeming to get it to work in this sequence and have used multiple examples etc etc. Can anyone assist please, is my design incorrect perhaps? I have ample other code but the code below details only one function calling global properties etc etc. I would appreciate an answer but also want to learn from the answer to understand what is being done wrong.
import os
import sys
import time
from VideoCapture import Device
impot Image
from PIL import ImageTk, Image
from Tkinter import *
import Tkinter
root = Tk()
root.wm_title("Camera Capture")
root.resizable(0,0)
root.geometry("600x400")
path = ('C:\Users\Public')
os.chdir(path)
def take_picture():
global root
global path
os.chdir(path)
cam = Device()
cam.saveSnapshot('pic.gif')
webcam_pic = Tkinter.PhotoImage(file='./pic.gif')
item = Label(root, anchor = W, image = webcam_pic)
item.pack()
button_take_picture = Button(root, text = "Take picture", command = take_picture(), bg
= 'blue')
button_take_picture.place(relx = .9, rely = .5, anchor = "center")
mainloop()
actually the command should be without this '()'
command =take_picture
button_take_picture = Button(root, text = "Take picture", command = take_picture, bg=blue')

Categories

Resources