How to delete frame on click of button? Python tkinter - python

import tkinter as tk
global counter
counter = 0
def addframe():
global counter
newtask_frame = tk.Frame(highlightbackground="green",highlightthickness=1, master = intrldisp_frame)
newtaskheading_label = tk.Label(newtask_frame, text="Added frame")
newtaskheading_label.grid(row=0,column=0)
newtaskdel_button = tk.Button(newtask_frame,text="del", command = newtask_frame.grid_forget())
newtaskdel_button.grid(row=1,column = 0,pady=5,padx=10)
newtask_frame.grid(row=counter,column=0,sticky = "nsew",pady=10,padx=5)
counter+=1
window = tk.Tk()
tasksinfo_frame = tk.Frame(highlightbackground="red",highlightthickness=2)
tasksinfo_frame.grid(row=0,pady=10)
addtask_button = tk.Button(tasksinfo_frame, text = "add",activebackground="blue",command = addframe)
addtask_button.pack(fill=tk.BOTH)
intrldisp_frame = tk.Frame(highlightbackground="blue",highlightthickness=1, master = window)
intrldisp_frame.grid(row=1,column=0,sticky = "n", padx=5)
window.mainloop()
So, I wrote a function for a button that creates a frame on click as can be read from the code above. I have also added a delete button in each frame that gets added, but I cannot figure out how to get the delete button to work.
How do I delete the frame when clicked on the del button? Is there any way to add id to them= frames? Do I have to use OOP for this?
Thank you.

How do I delete the frame when clicked on the del button?
You need to call the destroy method of the frame.
newtaskdel_button = tk.Button(..., command = newtask_frame.destroy)

Related

Create Tkinter buttons in a loop that reference each other

I'm trying to create a series of tkinter buttons with a loop that are .grid'd to their own respective frames. I want every button to have a function that .tkraises the next frame in the list of frames that I create. Any idea how? Here's what I've got. The buttons/ frames are created I think but the .tkraise function doesn't work. Thanks
from tkinter import *
from PIL import ImageTk, Image
## Define root and geometry
root = Tk()
root.geometry('200x200')
# Define Frames
winlist = list()
winlist = Frame(root, bg='red'), Frame(root, bg='green'), Frame(root, bg='blue')
# Configure Rows
root.grid_rowconfigure(0, weight = 1)
root.grid_columnconfigure(0, weight = 1)
# Place Frames
for window in winlist:
window.grid(row=0, column = 0, sticky = 'news')
# Raises first window 'To the top'
winlist[0].tkraise()
# Function to raise 'window' to the top
def raise_frame(window):
window.tkraise()
d = {}
count = 0
for x in range(0, 3):
d["label{0}".format(x)] = Label(winlist[x], text = "label{0}".format(x))
if count <=1:
try:
d["button{0}".format(x)] = Button(winlist[x], text = "button{0}".format(x), command = raise_frame(winlist[x+1]))
d["button{0}".format(x)].pack(side=TOP)
except:
pass
else:
d["label{0}".format(x)].pack(side=TOP)
count += 1
root.mainloop()
The issue is on the command option of the line:
d["button{0}".format(x)] = Button(winlist[x], text = "button{0}".format(x), command = raise_frame(winlist[x+1]))
It will execute raise_frame(winlist[x+1]) immediately and then assign the result (which is None) to command option. Therefore, clicking the button later does nothing.
You need to use lambda instead:
d["button{0}".format(x)] = Button(winlist[x], text="button{0}".format(x),
command=lambda x=x: raise_frame(winlist[x+1]))
I answered my own question. instead of using frames I went back to creating Tk() objects. I made a loop that runs a function that creates Tk() objects and passed in a variable that carried the count of my loop. I used that count to change information on each Tk() object and instead made the 'command =' of each button include a Tk().destroy function. This creates all the windows I wanted all at once and I can perform an action and exit the window. It's progress. Thanks,
Tim,

How do I enable right click in entry and output widget for pasting and copying respectively in Tkinter?

