I'm trying to figure out how to allow users to upload images, I'm starting easy with something I know tkinter can handle with no coercion, gif files. I've figures a bit out, but I'm having issues getting the image to actually SHOW.

from tkinter import *
from tkinter.filedialog import askopenfilename

root=Tk()
def get_image():
    file_name=askopenfilename(filetypes=[('GIF FILES', '*.gif')])
    print(file_name)
    the=PhotoImage(file=file_name)
    show(the)
def show(imaj):
    Show=Toplevel()
    Show.grid()
    the_image=Button(Show,image=imaj)
    the_image.grid()
    
root.upbutn=Button(root,text='upload an image',command=get_image)
root.upbutn.grid()
root.grid()
root.mainloop()

Recommended Answers

All 3 Replies

Probably problem with garbage collected image, if you do not do OO, you must have clear loop of main action in main code/single function.

(The way you chain functions by calling show at end of get_image is uggly, better to have only one function)

I found it easier to change my earlier thread OO answer:

try:
    import Tkinter as tk
except ImportError:
    import tkinter as tk
    from tkinter.filedialog import askopenfilename
    
class Uploader(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.root = tk.Canvas()
        self.root.grid()
        tk.Button(self.root, text='Upload an image',
                command=self.get_image).grid()
        tk.Label(text='Click preview picture to upload').grid()

    def get_image(self):
        preview = tk.Toplevel()
        file_name=askopenfilename(filetypes=[('GIF FILES', '*.gif')])
       
        self.image = tk.PhotoImage(file=file_name)
        self.upload = tk.Button(preview, image=self.image, command=self.upload)
        self.upload.grid()

    def upload(self):
        self.title('Uploading')
        
app = Uploader()
app.mainloop()

So can I not add a new widget onto a window that's already up? Only change an existing one?

You can but you must take care that reference exist for the widgets here is Vegaseats example of toggle button with these warnings: http://www.daniweb.com/software-development/python/threads/191210/1512550#post1512550

Could be adapted to multiple previews of image. Notice that button does not need to be declared global in toggle_image, but it is defined in main code. Usually it is bad idea to combine creating widgets and showing info, as you end up creating zillion widgets instead of one.

Try to have patience, I get myself it mixed up!

P.S. I do have my shorter and without magic string version of the toggle_image as shown in following code adapted for askopenfilename.
What it means, is that you must use the global if you create the PhotoImage in function (or class)

# create Tkinter image objects and display them ...
# create all image objects in __main__ to be persistent
# Note: if you create the image object and tie it to a
# function scope variable, then when the function is done
# the image will be garbage collected

try:
    # Python2
    import Tkinter as tk
    from tkFileDialog import askopenfilename
except ImportError:
    # Python3
    import tkinter as tk
    from tkinter.filedialog import askopenfilename

def show_image(event):
    global im
    im = tk.PhotoImage(file=askopenfilename(filetypes=[('GIF FILES', '*.gif')]))
    button['image'] = im

root = tk.Tk()
root.title("Click the image button")

# pick images you have in the working directory
# or give full path

# create a button to display the image
button = tk.Button(root, relief='raised', bd=10)
button.grid(row=1, column=1, padx=100, pady=10)
# bind left mouse click
button.bind('<Button-1>', show_image)  

root.mainloop()

Or as function is object:

def show_image(event):
    show_image.im = tk.PhotoImage(file=askopenfilename(filetypes=[('GIF FILES', '*.gif')]))
    button['image'] = show_image.im

Here the class code again with withdrawing during download Toplevel window:

try:
    import Tkinter as tk
    from tkFileDialog import askopenfilename
except ImportError:
    import tkinter as tk
    from tkinter.filedialog import askopenfilename
    
class Uploader(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.root = tk.Canvas()
        self.root.grid()
        tk.Button(self.root, text='Upload an image',
                command=self.get_image).grid()
        tk.Label(text='Click preview picture to upload').grid()
        self.preview = tk.Toplevel()
        self.preview.withdraw()
        self.upload = tk.Button(self.preview, command=self.upload)
        self.upload.grid()

    def get_image(self):
        file_name=askopenfilename(filetypes=[('GIF FILES', '*.gif')])       
        self.preview.deiconify()
        self.image= tk.PhotoImage(file=file_name) # critical save
        self.upload['image'] = self.image

    def upload(self):
        self.upload['command'] = None
        self.preview.withdraw()
        print('withdrawing and uploading')
        self.title('Uploading')
        
app = Uploader()
app.mainloop()
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.