I want to input an image in my program, when I do this code
from tkinter import *
root = Tk()
image1 = PhotoImage(file='dog.gif')
label1 = Label(root, image=image1)
label1.pack()
root.mainloop()
The image will appear, but when I do this code
from tkinter import *
class Image():
def __init__(self, master):
self.master = master
self.display_image()
def display_image(self):
self.image = PhotoImage(file='dog.gif')
self.label1 = Label(self.master, image=self.image)
self.label1.pack()
if __name__ == '__main__':
root = Tk()
Image(root)
root.mainloop()
The window will appear but the image was not shown
If you create an image without keeping a strong reference somewhere, it will create a conflict between the garbage collector of Python and Tkinter : the reference stored in the Label prevents the complete destruction and the image will be blank.
Also, be careful to not override base classes like Image, you'd better rename your own class My_Image
A simple workaround is to create a global variable containing the image:
from tkinter import *
class My_Image():
def __init__(self, master):
self.master = master
self.display_image()
def display_image(self):
self.label1 = Label(self.master, image=label1_img)
self.label1.pack()
root = Tk()
label1_img = PhotoImage(file='dog.gif')
My_Image(root)
root.mainloop()
or you can even create a global variable to store the My_Image instance :
if __name__ == '__main__':
root = Tk()
img = My_Image(root)
root.mainloop()
Related
I want to resize a frame inside my canvas, so that the frame covers the whole window.
I did some googleing and saw some people are using a resize function, but this doesn't work for me.
I get the following error message:
_tkinter.TclError: invalid boolean operator in tag search expression
This is my code:
import tkinter as tk
from tkinter import ttk
class MainGUI:
def __init__(self):
self.root = tk.Tk()
self.root.geometry('400x400')
self.root.title("A simple GUI")
self.canvas = tk.Canvas(self.root, background='GREEN',width=900,height=300,scrollregion=(0,0,500,2000))
self.scrollbar=tk.Scrollbar(self.canvas,orient="vertical",command=self.canvas.yview)
self.scrollbar.pack(side="right",fill="y")
self.canvas.configure(yscrollcommand=self.scrollbar.set)
self.canvas.bind('<Configure>', lambda e: self.canvas.configure(scrollregion = self.canvas.bbox("all")))
self.main = tk.Frame(self.canvas,bg='BLUE')
self.canvas.create_window((0,0), window=self.main, anchor="nw")
self.canvas.pack(side=tk.TOP,fill=tk.BOTH,expand=True)
self.canvas.bind("<Configure>", self.resize_frame)
for _ in range(30):
MyCoolFrame(self.main)
def resize_frame(self, e):
canvas_width = e.width
self.canvas.itemconfig(self.main, width = canvas_width)
class MyCoolFrame:
def __init__(self,master):
self.master = master
self.frame = tk.Frame(self.master,bg='RED')
for i in range(5):
tk.Label(self.frame,text=f'Cool Label {i}').pack(side=tk.LEFT,padx=2,pady=10)
self.frame.pack(side=tk.TOP,pady=10)
a = MainGUI()
a.root.mainloop()
I asked this question before and the previous one linked to another question but it didn't solve the problem.
I have a number of images, which are updated frequently in a file.
The names of images are on the same pattern (e.g: img1.jpg , img2.jpg ...)
I am programming a GUI on python tkinter to start from the first image and automatically update after 30 second.
after many tries, I have no idea how to achieve that because mainloop()function freezes the GUI and the problem is that I need them in one GUI.
Here is the code I used to open and resize images:
from PIL import Image, ImageTk
x=1
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack(fill=BOTH, expand=1)
load = Image.open("./images/img%s.jpg"%x)
load=load.resize((1350,800))
render = ImageTk.PhotoImage(load)
img = Label(self, image=render)
img.image = render
img.place(x=0, y=0)
root = Tk()
app = Window(root)
root.wm_title("Tkinter window")
root.geometry("1350x800")
root.mainloop()
I tried to use label.after(3000,function) but no results came up so I deleted it from the code.
Is there any way to solve this problem?
Thanks in advance
Too big for the comments, But this is a working version of your code:
from tkinter import *
from PIL import Image, ImageTk
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack(fill=BOTH, expand=1)
self.x = 1 #assigning x to 1 to start with img1
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS) #loading first img
self.render = ImageTk.PhotoImage(self.load) #instantiating first img
self.img = Label(self, image=self.render) #labelizing it
self.img.image = self.render #keeping reference
self.img.pack() #packing it because place(x=0,y=0) will lead to overwriting of image
self.master.after(3000,self.update) #calling the function continoursly
def update(self):
self.x+=1 #increasing the x by 1 over each call to function
if self.x < 9:
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS)
self.render = ImageTk.PhotoImage(self.load)
self.img.config(image=self.render) #changing the image of label
self.master.after(3000,self.update)
root = Tk()
app = Window(root)
root.wm_title("Tkinter window")
root.geometry("1350x800")
root.mainloop()
Hope this helped, do let me know if any errors or doubts.
Cheers
This code solved my problem:
#from tkinter import *
from PIL import Image, ImageTk
import os
from tkinter import Frame,Label,BOTH,Tk
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack(fill=BOTH, expand=1)
self.x = 1
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS)
self.render = ImageTk.PhotoImage(self.load)
self.img = Label(self, image=self.render)
self.img.image = self.render
self.img.pack()
self.master.after(3000,self.update)
def update(self):
if self.x<len(os.listdir("./images/")):
self.x+=1
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS)
self.render = ImageTk.PhotoImage(self.load)
self.img.config(image=self.render)
self.master.after(3000,self.update)
else:
self.x=1
self.master.after(1,self.update)
root = Tk()
app = Window(root)
root.wm_title("Tkinter window")
root.geometry("1350x800")
root.mainloop()
I'm a beginner trying to use tkinter to create a GUI. I've adapted code from other sources for my own use.
At the moment I'm trying to display an image along with a button.
However, when running the code, only the image displays no matter where I move the button, the button isn't displayed.
Would be grateful for any help.
Additional functionality:
I'm looking to implement a function so that I can move the image around using coordinates, also a function that allows me to use .jpg instead of .png.
Thanks in advance!
Code:
from tkinter import *
from PIL import Image, ImageTk
class Window(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title("WindowName")
self.pack(fill = BOTH, expand = 1)
quitButton = Button(self, text = "quit", command=self.client_exit)
quitButton.place(x=400,y=400)
self.showImg()
def client_exit(self):
exit() # Or another function
def showImg(self):
self.grid(row=0)
self.columnconfigure(0,weight=1)
self.rowconfigure(0,weight=1)
self.original = Image.open('wire.png')
resized = self.original.resize((200, 200),Image.ANTIALIAS)
self.image = ImageTk.PhotoImage(resized)
self.display = Label(self, image = self.image)
self.display.grid(row=0)
root = Tk()
root.geometry("600x600")
app = Window(root)
root.mainloop()
This question concerns Python's Tkinter.
I first produced this GUI, a simple two-column set of rows in a Labelframe, with an icon on the right:
The above behaviour was correct and expected, based on this following code:
import tkinter as tk
import tkinter.ttk as ttk
from PIL import Image, ImageTk
root = tk.Tk()
icon_colours_fp = r"D:\Dropbox\coding\python\experiments\icon_component.gif"
icon_col = tk.PhotoImage(file=icon_colours_fp)
# icon_col = ImageTk.PhotoImage(Image.open(icon_colours_fp))
tk.Label(root, text="Past").grid(row=0, column=0)
tk.Label(root, text="Today").grid(row=1, column=0)
tk.Label(root, text="Future").grid(row=2, column=0)
_b = ttk.Button(root, image=icon_col)
_b['image'] =icon_col
_b.grid(row=0, column=1)
root.mainloop()
I then re-wrote the code as a class, hoping to produce something similar within a Labelframe:
import tkinter as tk
import tkinter.ttk as ttk
from PIL import Image, ImageTk
class Options(tk.Frame):
def __init__(self, parent):
super().__init__()
main_labelframe = ttk.LabelFrame(parent, text="Test Labelframe")
main_labelframe.pack(fill=tk.BOTH, expand=1)
frame_1 = tk.Frame(main_labelframe)
frame_1_sep = ttk.Separator(main_labelframe, orient=tk.VERTICAL)
frame_2 = tk.Frame(main_labelframe)
frame_1.pack(side=tk.LEFT)
frame_1_sep.pack(side=tk.LEFT, fill=tk.BOTH)
frame_2.pack(side=tk.LEFT)
tk.Label(frame_1, text="Past").grid(row=0, column=0)
tk.Label(frame_1, text="Today").grid(row=1)
tk.Label(frame_1, text="Future").grid(row=2)
icon_colours_fp = r"D:\Dropbox\coding\python\experiments\icon_component.gif"
icon_col = tk.PhotoImage(file=icon_colours_fp)
_b = ttk.Button(frame_2, image=icon_col)
_b['image'] = icon_col
_b.grid(row=0, column=0)
class Gui(tk.Tk):
def __init__(self):
super().__init__()
options = Options(self)
options.pack()
gui = Gui()
gui.mainloop()
The code then failed, in two respects:
The icon fails to appear.
The ttk Button becomes misaligned. (It appears in the centre, whereas by the grid, it should appear at the top.)
The failed code appears as follows:
I have experimented: among others, I changed the geometry manager to .pack(), and changed the parent of ttk.Button, but without success. Would appreciate some pointers as to where I've gone wrong, especially as to the disappearing icon.
You didn't keep a reference to the image. Easiest way here is to change:
icon_col = tk.PhotoImage(file=icon_colours_fp)
b = ttk.Button(frame_2, image=icon_col)
_b['image'] = icon_col
To:
self.icon_col = tk.PhotoImage(file=icon_colours_fp)
b = ttk.Button(frame_2, image=self.icon_col)
I am trying to create a program in tkinter which allows me to open an initial window then to keep it throughout all classes used. For example, if I was to create a button in a window then when I click this button, it would exuecute a method that destroys the widget, and then executes a new class that builds a new screen within the same window, such as text opposed to a button.
from tkinter import *
class Window1:
def __init__(self, master):
self.master = master
self.label = Button(self.master, text = "Example", command = self.load_new)
self.label.pack()
def load_new(self):
self.label.destroy()
## Code to execute next class
class Window2:
def __init__(self, master):
self.master = master
self.label = Label(self.master, text = "Example")
self.label.pack()
def main():
root = Tk()
run = Window1(root)
root.mainloop()
if __name__ == '__main__':
main()
I understand this is less practical, but I am curious. Cheers.
Tk() creates main window and variable root gives you access to this window. You can use root as argument for Window2 and you will have access to main window inside Window2
from tkinter import *
class Window1:
def __init__(self, master):
# keep `root` in `self.master`
self.master = master
self.label = Button(self.master, text="Example", command=self.load_new)
self.label.pack()
def load_new(self):
self.label.destroy()
# use `root` with another class
self.another = Window2(self.master)
class Window2:
def __init__(self, master):
# keep `root` in `self.master`
self.master = master
self.label = Label(self.master, text="Example")
self.label.pack()
root = Tk()
run = Window1(root)
root.mainloop()
--
Probably nobody use another class to create Label in place of Button ;)
--
EDIT: In this example using names Window1 and Windows2 is misleading because there is only one window and two classes which use this window. I would rather use names FirstOwner, SecondOwner
Everything is implemented in one Tk class and in this case there always is only one window.
from tkinter import *
from tkinter import ttk
class MainWindow():
def __init__(self, mainWidget):
self.main_frame = ttk.Frame(mainWidget, width=300, height=150, padding=(0, 0, 0, 0))
self.main_frame.grid(row=0, column=0)
self.some_kind_of_controler = 0
self.main_gui()
def main_gui(self):
root.title('My Window')
self.main_label_1 = ttk.Label(self.main_frame, text='Object_1')
self.main_label_1.grid(row=0, column=0)
self.main_label_2 = ttk.Label(self.main_frame, text='Object_2')
self.main_label_2.grid(row=1, column=0)
self.main_label_3 = ttk.Label(self.main_frame, text='Object_3')
self.main_label_3.grid(row=2, column=0)
self.setings_button = ttk.Button(self.main_frame, text='Setings')
self.setings_button.grid(row=0, column=1)
self.setings_button.bind('<Button-1>', self.setings_gui)
self.gui_elements = [self.main_label_1,
self.main_label_2,
self.main_label_3,
self.setings_button]
def setings_gui(self, event):
self.gui_elements_remove(self.gui_elements)
root.title('Setings')
self.main_label_1 = ttk.Label(self.main_frame, text='Object_1')
self.main_label_1.grid(row=2, column=0)
self.main_menu_button = ttk.Button(self.main_frame, text='Main menu')
self.main_menu_button.grid(row=0, column=1)
self.main_menu_button.bind('<Button-1>', self.back_to_main)
self.some_kind_of_controler = 1
self.gui_elements = [self.main_label_1,
self.main_menu_button]
def back_to_main(self, event):
if self.some_kind_of_controler == 1:
self.gui_elements_remove(self.gui_elements)
else:
pass
self.main_gui()
def gui_elements_remove(self, elements):
for element in elements:
element.destroy()
def main():
global root
root = Tk()
root.geometry('300x150+50+50')
window = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()