How to remove edit TKinter widget Python - python

Im trying to set up simple frame work for a trashy hang man game, the images are named in series of 6 for each stage of failure. S0 is the beginning and S6, is the final stage.
Im trying to figure out how to upudate the photo.
from tkinter import *
from PIL import ImageTk, Image
root = Tk()
i=0
frameLeft = Frame(root)
frameRight = Frame(root)
frameRight.pack(side=RIGHT)
frameLeft.pack(side=LEFT)
#frame Left
#function Declaration
entry1 = Entry(frameLeft)
entry1.pack()
def updatePhoto():
i = entry1.get()
img = ImageTk.PhotoImage(Image.open("S" + i + ".gif"))
imgPanel = Label(frameRight, image = img)
imgPanel.pack(side=BOTTOM, fill=BOTH, expand=YES)
labelInstruction = Label(frameLeft, text=entry1.get())
labelInstruction.pack()
submitButton = Button(frameLeft, text="Submit", command=updatePhoto)
submitButton.pack()
#frame Right
img = ImageTk.PhotoImage(Image.open("S" + str(i) + ".gif"))
imgPanel = Label(frameRight, image = img)
imgPanel.pack(side=BOTTOM, fill=BOTH, expand=YES)
root.mainloop()

Instead of these lines:
imgPanel = Label(frameRight, image = img)
imgPanel.pack(side=BOTTOM, fill=BOTH, expand=YES)
I was able to use these
imgPanel.configure(image=img)
imgPanel.image = img
I also changed the order of left and right side making right come first as it's a scripting language and requires declaration.

Related

Problem with Python tkinter (image does not appear as button)

