Integrate a picture with Tkinter - python

I am a begginner in Python. I'm trying to display a picture with Tkinter in a window, but I don't success...
This is a piece of my code :
import serial
import time
import sys
import os
from Tkinter import *
root = Tk()
root.title("Title")
root.geometry("500x500")
[...]
class Application(Frame):
def __init__(self, master):
""" Initialize the Frame"""
Frame.__init__(self,master)
self.create_widgets()
def create_widgets(self):
[...]
try:
self.photo=PhotoImage('buttongreen.gif')
pic = Canvas(self,width =256, height = 256, bg ='blue')
pic.grid(row=6, columnspan=2,column=0,padx = 10, pady =10)
pic.create_image(256,256, image=self.photo)
"""self.panel = Label(self, image = photo)
self.panel.pack(side = "bottom", fill = "both", expand = "yes")"""
except:
print "Unable to load image"
[...]
app = Application(root)
app.grid()
root.mainloop()
The problem is that the canvas is displaying only the background, not the picture, can you tell me what is wrong please?
Note : The buttongreen.gif is in the same folder that my .py

self.photo=PhotoImage('buttongreen.gif')
Should be...
self.photo=PhotoImage(file = 'buttongreen.gif')

You need file= in self.photo = PhotoImage(file='buttongreen.gif')
Working example
from Tkinter import *
root = Tk()
root.title("Title")
root.geometry("500x500")
class Application(Frame):
def __init__(self, master):
""" Initialize the Frame"""
Frame.__init__(self, master)
self.create_widgets()
self.grid()
def create_widgets(self):
try:
self.photo = PhotoImage(file='buttongreen.gif') # file =
pic = Canvas(self, width=256, height=256, bg='blue')
pic.grid(row=6, columnspan=2, column=0, padx=10, pady=10)
pic.create_image(256, 256, image=self.photo)
except:
print "Unable to load image"
app = Application(root)
root.mainloop()

Related

python tkinter resize background image according to window size

The background image is not adjusting automatically to the window size in python using tkinter
Following is the code snippet
self.background_image = tk.PhotoImage(file="background.png")
self.background_label = tk.Label(self.master, image=self.background_image)
self.background_label.pack(fill='both', expand=True)
The image should be in background of the behind all the GUI components.
The code is actually a part of a python GUI but the image is not resizing automatically according to the window size previously i tried this but it was to add a static image but in need the image to fit automatically to the window size
This is the kinda the complete code
import tkinter as tk
from tkinter import ttk
class MongoDBGUI:
def __init__(self, master):
self.master = master
self.master.title("MongoDB Cloud Search and Display")
self.master.geometry("1000x400")
self.background_image = tk.PhotoImage(file="background.png")
self.background_label = tk.Label(self.master, image=self.background_image)
self.background_label.place(relwidth=1, relheight=1)
self.label = tk.Label(self.master, text="Enter search criteria:")
self.label.pack()
self.entry = tk.Entry(self.master)
self.entry.pack()
self.search_button = tk.Button(self.master, text="Search", command=self.search)
self.search_button.pack()
self.tree = ttk.Treeview(self.master)
self.tree.pack()
self.tree["columns"] = ("transcript", "audio_file", "audio")
self.tree.column("transcript", width=400, anchor="center")
self.tree.column("audio_file", width=150, anchor="center")
self.tree.column("audio", width=50, anchor="center")
self.tree.heading("transcript", text="Transcript")
self.tree.heading("audio_file", text="Audio File Number")
self.tree.heading("audio", text="Audio")
This is an not so easy task. If you want to have a resizable image then you need to use the PIL package. Additionally a further method is needed to rezise the image dynamically. Ofcourse if the window size always stays the same the solution could be implemented like :
self.image = self.img_copy.resize((new_width, new_height))
#resize is included in the PIL.Image module
To dynamically resize the background Picture the code could look like this:
import tkinter as tk
from tkinter import ttk
from scipy import misc,datasets
from PIL import Image, ImageTk
class MongoDBGUI:
def __init__(self, master):
self.master = master
self.master.title("MongoDB Cloud Search and Display")
self.master.geometry("1000x400")
self.image = Image.open("background.png")
self.background_image = ImageTk.PhotoImage(self.image)
self.img_copy = self.image.copy()
self.background_label = tk.Label(self.master, image=self.background_image)
self.background_label.place(relwidth=1, relheight=1)
self.label = tk.Label(self.master, text="Enter search criteria:")
self.label.pack()
self.entry = tk.Entry(self.master)
self.entry.pack()
self.search_button = tk.Button(self.master, text="Search", command=self.search)
self.search_button.pack()
self.tree = ttk.Treeview(self.master)
self.tree.pack()
self.tree["columns"] = ("transcript", "audio_file", "audio")
self.tree.column("transcript", width=400, anchor="center")
self.tree.column("audio_file", width=150, anchor="center")
self.tree.column("audio", width=50, anchor="center")
self.tree.heading("transcript", text="Transcript")
self.tree.heading("audio_file", text="Audio File Number")
self.tree.heading("audio", text="Audio")
self.background_label.bind('<Configure>', self._resize_image)
def _resize_image(self,event):
new_width = event.width
new_height = event.height
self.image = self.img_copy.resize((new_width, new_height))
self.background_image = ImageTk.PhotoImage(self.image)
self.background_label.configure(image = self.background_image)
master=tk.Tk()
test=MongoDBGUI(master)
master.mainloop()