I'm still working on the translator app, with the help of Python Dictionary. But I have this challenge: I want to be able to right click in the entry widget and paste keys as well as right click in the output widget and copy values. I'm only able to do so with keyboard shortcut; for convenience sake, I want to be able to do so with the mouse. Thanks. Below is the code:
from tkinter import *
import tkinter. messagebox
root=Tk()
root.geometry('250x250')
root.title("Meta' Translator")
root.configure(background="#35424a")
from playsound import playsound
#Entry widget object
textin = StringVar()
#press ENTER key to activate translate button
def returnPressed(event):
clk()
def clk():
entered = ent.get().lower() #get user input and convert to lowercase
output.delete(0.0,END)
if len(entered) > 0:
try:
textin = exlist[entered]
except:
textin = 'Word not found'
output.insert(0.0,textin)
def play():
text = output.get("0.0", "end").strip("\n")
if text == "əsɔ́":
playsound("hoe.mp3")
elif text == "jam":
playsound("axe.mp3")
elif text == "ɨghə́":
playsound("eye.mp3")
else:
# If there is no sound file for the translation:
playsound("eze.mp3")
#heading
lab0=Label(root,text='Translate English Words to Meta\'',bg="#35424a",fg="silver",font=
('none 11 bold'))
lab0.place(x=0,y=2)
#Entry field
ent=Entry(root,width=15,font=('Times 18'),textvar=textin,bg='white')
ent.place(x=30,y=30)
#focus on entry widget
ent.focus()
#Search button
but=Button(root,padx=1,pady=1,text='Translate',command=clk,bg='powder blue',font=('none 18
bold'))
but.place(x=60,y=90)
#press ENTER key to activate Translate button
root.bind('<Return>', returnPressed)
#output field
output=Text(root,width=15,height=1,font=('Times 18'),fg="black")
output.place(x=30,y=170)
#play button
play_button=Button(root,padx=1,pady=1,text='Play',command=play,bg='powder blue',font=('none
10 bold'))
play_button.place(x=100,y=210)
#prevent sizing of window
root.resizable(False,False)
#Dictionary
exlist={
"hat":"ɨ̀də̀m",
"hoe":"əsɔ́",
"honey":"jú",
"chest":"ɨgɔ̂",
"eye":"ɨghə́",
"ear":"ǝ̀tǒŋ",
"axe":"jam"
}
root.mainloop()
Since your code has a lot of dependency, it cannot be run on another system, so here is a common example which you should be able to implement to your code easily:
from tkinter import *
root = Tk()
def popup(event):
try:
menu.tk_popup(event.x_root,event.y_root) # Pop the menu up in the given coordinates
finally:
menu.grab_release() # Release it once an option is selected
def paste():
clipboard = root.clipboard_get() # Get the copied item from system clipboard
e.insert('end',clipboard) # Insert the item into the entry widget
def copy():
inp = e.get() # Get the text inside entry widget
root.clipboard_clear() # Clear the tkinter clipboard
root.clipboard_append(inp) # Append to system clipboard
menu = Menu(root,tearoff=0) # Create a menu
menu.add_command(label='Copy',command=copy) # Create labels and commands
menu.add_command(label='Paste',command=paste)
e = Entry(root) # Create an entry
e.pack(padx=10,pady=10)
e.bind('<Button-3>',popup) # Bind a func to right click
root.mainloop()
I have explained it with comments to understand on-the-go, nothing complicated. The menu just pops up when you right click on the entry as the function is binded to the entry alone. I think, without clipboard_clear() it would append all the items in the tkinter clipboard to the system clipboard.

Python tkinter updating canvas label outside the main function

I am trying to update the canvas label outside the function that canvas was created.
def Application_GUI():
global Scanned_serial
global label1
global label2
global window
global label_gaminys
global canvas_tk
window = Tk() # create a GUI window
window.geometry("1920x1080") # set the configuration of GUI window
canvas_tk = Canvas(window,bg='ivory2',width=1920,height=1080)
canvas_tk.pack()
label1=Label(canvas_tk,text = "SKENUOKITE BARKODA(GUID) ARBA DAIKTO RIVILINI KODA:",bg='ivory2')
entry = Entry(canvas_tk) # entry = guid
canvas_tk.create_window(960,50,window=label1)
canvas_tk.create_window(960,100,window=entry)
var = IntVar()
button = Button(canvas_tk,text="Testi operacija",width = 30,height=2,command = lambda: var.set(1))
button2 = Button(canvas_tk,text="RESTART DEVICES",width = 30,height=2,command = lambda:restart_devices(myConnection))
ota_button = Button(canvas_tk, text="OTA", width=30, height=1, command=OTA_gui)
canvas_tk.create_window(960,150,window=button)
canvas_tk.create_window(960,200,window=button2)
canvas_tk.create_window(960,250,window=ota_button)
# ********************* IMPORTANT PART *************************
label_gaminys=Label(canvas_tk,text = "GAMINIO KODAS:",bg='ivory2')
canvas_tk.create_window(960,450,window=label_gaminys)
# ***************************************************************
print("waiting...")
button.wait_variable(var)
result = entry.get()
print("result=",result)
Scanned_serial = entry.get()
label2=Label(window,text = "Vykdoma operacija:")
label2.pack()
window.update()
In the function above, I am creating my user interface using a canvas. The important line of code is there:
label_gaminys=Label(canvas_tk,text = "GAMINIO KODAS:",bg='ivory2')
canvas_tk.create_window(960,450,window=label_gaminys)
I have created a window for a text at location 960,450.
I want to update this label outside this GUI function during a operation .
def Full_operation():
#Destroy previous window
window.destroy()
#create a new GUI window
Application_GUI()
global canvas_tk
operacijos_kodas=Scanning_operation(myConnection,Scanned_serial)
elif(operacijos_kodas == 1):
insertData_komplektacija(myConnection,"fmb110bbv801.csv");
update_current_operation(myConnection);
#label2.config(text = "Take items from the box:")#update the label2
label_gaminys=Label(canvas_tk,text = "Gamninio kodas=%s"%(Scanned_serial),bg='ivory2')
canvas_tk.create_window(960,450,window=label_gaminys)
picking_operation(myConnection,label2);
The function above describes the operatio. I want to modify the label inside this function. I have described my canvas_tk as global and initialise in this function so I can access and modify it. I have managed to update the label by creating a new window as following:
label_gaminys=Label(canvas_tk,text = "Gamninio kodas=%s"%(Scanned_serial),bg='ivory2')
canvas_tk.create_window(960,450,window=label_gaminys)
picking_operation(myConnection,label2);
But that does not seem like a correct way to do that since I am not actually "updating" the label, instead I am creating a new window and assigning it to a new label.
Could someone give me some general advice on how to do that properly?
You can just create a function that does this:
label_gaminys["text'] = "" #Insert the text you want into it and then the text changes
and then you can modify it whilst being in the same window. On another note, do notice that your Full_operation has an elif in it without an if first (just notifying you, because if there is no if before it it will cause an error).

Need help completing code for password conversion

I'm very new at Python and need some help finishing the code. This is Tkiner related. I have an entry box, a button, and a lower frame for the output.
def loop_over_input(the_str=''):
master_list = []
for char in the_str:
tmp_char = passwordConversion[char]
master_list.append(tmp_char)
print("Master Pass List: ", master_list)
return master_list
This will work in command line with a couple of other lines. I'm not sure how tell it when I put text in the entry field and click the button to return the results in my lower frame. I have moved def loop_over_input to different parts of the code I think I may need to reference the test entry box and the button and the lower box.
I will post the complete code if requested to do so.
Firstly, you need to indent your code correctly. Everything that is in the function loop_over_input needs to be indented once more than the line def loop_over_input(the_str=''):
A few other notes. If you look up the documentation for the tkinter button, it will explain how to link a command to it. The piece of code you have supplied appears to be what you want the button command to be. Printing the list will do so in the shell, not in a frame below your entry field and button.
Here's some example code that should do what you want:
import tkinter as tk
# Creating tk window
window = tk.Tk()
# Master list
master_list = []
master_list_string = tk.StringVar()
# Frames
top_frame = tk.Frame(window)
top_frame.pack(expand = True, fill = 'x', pady = 10, padx = 10)
bottom_frame = tk.Frame(window)
bottom_frame.pack(expand = True, fill = 'both', padx = 10)
# Entry box
myEntry = tk.Entry(top_frame)
myEntry.pack(side = 'left',expand = True, fill = 'x', padx = 10)
# Label to display master list
myLabel = tk.Label(bottom_frame, textvariable = master_list_string)
myLabel.pack(expand = True, fill = 'both')
# Button to submit
def clicked():
master_list.append(myEntry.get())
myEntry.delete(0, 'end')
printed_list = ''
for password in master_list:
printed_list += "\n" + password
master_list_string.set(printed_list)
myButton = tk.Button(top_frame, text = "Submit", command = clicked)
myButton.pack(side = 'left', padx = 10)
# Mainloop
window.mainloop()
The two frames allow you to have the top section with your entry and button, while the bottom frame is for your output. However, you cannot just use a frame as your output, as your frame can't display text. Instead, use a Label widget linked to a StringVar which allows the text in the Label to update when the variable is changed.
The button command then takes the string entered into the entry, saves it to the master list and then sets the StringVar to the updated list, which automatically updates the Label.
I would highly recommend ready the documentation on Effbot, it's quite easy to understand with good examples. Link here

Simple gui that display a repeated set of images when a button is pushed

I made a very simple gui that has a button and shows an image(.gif). My goal is to output another .gif whenever you press the button. There are 2 .gif files in my file directory and the point is to keep switching between these two whenever you press the button.
#Using python2.7.2
import Tkinter
root = Tkinter.Tk()
try:
n
except:
n = 0
def showphoto(par):
if par%2 == 0:
try:
label2.destroy()
except:
pass
photo = Tkinter.PhotoImage(file="masc.gif")
label2 = Tkinter.Label(image=photo)
label2.image = photo
label2.pack()
else:
try:
label2.destroy()
except:
pass
photo = Tkinter.PhotoImage(file="123.gif")
label2 = Tkinter.Label(image=photo)
label2.image = photo
label2.pack()
myContainer1 = Tkinter.Frame(root, width = 100, height = 100)
myContainer1.pack()
def callback(event):
global n
showphoto(n)
n = n + 1
button1 = Tkinter.Button(myContainer1)
button1["text"]= "Next pic"
button1["background"] = "green"
button1.bind("<Button-1>", callback(n))
button1.pack()
root.mainloop()
The current code just outputs the first image (masc.gif) but when I press the button it doesn't switch to the other image(123.gif). What am I doing wrong?
This can achieved much easier with classes as the class holds all the data necessary without the use of global variables.
import Tkinter as tk
from collections import OrderedDict
class app(tk.Frame):
def __init__(self,master=None, **kwargs):
self.gifdict=OrderedDict()
for gif in ('masc.gif','123.gif'):
self.gifdict[gif]=tk.PhotoImage(file=gif)
tk.Frame.__init__(self,master,**kwargs)
self.label=tk.Label(self)
self.label.pack()
self.button=tk.Button(self,text="switch",command=self.switch)
self.button.pack()
self.switch()
def switch(self):
#Get first image in dict and add it to the end
img,photo=self.gifdict.popitem(last=False)
self.gifdict[img]=photo
#display the image we popped off the start of the dict.
self.label.config(image=photo)
if __name__ == "__main__":
A=tk.Tk()
B=app(master=A,width=100,height=100)
B.pack()
A.mainloop()
Of course, this could be done more generally ... (the list of images to cycle through could be passed in for example), and this will switch through all the images in self.gifs ...
This approach also removes the necessity to destroy and recreate a label each time, instead we just reuse the label we already have.
EDIT
Now I use an OrderedDict to store the files. (keys=filename,values=PhotoImages). Then we pop the first element out of the dictionary to plot. Of course, if you're using python2.6 or earlier, you can just keep a list in addition to the dictionary and use the list to get the keys.
button1 = Tkinter.Button(myContainer1)
button1["text"]= "Next pic"
button1["background"] = "green"
button1.bind("<Button-1>", callback(n))
First, you bind the <Button-1> event to None (that's what callback(n) evaluates to). You should bind it to callback (no parentheses a.k.a the call operator).
Second, I suggest you change callback to not accept any arguments, remove the bind call and create your button as:
button1 = Tkinter.Button(myContainer1, command=callback)

Categories

Resources