First: In code below i want to use instead of default rectangle button, images prepared by myslef.
This generates some problems (mayby with reference)? This button does not appear as image, also i am not able to use function (name: load_frame_insert()) after click.
Second: I wonder to have 2 bbtns:
Normal: assets/insert_data.png
OnClick: assets/insert_data2.png
Could you help me?
PS. Doesn't work after moving from up-down code to code with functions
import pyodbc
import pandas as pd
import os
import tkinter as tk
from PIL import ImageTk
# DB connector
conn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};'
'SERVER=onyx1905;'
'DATABASE=DW_15;'
'Trusted_Connection=yes')
# variables
name = os.getlogin()
cursor = conn.cursor()
running = True
bg_color_1 = "#205E61"
bg_button = "#1B4E51"
bg_button_ac = "#FFD966"
global img_button_1
def image_button_1(size):
img = tk.PhotoImage(file="assets/insert_data.png")
img = img.subsample(size, size)
return img
#button img: insert_data
#button img: insert_data_on_click
def clear_widgets(frame):
for widget in frame.winfo_children():
widget.destroy()
def load_main_frame():
clear_widgets(frame_insert)
frame_main.tkraise()
frame_main.pack_propagate(False)
# widget frame_main logo
logo_image = ImageTk.PhotoImage(file="assets/xrdl_logo.png")
logo_widget = tk.Label(frame_main, image=logo_image, bg=bg_color_1)
logo_widget.image = logo_image
logo_widget.pack()
# label on 1st frame
tk.Label(
frame_main,
text=(f" Hi {name}, please choose an action "),
bg=bg_button,
fg="white",
font=("TkMenuFont", 12)
).pack(pady=10)
# btn code on 1st frame
tk.Button(
frame_main,
image=image_button_1(1),
bd=0,
relief="groove",
compound=tk.CENTER,
bg=bg_color_1,
fg="yellow",
activeforeground="pink",
activebackground=bg_color_1,
font=("TkMenuFont", 12),
cursor="hand2",
text="",
command=lambda: load_frame_insert()
).pack(pady=5)
def load_frame_insert():
print("Hi XYZ")
# ini for app
main_app = tk.Tk()
main_app.title("SRD Loader")
main_app.eval("tk::PlaceWindow . center")
x = main_app.winfo_screenwidth() // 3
y = int(main_app.winfo_screenheight() * 0.1)
main_app.geometry('500x600+' + str(x) + '+' + str(y))
# frame look
frame_main = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
frame_insert = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
for frame in (frame_main, frame_insert):
frame.grid(row=0, column=0)
load_main_frame()
main_app.mainloop()
conn.close()
other related topics but doesnt work
youtube tutorials
For the statement command=image_button_1(1), the image returned by image_button_1(1) will be garbage collected because there is no variable referencing it. That is why you get a button without image.
You need to save the reference of the image, for example using an attribute of the button as below:
image = image_button_1(1)
btn = tk.Button(
frame_main,
image=image,
bd=0,
relief="groove",
compound=tk.CENTER,
bg=bg_color_1,
fg="yellow",
activeforeground="pink",
activebackground=bg_color_1,
font=("TkMenuFont", 12),
cursor="hand2",
text="",
command=lambda: load_frame_insert()
)
btn.pack(pady=5)
btn.image = image # save the reference of the image
I removed three libraries.
I removed image_button_1 function
Added image = tk.PhotoImage(file="p1.png")
Added variable for Button
Change 5 to 25 .pack(pady=25)
Removed lambda and brace bracket command=load_frame_insert
Snippet:
import os
import tkinter as tk
running = True
bg_color_1 = "#205E61"
bg_button = "#1B4E51"
bg_button_ac = "#FFD966"
def clear_widgets(frame):
for widget in frame.winfo_children():
widget.destroy()
def load_main_frame():
clear_widgets(frame_insert)
frame_main.tkraise()
frame_main.pack_propagate(False)
# widget frame_main logo
logo_image = tk.PhotoImage(file="p2.png")
logo_widget = tk.Label(frame_main, image=logo_image, bg=bg_color_1)
logo_widget.image = logo_image
logo_widget.pack()
# label on 1st frame
tk.Label(
frame_main,
text=(f"Hi please choose an action"),
bg=bg_button,
fg="white",
font=("TkMenuFont", 12)
).pack(pady=10)
image = tk.PhotoImage(file="p1.png")
# btn code on 1st frame
btn= tk.Button(
frame_main,
image=image,
bd=0,
relief="groove",
compound=tk.CENTER,
bg=bg_color_1,
fg="yellow",
activeforeground="pink",
activebackground=bg_color_1,
font=("TkMenuFont", 12),
cursor="hand2",
text="",
command=load_frame_insert
)
btn.pack(pady=25)
btn.image = image
def load_frame_insert():
print("Hi XYZ")
# ini for app
main_app = tk.Tk()
main_app.title("SRD Loader")
main_app.eval("tk::PlaceWindow . center")
x = main_app.winfo_screenwidth() // 3
y = int(main_app.winfo_screenheight() * 0.1)
main_app.geometry('500x600+' + str(x) + '+' + str(y))
# frame look
frame_main = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
frame_insert = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
for frame in (frame_main, frame_insert):
frame.grid(row=0, column=0)
load_main_frame()
main_app.mainloop()
Screenshot:

Buttons getting misplaced after using background image in Tkinter