TKinter background resizer + buttons/labels

I'm trying to setup tkinter gui screen with wallpaper on the background when the bg image fit the resize of the screen, i have took code from here..but the problem is when i'm trying to put buttons on it or another labels, the wallpaper still stay on the top and i can't see them.
Here the code:
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
root.title("Title")
root.geometry("800x600")
class Example(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.configure(background="black")
self.grid(sticky=N+S+E+W)
self.image = Image.open("bg.jpg")
self.img_copy= self.image.copy()
self.background_image = ImageTk.PhotoImage(self.image)
self.background = Label(self, image=self.background_image)
self.background.grid(row =0, column =0,sticky="nsew")
self.background.grid_rowconfigure(0, weight=1)
self.background.grid_columnconfigure(0, weight=1)
self.master = master
self.master.bind('<Configure>', self._resize_image)
# create a button
self.button= Button(root, text="EXIT", width=4).grid(row=3, column=1, sticky=N+S+E+W)
def _resize_image(self,event):
new_width = self.master.winfo_width()
new_height = self.master.winfo_height()
self.image = self.img_copy.resize((new_width, new_height))
self.background_image = ImageTk.PhotoImage(self.image)
self.background.configure(image = self.background_image)
e = Example(root)
e.grid(row =0, column =0,sticky="nsew")
e.grid_rowconfigure(0, weight=1)
e.grid_columnconfigure(0, weight=1)
root.mainloop()
You need to use place() to put the background image so that it does not interfere other widgets in the same parent.
Below is a simplified example based on your code:
from tkinter import *
from PIL import Image, ImageTk
class Example(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.configure(background="black")
self.image = Image.open("bg.jpg")
# label for the background image
self.background = Label(self)
self.background.place(x=0, y=0)
self.bind('<Configure>', self._resize_image)
# create a button
self.button = Button(self, text="EXIT", width=4)
self.button.grid(row=3, column=1, sticky=N+S+E+W, padx=50, pady=50)
def _resize_image(self,event):
if event.widget is self:
# resize background image to fit the frame size
image = self.image.resize((event.width, event.height))
self.background_image = ImageTk.PhotoImage(image)
self.background.configure(image=self.background_image)
root = Tk()
root.title("Title")
root.geometry("800x600")
e = Example(root)
e.pack(fill=BOTH, expand=1)
root.mainloop()

How to use 2nd Tkinter window to change image in 1st?

Quick summary: The green button is supposed to change when an image is selected, but it doesn't:
I have a Tkinter window-A with a button that when pressed will use a separate Python file to create a new window-B. Window-B has two buttons: new screen-snip or select image from folder. The method used for this is supposed to then change self.image_selected so that it can be used to update the button in window-A to have this new image.
I've tried both lines of code below, and neither are working. I'm not getting any errors either:
self.button.configure(image = img.image_selected) # first try
self.button['image'] = img.image_selected # second try
Here is my code (simplified for clarity):
import tkinter as tk
import get_image_or_snip
class ButtonImg:
def __init__(self, master):
self.newWindow = None
self.master = master
self.title = "My Minimum Reproducible Example"
self.fontA = ("arial", 20, "bold")
self.canvas = tk.Canvas(height = 5)
self.canvas.pack()
self.button = tk.Button(bg="#93d9cc", height = 5, text = "Select Image",
font = self.fontA, command = self.changeImage)
self.button.pack(fill="both")
def changeImage(self):
self.newWindow = tk.Toplevel(self.master)
img = get_image_or_snip.AcquireImage(self.newWindow)
self.button.configure(image = img.image_selected)
#self.button['image'] = img.image_selected
root = tk.Tk()
app = ButtonImg(root)
root.mainloop()
Here is the aforementioned get_image_or_snip.py code:
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk, Image
import snipping_tool
class AcquireImage:
def __init__(self, master):
self.master = master
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command =lambda: self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command=lambda: self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")
self.image_selected = None
self.master.mainloop()
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename()
load_img = Image.open(ret)
self.image_selected = ImageTk.PhotoImage(load_img)
if method == 2:
ret = snipping_tool.get_snip()
self.image_selected = ret
def main():
root = tk.Tk()
AcquireImage(root)
root.mainloop()
if __name__ == '__main__':
main()
If you add print() before and after get_image_or_snip.AcquireImage(self.newWindow) in changeImage() then you should see only first text because you run second mainloop() and it never ends this loop and never go back to changeImage() and never runs self.button.configure(image=img.image_selected)
You should use only one mainloop() and eventually use
root.wait_window(self.newWindow)
to wait until you close second window and then it will run self.button.configure(image=img.image_selected)
But there are other problems.
It removes image from memory memory when second windows is destroyed so you have to assign it to variable in first window.
Button use height in chars when you sent text but when you assign image then it use height in pixels and you have to change it from 5 to image.height()`
All code in one file
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk
class AcquireImage:
def __init__(self, master):
self.master = master
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")
self.image_selected = None
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename(initialdir='/home/user/images/')
if ret:
self.image_selected = ImageTk.PhotoImage(file=ret)
self.master.destroy()
elif method == 2:
self.image_selected = snipping_tool.get_snip()
class ButtonImg:
def __init__(self, master):
self.newWindow = None
self.master = master
self.title = "My Minimum Reproducible Example"
self.fontA = ("arial", 20, "bold")
self.canvas = tk.Canvas(height=5)
self.canvas.pack()
self.button = tk.Button(bg="#93d9cc", height=5, text="Select Image",
font=self.fontA, command=self.changeImage)
self.button.pack(fill="both")
def changeImage(self):
print('open second window')
self.newWindow = tk.Toplevel(self.master)
img = AcquireImage(self.newWindow)
self.master.wait_window(self.newWindow)
print('close second window')
if img.image_selected: # check if image was selected
self.image = img.image_selected
self.button.configure(image=self.image, height=self.image.height())
root = tk.Tk()
app = ButtonImg(root)
root.mainloop()
BTW: If you want to change image without closing second window then you should send first window (or button from first window) as argument to second window and change image in show_dialogs()
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk
class AcquireImage:
def __init__(self, master, first_window):
self.master = master
self.first_window = first_window
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font=self.fontA, command=lambda:self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")
self.image_selected = None
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename(initialdir='/home/user/images/')
if ret:
self.image_selected = ImageTk.PhotoImage(file=ret)
self.first_window.image = self.image_selected
self.first_window.button.configure(image=self.first_window.image, height=self.first_window.image.height())
elif method == 2:
self.image_selected = snipping_tool.get_snip()
class ButtonImg:
def __init__(self, master):
self.newWindow = None
self.master = master
self.title = "My Minimum Reproducible Example"
self.fontA = ("arial", 20, "bold")
self.canvas = tk.Canvas(height=5)
self.canvas.pack()
self.button = tk.Button(bg="#93d9cc", height=5, text="Select Image",
font=self.fontA, command=self.changeImage)
self.button.pack(fill="both")
def changeImage(self):
self.newWindow = tk.Toplevel(self.master)
img = AcquireImage(self.newWindow, self) # first window as `self` but you can send `self.button`
root = tk.Tk()
app = ButtonImg(root)
root.mainloop()
EDIT: Doc about creating Dialog Windows

How do I make the background in a tkinter window transparent?

How do I make this so the window background is transparent, but the image remains visible?
Here is my code;
from tkinter import Tk, Label, Button, Canvas
from PIL import ImageTk, Image
class MyFirstGUI:
def __init__(self, master):
self.canvas = Canvas(master, width = 300, height = 300)
self.canvas.pack()
self.image = ImageTk.PhotoImage(Image.open("Sprites/ph1.png"))
self.canvas.create_image(150, 150, image=self.image)
self.master = master
master.title("A simple GUI")
self.close_button = Button(master, text="Close", command=master.quit)
self.close_button.pack()
def greet(self):
print("Greetings!")
root = Tk()
root.geometry("+1630+775")
root.overrideredirect(1)
my_gui = MyFirstGUI(root)
root.mainloop()

tkinter & PIL: removing image

I'm trying to write simple app that would display poster of random movie after button is pressed.
Problem: I don't know how to remove one image before displaying next one (so they don't stack on each other, like here: ).
My shortened code:
from tkinter import *
from tkinter import ttk
import random
from PIL import ImageTk, Image
mlist = ['resized.jpg', 'cat.jpg']
class App(Frame):
def __init__(self, master):
ttk.Frame.__init__(self, master, padding='5')
self.grid(column=0, row=0, sticky=(N, W, E, S))
self.create_button()
self.name = ttk.Label()
self.image = ttk.Label()
def create_button(self):
self.button = ttk.Button(self,
text="Press me",
width=12,
command=lambda: self.display()
).grid(column=0, row=2, columnspan=2, pady=10, sticky=N)
def display(self):
self.name.destroy()
k = random.randrange(0, 2)
self.name = ttk.Label(self, font=(None, 16), text=mlist[k])
self.image = Image.open(mlist[k])
poster = ImageTk.PhotoImage(self.image)
display = ttk.Label(self, image=poster)
display.my_image = poster
display.grid(row=2, column=3, rowspan=3)
self.name.grid(row=0, rowspan=2, column=3)
root = Tk()
root.title("Test")
root.geometry("550x575")
app = App(root)
root.mainloop()
I believe, I should apply something similar to 'self.name.destroy()' on 'self.image'. However doesn't have such method... so how to solve it?

Categories