Whenever I run this code with a background Image the button grid gets misplaced and pushed towards the bottom. Fortunately, it works as intended when no background is added .I want them to cover the background when executed. Pictures for reference are added below. Your help is highly appreciated.
# importing the module
import tkinter.messagebox
from tkinter import *
import random
# importing the module
# initialising tkinter
class window(Frame):
def __init__(self,master = None):
Frame.__init__(self,master)
self.master = master
# initialising tkinter
# creating the window
root = Tk()
app = window(root)
root.geometry("630x630")
root.title('Odd Even Game')
C = Canvas(root, bg="blue", height=250, width=300)
filename = PhotoImage(file = "BG.png")
background_label = Label(root,image=filename)
background_label.place(x=0, y=0, relwidth=1, relheight=1)
C.pack()
frame = Frame(root)
frame.pack()
# creating the window
# image
level_1e = "p1.png"
level_1o = "pe.png"
level_2e = "r1.png"
level_2o = "re.png"
# image
def create_cards(odd_image,even_image,next_level,fno,order,suc,err,w,h):
rx = random.randint(0,order-1)
ry = random.randint(0,order-1)
for i in range(0,order):
for j in range(0,order):
if i == rx and j == ry:
create_button(i,j,suc,odd_image,next_level,fno,odd_image,w,h)
else:
create_button(i,j,err,even_image,next_level,fno,odd_image,w,h)
def second_level(fno):
fno.pack_forget()
frame2 = Frame(root)
frame2.pack()
suc = "Congratulations! You have cleared level 2..Keep Going Buddy!"
err = "Wrong Answer..Don't give up yet!"
create_cards(level_2o,level_2e,final_level,frame2,4,suc,err,157.5,157.5)
def final_level(fno):
fno.pack_forget()
root.geometry("700x700")
ap = App(root)
# creating a button function
def create_button(x,y,msg,picture,next_level,fno,odd,w,h):
if picture == odd:
image = PhotoImage(file=picture)
click = Button(fno, image=image, width= w, height=h, bd = 0,command = lambda : [score_update(),next_level(fno),tkinter.messagebox.showinfo( "Odd One Out Project",msg)])
click.image = image
click.grid( row = x, column = y)
else:
image = PhotoImage(file=picture)
click = Button(fno, image=image, width= w, height=h, bd = 0,command = lambda : [next_level(fno),tkinter.messagebox.showinfo( "Odd One Out Project",msg)])
click.image = image
click.grid( row = x, column = y)
# creating a button function
def create_frame(fno):
root.geometry("630x630")
fno.pack_forget()
frame = Frame(root)
frame.pack()
suc = "Congratulations! You have cleared level 1..Time to increas[![enter image description here][1]][1]e the difficulty!"
err = "Wrong Answer..Please Try again !!"
create_cards(level_1o,level_1e,second_level,frame,3,suc,err,200,200)
def intro():
root.geometry("630x630")
frame0 = Frame(root)
frame0.pack()
click = Button(frame0,text="Start!" ,command = lambda [create_frame(frame0),tkinter.messagebox.showinfo( "Odd One Out Project","The game has begun!!")])
click.pack()
intro()
# starting the widget
root.mainloop()
# starting the widget
The first image is the error. Second Image is the required output.
Note: I'm still a beginner in Python and Tkinter hence various terms and methods might be something out of my scope. Would be appreciated if taken into consideration.
In case needed, you might know that this is a tkinter project for picking the odd one out image out of A*A grid.
I got the answer myself so will be sharing for future use.
C = Canvas(root, bg="blue", height=250, width=300)
This part draws a canvas of 250*300 dimensions hence does not let the buttons draw over it.
just change it to,
C = Canvas(root, bg="blue", height=0, width=0)
for the desired result

How to attach delete function in Tkinter GUI

I am new to python & requesting help from experts in this community. I am trying to delete images from my Tkinter widget FrameLabel. I have followed many solutions provided on the StackOverflow, but unfortunately, I am unable to implement those solutions in my code. I need help in deleting the image I have uploaded on the window.
GUI working:
Click on Select
Browse the image
Upload the image
It will display in the LabelFrame shown as following:
frame3 = tk.LabelFrame(pw_right, bd=2, text='Uploaded images')
frame3.pack(side='left', anchor='nw')
Delete Button
DelButton = tk.Button(frame1, text ='Delete', command = button.on_click_del_button)
DelButton.grid(row=0, column=4)
Delete Function:
def on_click_del_button(self):
print('Delete button clicked')
image = self.paths[self.radio_var.get()]
if os.path.exists(image):
os.remove(image)
else:
print("The file does not exist")
Help required section: I need help in defining Delete Function i.e button.on_click_del_button
so that when I press delete. Tkinter deletes the selected image from the window.
Below is the GUI for the window:
I followed the suggestion followed by expert furas, But nothing is happening in the Tkinter window. Although all the print values are being displayed.
You don't have to load image to delete from disk - you need only path
image = self.paths[self.radio_var.get()]
and you have to use variable image, not string "image"
BTW: you don't need lambda to assing this function
command=button.on_click_del_button
and you don't need path='None', image='None' if you don't send values as arguments.
def on_click_del_button(self):
print('Delete button clicked')
image = self.paths[self.radio_var.get()]
if os.path.exists(image):
os.remove(image)
else:
print("The file does not exist")
To hide widget from window you have widget.pack_foger() and widget.grid_forget(). It hides so you can show it again using widget.pack() or widget.grid(...).
To remove widget from window and from memory - so you can't use it again - you have widget.destroy() like
self.radio_handle[0].destroy()
but you would have to know which radiobutton was selected 0, 1 or 2.
Maybe better use path to keep elements in dictionary, not on list
self.radio_handle[path] = radio_button
and later in on_click_del_button
self.radio_handle[path].destroy()
You could also use path as value in Radiobutton
tk.Radiobutton(..., value=path)
EDIT: It remove image from window.
I use StringVar() instead of IntVar()
self.radio_var = tk.StringVar()
and assign path as value in Radiobutton
Radiobutton(..., value=path)
so now it can return path instead of numer and it can be easier to find object in dictionary
self.radio_handle = dict()
Using list and numbers it could be problem because after removing element from list other elements change position on list and it could make problem.
Now I can add widget to dictionary
self.radio_handle[path] = (radio_button)
and the same way I can destroy it
def on_click_del_button(self):
print('Delete button clicked')
path = self.radio_var.get()
self.radio_handle[path].destroy()
import os
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
import cv2
from PIL import Image
from PIL import ImageTk
class Button:
def __init__(self, root, frame3):
self.root = root
self.frame3 = frame3
self.radio_var = tk.StringVar()
self.path_selected = '' # or None
self.paths = []
self.radio_handle = dict()
self.check_value = []
def on_click_select_button(self, fname_label):
print('select button clicked')
fileType = [('jpg/png file', ('*.jpg', '*.png'))]
self.path_selected = filedialog.askopenfilename(filetypes=fileType)
fname_label['text'] = os.path.basename(self.path_selected)
def on_click_upload_button(self, path='None', image='None'):
print('upload button clicked')
if path == 'None':
path = self.path_selected
else:
cv2.imwrite(path, image)
if path in self.paths:
messagebox.showerror('Upload Error', '"'
+ path
+ '"' + ' is already uploaded.')
else:
self.paths.append(path)
self.create_radio_button(path)
def on_click_show_button(self, method):
print('showButton clicked')
image = cv2.imread(self.paths[self.radio_var.get()])
file_name = os.path.basename(self.paths[self.radio_var.get()])
name, ext = os.path.splitext(file_name)
path = 'images/' + name + '_' + method + ext
def create_radio_button(self, path):
image = cv2.imread(path)
# image = cv2.resize(image,(120,120))
image = self.scale_to_height(image, 120)
image_tk = self.to_tk_image(image)
radio_button = tk.Radiobutton(self.frame3, image=image_tk,
value=path,
variable=self.radio_var)
self.radio_var.set('')
self.radio_handle[path] = (radio_button)
self.check_value.append(self.radio_var)
radio_button.grid(row=(len(self.radio_handle) - 1) // 3,
column=(len(self.radio_handle) - 1) % 3)
self.root.mainloop()
def to_tk_image(self, image_bgr):
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
image_pil = Image.fromarray(image_rgb)
image_tk = ImageTk.PhotoImage(image_pil)
return image_tk
def on_click_del_button(self):
print('Delete button clicked')
path = self.radio_var.get()
if path:
self.radio_handle[path].destroy() # remove widget from window
del self.radio_handle[path] # remove from dictionary
self.paths.remove(path) # remove path from list
self.radio_var.set('')
else:
print('Not selected')
#image = path # self.paths[self.radio_var.get()]
#if os.path.exists(image):
# os.remove(image)
#else:
# print("The file does not exist")
def scale_to_height(self, img, height):
scale = height / img.shape[0]
return cv2.resize(img, dsize=None, fx=scale, fy=scale)
if __name__ == '__main__':
os.makedirs('images', exist_ok=True)
root = tk.Tk()
root.title('Image GUI')
root.geometry('1280x960')
pw_left = tk.Frame(root, relief='ridge', borderwidth=4)
pw_left.pack(side='left', anchor='nw')
pw_right = tk.Frame(root, relief='ridge', borderwidth=4)
pw_right.pack(side='left', anchor='nw')
frame1 = tk.Frame(pw_left, bd=2, relief="ridge")
frame1.pack()
frame2 = tk.LabelFrame(pw_left, bd=2, relief="ridge", text='options')
frame2.pack(anchor='nw')
frame3 = tk.LabelFrame(pw_right, bd=2, text='Uploaded images')
frame3.pack(side='left', anchor='nw')
button = Button(root, frame3)
# add label
label = tk.Label(frame1, text='File:')
label.grid(row=0, column=0)
# label to show file name
file_name_label = tk.Label(frame1, text='-----not selected-----', width=20, bg='white')
file_name_label.grid(row=0, column=1)
# file select button
select_button = tk.Button(frame1, text='select',
command=lambda: button.on_click_select_button(file_name_label))
select_button.grid(row=0, column=2)
# upload button
uploadButton = tk.Button(frame1, text='Upload',
command=lambda: button.on_click_upload_button())
uploadButton.grid(row=0, column=3)
DelButton = tk.Button(frame1, text='Delete', command=button.on_click_del_button)
DelButton.grid(row=0, column=4)
root.mainloop()

How to make image disappear in tkinter

I've been programming a random operator name generator for Rainbox Six Siege and I want the operators picture to appear when their name comes up. The image appears fine, but it won't go away. This is my Code:
from tkinter import *
import tkinter
import random
names = ['Sledge','Thatcher','Ash','Thermite','Twitch','Montagne','Glaz','Fuze','Blitz','IQ','Buck','Blackbeard','Capitão','Hibana']
name = ["Smoke","Mute","Castle","Pulse","Doc","Rook","Kapkan","Tachanka","Jäger","Bandit","Frost","Valkyrie","Caveira","Echo"]
root = tkinter.Tk()
def pickName():
rad = random.choice(names)
photo = PhotoImage(file=rad+".png")
label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()
nameLabel.configure(text=rad, foreground="white", background="blue")
root.configure(background='blue')
def pickName1(): nameLabel.configure(text=random.choice(name),background="orange",foreground="black")
root.configure(background='orange')
root.title("Operator Picker")
root.geometry("250x100")
nameLabel = tkinter.Label(root, text="", font=('Helvetica', 32))
nameLabel.pack()
Grid()
f1 = tkinter.Frame(root, height=100, width=100) #defines frame size in
pixels
f1.pack(side=tkinter.LEFT) #packs on the left
f1.pack_propagate(0) #tells frame not to let children control size
pickButton1 = tkinter.Button(f1, command=pickName, text="Pick
Attack",background="blue",foreground="white")
pickButton1.pack(fill=tkinter.BOTH, expand=1) #takes up all available space
f2 = tkinter.Frame(root, height=100, width=100)
f2.pack(side=tkinter.RIGHT)
f2.pack_propagate(0)
pickButton2 = tkinter.Button(f2, command=pickName1, text="Pick
Defend",background="orange",foreground="black")
pickButton2.pack(fill=tkinter.BOTH, expand=1)
root.mainloop()
Note: This is still a WIP, all I need is to know how to get rid of the pictures once they appear. This is what it looks like when more than one image appears: https://imgur.com/eroXLLn
You are adding a new Label every time you call that function. Instead, you should make the Label only once (probably in the initialization stage), and update the picture. Just like you update the text for nameLabel, plus the step to keep the reference.
photo_label = tkinter.Label()
def pickName():
rad = random.choice(names)
photo = PhotoImage(file=rad+".png")
photo_label.configure(image = photo)
photo_label.image = photo # keep a reference!
photo_label.pack()
nameLabel.configure(text=rad, foreground="white", background="blue")
and your whole code should look like:
from tkinter import *
import tkinter
import random
names = ['Sledge','Thatcher','Ash','Thermite','Twitch','Montagne','Glaz','Fuze','Blitz','IQ','Buck','Blackbeard','Capitão','Hibana']
name = ["Smoke","Mute","Castle","Pulse","Doc","Rook","Kapkan","Tachanka","Jäger","Bandit","Frost","Valkyrie","Caveira","Echo"]
root = tkinter.Tk()
photo_label = tkinter.Label()
def pickName():
rad = random.choice(names)
photo = PhotoImage(file=rad+".png")
photo_label.configure(image = photo)
photo_label.image = photo # keep a reference!
photo_label.pack()
nameLabel.configure(text=rad, foreground="white", background="blue")
root.configure(background='blue')
def pickName1(): nameLabel.configure(text=random.choice(name),background="orange",foreground="black")
root.configure(background='orange')
root.title("Operator Picker")
root.geometry("250x100")
nameLabel = tkinter.Label(root, text="", font=('Helvetica', 32))
nameLabel.pack()
Grid()
f1 = tkinter.Frame(root, height=100, width=100) #defines frame size inpixels
f1.pack(side=tkinter.LEFT) #packs on the left
f1.pack_propagate(0) #tells frame not to let children control size
pickButton1 = tkinter.Button(f1, command=pickName, text="PickAttack",background="blue",foreground="white")
pickButton1.pack(fill=tkinter.BOTH, expand=1) #takes up all available space
f2 = tkinter.Frame(root, height=100, width=100)
f2.pack(side=tkinter.RIGHT)
f2.pack_propagate(0)
pickButton2 = tkinter.Button(f2, command=pickName1, text="PickDefend",background="orange",foreground="black")
pickButton2.pack(fill=tkinter.BOTH, expand=1)
root.mainloop()

Displaying .jpg image when button is clicked in Tkinter?

This seems like a pretty straightforward question, but i am having trouble displaying a jpg image when a button is clicked. Here is my code (without the button code for the sake of time):
from tkinter import *
#screen stuff here
canvas = Canvas(app)
canvas.grid(row = 0,column = 0)
photo = PhotoImage(file = "test.jpg")
canvas.create_image(0,0, image = photo)
def show_image():
global canvas
global photo
canvas.create_image(0,0, image = photo)
#button that calls the function down here
Thanks!
This works with Python2:
import Tkinter as tk
import ImageTk
def show_image():
x = canvas.create_image(125, 125, image=tk_img)
while True:
print('show')
canvas.itemconfigure(x, state=tk.NORMAL)
button.configure(text = 'Hide')
yield
print('hide')
canvas.itemconfigure(x, state=tk.HIDDEN)
button.configure(text = 'Show')
yield
root = tk.Tk()
canvas = tk.Canvas(root, width=250, height=250)
canvas.grid(row=0, column=0)
tk_img = ImageTk.PhotoImage(file='image.png')
button = tk.Button(
root, text="Show", command=show_image().next, anchor='w',
width=10, activebackground="#33B5E5")
button.grid(row=1, column=0)
root.mainloop()
In Python3, PhotoImage can open GIF, PPM/PGM images. To open other formats, you may need to install Pillow (a fork of the PIL project for Python3).

Categories

Resources