tkinter: my second option menu broke the first one - python

I made an option menu with tkinter that worked exactly as I wanted to, but when I added a second option menu I started getting error messages and I'm not sure why. I attached the code for the first and second option menu and the error message.
Code for first option menu:
# Option Menu teams
om_team_options = []
for i in team_list:
om_team_options.append(i.name)
var_team = StringVar(root)
var_team.set(om_team_options[0])
om_team = tk.OptionMenu(frm_create_team, var_team, *om_team_options)
om_team.grid(row=0, column=1)
# - Save team button
btn_team_save = tk.Button(frm_create_team, text='Voeg team toe', #Line 92
command=lambda: add_team())
btn_team_save.grid(row=3, column=5)
def add_team():
for obj in team_list:
if var_team.get() == obj.name:
ingame_list.append(obj)
place_team(obj.name)
team_list.remove(obj)
om_team_options.remove(var_team.get())
x = om_team['menu'].index(var_team.get()) #Line 103
om_team['menu'].delete(x)
var_team.set(om_team['menu'].entrycget(0, 'label'))
def place_team(name):
cols, rows = frm_team_list.grid_size()
lbl = tk.Label(frm_team_list, text=name)
lbl.grid(row=rows, column=0)
btn = tk.Button(frm_team_list, text='-',
command=lambda: remove_team(lbl, btn, name))
btn.grid(row=rows, column=1)
def remove_team(lbl, btn, name):
for obj in ingame_list:
if name == obj.name:
team_list.append(obj)
add_om_option(name)
ingame_list.remove(obj)
lbl.destroy()
btn.destroy()
def add_om_option(name):
om_team['menu'].add_command(label=name, command=tk._setit(var_team, name))
om_team_options.append(name)
var_team.set(om_team_options[0])
code for second option menu:
# Option menu existing players
om_players_options = ['Player1', 'Player2', 'Player3']
var_players = StringVar(root)
var_players.set(om_players_options[0])
om_team = tk.OptionMenu(frm_create_team, var_players, *om_players_options)
om_team.grid(row=2, column=1)
Error message:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\max\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:\Users\max\Desktop\Coding\Python projects\31_Seconds\Test2.py", line 92, in <lambda>
btn_team_save = tk.Button(frm_create_team, text='Voeg team toe', command=lambda: add_team())
File "C:\Users\max\Desktop\Coding\Python projects\31_Seconds\Test2.py", line 103, in add_team
x = om_team['menu'].index(var_team.get())
File "C:\Users\max\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 3394, in index
i = self.tk.call(self._w, 'index', index)
_tkinter.TclError: bad menu entry index "Team Blauw"
Process finished with exit code 0
Edit 2: minimal runnable example:
import tkinter as tk
from tkinter import StringVar
root = tk.Tk()
root.geometry('400x600')
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
# ______________________________________________________________________________________________________________________
# Game Frames
teams = tk.Frame(root, bg='yellow')
teams.grid(sticky='news')
# ______________________________________________________________________________________________________________________
# Teams Frame
# - Team class and instances
class Team:
def __init__(self, name):
self.name = str(name)
self.players = []
self.current_player = int(0)
self.points = int(0)
team_blue = Team('Team Blauw')
team_red = Team('Team Rood')
team_green = Team('Team Groen')
team_yellow = Team('Team Geel')
# - Team lists
team_list = [team_blue, team_red, team_green, team_yellow]
ingame_list = []
# - Frames in teams frame
frm_create_team = tk.Frame(teams)
frm_team_list = tk.Frame(teams)
frm_create_team.grid()
frm_team_list.grid()
# - Buttons and lables for team frame
cols, rows = frm_create_team.grid_size()
tk.Label(frm_create_team, text='Choose a team: ').grid(row=0, column=0)
tk.Label(frm_create_team, text='Existing player: ').grid(row=1, column=0)
# - Option Menu teams
om_team_options = []
for i in team_list:
om_team_options.append(i.name)
var_team = StringVar(root)
var_team.set(om_team_options[0])
om_team = tk.OptionMenu(frm_create_team, var_team, *om_team_options)
om_team.grid(row=0, column=1)
# - Save team button
btn_team_save = tk.Button(frm_create_team, text='Add Team', command=lambda: add_team())
btn_team_save.grid(row=3, column=5)
def add_team():
for obj in team_list:
if var_team.get() == obj.name:
ingame_list.append(obj)
place_team(obj.name)
team_list.remove(obj)
om_team_options.remove(var_team.get())
x = om_team['menu'].index(var_team.get())
om_team['menu'].delete(x)
var_team.set(om_team['menu'].entrycget(0, 'label'))
def place_team(name):
column, row = frm_team_list.grid_size()
lbl = tk.Label(frm_team_list, text=name)
lbl.grid(row=row, column=0)
btn = tk.Button(frm_team_list, text='-', command=lambda: remove_team(lbl, btn, name))
btn.grid(row=row, column=1)
def remove_team(lbl, btn, name):
for obj in ingame_list:
if name == obj.name:
team_list.append(obj)
add_om_option(name)
ingame_list.remove(obj)
lbl.destroy()
btn.destroy()
def add_om_option(name):
om_team['menu'].add_command(label=name, command=tk._setit(var_team, name))
om_team_options.append(name)
var_team.set(om_team_options[0])
# - Option menu existing players
om_players_options = ['Player1', 'Player2', 'Player3']
var_players = StringVar(root)
var_players.set(om_players_options[0])
om_team = tk.OptionMenu(frm_create_team, var_players, *om_players_options)
om_team.grid(row=1, column=1)
root.mainloop()

Related

Modules and classes in Python for a desktop application

This is to be a desktop application for opening multiple small databases and running queries on them. So far I've written some code for opening forms as necessary. Is this a good way to do it? Also - the code shown opens two copies of each form - what am I doing wrong? It's my first attempt at Python and I'm a rudimentary programmer so simple answers would be of most help please. TIA (Python 3.9.6)
link_1.py
from tkinter import Tk
import link_2
root = Tk()
class ClassLink_1:
#if another function in the class is called, the __init__ function is run at start up
def __init__(self):
print("in link_1 __init__ instruction")
#the call_function function can be called at start up, or not, and will act accordingly
def call_function(self):
print("in call_function")
#the line below is run at start up whether or not another function in the class is called
print("in link_1")
root.withdraw() #hides the blank form at start up
#if __name__ == "__main__":
#the line below shows the link_2 form, whether or not the if __name__==__main__ condition is used as its condition
link_2.ClassLink_2(root).__init__(root)
#link_3.ClassLink_3(root).__init__(root)
#the line below runs call_function on start up to print text
ClassLink_1().call_function()
root.mainloop()
link_2.py
from tkinter import Tk, Button
from tkinter import * #for Toplevel
import link_3
root = Tk()
class ClassLink_2:
def __init__(self, master):
self.openNewWindow()
def openNewWindow(self):
newWindow = Toplevel(root) #creates a top level widget with the parent root (first parameter)
newWindow.title("Title opened from link_1")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_1").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_2", command= self.do_add)
self.add_button.grid(row=3, column=1)
def do_add(self):
print("button pressed")
link_3.ClassLink_3(root).__init__(root)
root.withdraw() #hides the blank form at start up
link_3.py
from tkinter import Tk, Button
from tkinter import * #for Toplevel
root = Tk()
class ClassLink_3:
def __init__(self, master):
self.openNewWindow()
def openNewWindow(self):
newWindow = Toplevel(root) #creates a top level widget with the parent root (first parameter)
newWindow.title("Title opened from link_2")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_2").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_3", command= self.do_add)
self.add_button.grid(row=3, column=1)
def do_add(self):
print("button pressed")
# link_4.ClassLink_4(root).__init__(root) this file has not yet been made
root.withdraw() #hides the blank form at start up
This is a proposed solution, can be expanded as needed. Constructive suggestions for improvement of the structure or code would be appreciated. TIA. I've left in the details in case they are of use to anyone.
link_1
from tkinter import Tk
import link_2
root = Tk()
class ClassLink_1:
def __init__(self):
print("in link_1 __init__ instruction")
root.withdraw() #hides the blank form at start up
link_2.ClassLink_2(root).openNewWindow(0)
root.mainloop()
link_2
from tkinter import Tk, Button
from tkinter import *
import link_3
root = Tk()
class ClassLink_2:
root.withdraw() #hides the blank form at start up
class_var_1 = 0
inst_var_1 = 0
def __init__(self, incoming_inst_var_1):
pass
def openNewWindow(self, inst_var_1_to_open):
newWindow = Toplevel(root)
newWindow.title("Title opened from link_1")
newWindow.geometry("500x500")
label = Label(newWindow, text ="Opened from link_1").grid(row=1, column=1)
self.add_button = Button(newWindow, text="in ClassLink_2", command= self.do_add)
self.add_button.grid(row=3, column=1)
self.add_button = Button(newWindow, text="increment class_var_1", command= self.inc_class_var_1)
self.add_button.grid(row=5, column=1)
self.inst_var_1 = inst_var_1_to_open
def do_add(self):
print("button pressed")
link_3.ClassLink_3(root).openNewWindow(0)
def inc_class_var_1(self):
ClassLink_2.class_var_1 += 2
self.inst_var_1 += 1
print("self.class_var_1 = " + (str)(self.class_var_1))
print("self.inst_var_1 = " + (str)(self.inst_var_1))
link_3
from tkinter import Tk, Button
from tkinter import *
from tkinter.ttk import Combobox
import tkinter.scrolledtext as tkscrolled
# import link_4 <filename of next form>
root = Tk()
class ClassLink_3:
class_var_1 = 0
inst_var_1 = 0
# ------------------------------- START CLASS CONTROLS -----------------------------
root.withdraw()
def __init__(self, incoming_inst_var_1):
pass
def openNewWindow(self, inst_var_1_to_open):
new_window = Toplevel(root)
self.widget_factory(new_window)
self.inst_var_1 = inst_var_1_to_open
def do_add(self):
print("button pressed")
# link_4.ClassLink_4(root).openNewWindow(0) # <filename of next form>
# ---------------------------------- END CLASS CONTROLS -----------------------------
# -------------------------------------- START CALCS --------------------------------------
def inc_class_var_1(self):
ClassLink_3.class_var_1 += 2
self.inst_var_1 += 1
print("self.class_var_1 = " + (str)(self.class_var_1))
print("self.inst_var_1 = " + (str)(self.inst_var_1))
# ---------------------------------------- END CALCS --------------------------------------
# ---------------------------------------- START FACTORY SHOPS-----------------------------------------
def widget_factory(self, new_window):
self.shop_window(new_window)
self.shop_labels(new_window)
self.shop_buttons(new_window)
self.shop_menu(new_window)
self.shop_listbox(new_window)
self.shop_combobox(new_window)
self.shop_radiobuttons(new_window)
self.shop_checkbuttons(new_window)
self.shop_entries(new_window)
self.shop_canvas(new_window)
self.shop_scale(new_window)
self.shop_scrollbars(new_window)
self.shop_textbox(new_window)
self.shop_menu(new_window)
pass
# ------------------------
def shop_window(self, new_window):
new_window.title("Title opened from link_2")
new_window.geometry("800x900")
def shop_labels(self, new_window):
self.label_1 = Label(new_window, text ="Opened from link_2").grid(row=1, column=1)
def shop_buttons(self, new_window):
self.button_1 = Button(new_window, text="in ClassLink_3", command= self.do_add)
self.button_1.grid(row=3, column=1)
self.button_2 = Button(new_window, text="increment class_var_1", command= self.inc_class_var_1)
self.button_2.grid(row=5, column=1)
def shop_listbox(self, new_window):
data=("one", "two", "three", "four")
self.listbox_1 = Listbox(new_window, height=5, selectmode='multiple')
for num in data:
self.listbox_1.insert(END,num)
self.listbox_1.grid(row=7, column=1)
def shop_combobox(self, new_window):
data=("one", "two", "three", "four")
self.combobox_1 = Combobox(new_window, values=data)
self.combobox_1.grid(row=8, column=3)
def shop_radiobuttons(self, new_window):
var_1 = IntVar()
var_1.set(1)
self.rad_btn_1 = Radiobutton(new_window, text="male", variable=var_1, value=1)
self.rad_btn_2 = Radiobutton(new_window, text="female", variable=var_1, value=2)
self.rad_btn_1.grid(row=9, column=1)
self.rad_btn_2.grid(row=9, column=2)
def shop_checkbuttons(self, new_window):
var_1 = IntVar()
var_2 = IntVar()
self.checkbtn_1 = Checkbutton(new_window, text = "Cricket", variable = var_1)
self.checkbtn_2 = Checkbutton(new_window, text = "Tennis", variable = var_2)
self.checkbtn_1.grid(row=10, column=1)
self.checkbtn_2.grid(row=10, column=2)
def shop_entries(self, new_window):
self.entry_1 = Entry(new_window, width = 20)
self.entry_1.insert(0,'Username')
self.entry_1.grid(row= 11, column=2)
self.entry_2 = Entry(new_window, width = 15)
self.entry_2.insert(0,'password')
self.entry_2.grid(row= 12, column=2)
#might want to place on a frame, see example https://coderslegacy.com/python/list-of-tkinter-widgets/
def shop_canvas(self, new_window):
canvas = Canvas(new_window, bg= 'white', width = 260,height = 260) #this is the background for the figure
# left and top of figure is from [x from left, y from top] of canvas right and bottom of figure from [x from left, y from top] of canvas
coordinates = 20, 50, 210, 230
arc = canvas.create_arc(coordinates, start=0, extent=250, fill="blue") #start is from E, extent is in degrees CCW
arc = canvas.create_arc(coordinates, start=250, extent=50, fill="red")
arc = canvas.create_arc(coordinates, start=300, extent=60, fill="yellow")
canvas.grid(row=2, column=1)
def shop_scale(self, new_window):
self.scale_1 = Scale(new_window, from_=0, to=10, orient=VERTICAL)
self.scale_1.grid(row=15, column=2)
self.scale_2 = Scale(new_window, from_=0, to=10, orient = HORIZONTAL)
self.scale_2.grid(row=15, column=3)
def shop_scrollbars(self, new_window):
self.scroll_vert = Scrollbar(new_window)
self.scroll_vert.grid(row=19, column=3)
self.listbox_3 = Listbox(new_window, yscrollcommand = self.scroll_vert.set )
for line in range(1, 100):
self.listbox_3.insert(END, "Number " + str(line))
self.listbox_3.grid(row=19 , column=2)
self.scroll_vert.config(command = self.listbox_3.yview)
def shop_textbox(self, new_window):
#make a frame with parent new_window
self.frame_textbox_1 = Frame(new_window)
self.frame_textbox_1.grid(row=1, column=5)
#make the textbox with parent frame
self.textbox_1 = Text(self.frame_textbox_1)
self.textbox_1.config(wrap=NONE, width=15, height=8) #width, height are characters x rows permitted wrap values should be WORD CHAR, or NONE
#make the X scrollbar with parent frame
self.scroll_text_horiz = Scrollbar(self.frame_textbox_1, orient="horizontal")
self.scroll_text_horiz.config(command = self.textbox_1.xview)
#make the Y scrollbar with parent frame
self.scroll_text_vert = Scrollbar(self.frame_textbox_1, orient="vertical")
self.scroll_text_vert.config(command = self.textbox_1.yview)
#pack the scrollbars before the texbox to allow them to fill the frame width and height
self.scroll_text_horiz.pack(side=BOTTOM, fill=X)
self.scroll_text_vert.pack(side=RIGHT, fill=Y)
self.textbox_1.pack(fill="y")
#connect the scrollbars to the textbox
self.textbox_1["xscrollcommand"] = self.scroll_text_horiz.set
self.textbox_1["yscrollcommand"] = self.scroll_text_vert.set
message = "the quick brown fox"
self.textbox_1.insert(1.1, message)
# ----------------------------------------------
def shop_menu(self, new_window):
print("in shop menu1")
menubar = Menu(new_window)
print("in shop_menu2")
file = Menu(menubar, tearoff=0)
file.add_command(label="New")
file.add_command(label="Open")
file.add_command(label="Save")
file.add_command(label="Save as...")
file.add_command(label="Close")
file.add_separator()
file.add_command(label="Exit", command=new_window.quit)
menubar.add_cascade(label="File", menu=file)
edit = Menu(menubar, tearoff=0)
edit.add_command(label="Undo")
edit.add_separator()
edit.add_command(label="Cut")
edit.add_command(label="Copy")
edit.add_command(label="Paste")
edit.add_command(label="Delete")
edit.add_command(label="Select All")
menubar.add_cascade(label="Edit", menu=edit)
help = Menu(menubar, tearoff=0)
help.add_command(label="About")
menubar.add_cascade(label="Help", menu=help)
new_window.config(menu=menubar)
print("in shop menu3")
# --------------------------------------- END FACTORY SHOPS---------------------------------------

Python Tkinter Spinboxes return value using for loops

I'm trying to use X many spin boxes as there are items in a list - so have put them on screen using a for loop.
However, I don't seem able to get them to return their value when I click a button.
aStarter = ["Starter 1", "Starter 2", "Starter 3"]
def getOrders():
aStarterOrder = []
aMainOrder = []
aDessertOrder = []
for i in aStarterQuantity:
aStarterOrder.append(StarterQuantity.get())
print(aStarterOrder)
aStarterQuantity = []
StarterQuantity = IntVar()
for i in range(len(aStarter)):
lbl = Label(self, text = aStarter[i]).grid(column = 0, row = 2 + i)
StarterQuantity = Spinbox(self, from_=0, to=20, width=5, command=callback, font=Font(family='Helvetica', size=20, weight='bold')).grid(column = 1, row = 2 + i)
print(StarterQuantity.get())
I have tried appending the StarterQuantity to an array inside of the for loop:
aStarterQuantity = []
StarterQuantity = IntVar()
for i in range(len(aStarter)):
lbl = Label(self, text = aStarter[i]).grid(column = 0, row = 2 + i)
StarterQuantity = Spinbox(self, from_=0, to=20, width=5, command=callback, font=Font(family='Helvetica', size=20, weight='bold')).grid(column = 1, row = 2 + i)
aStarterQuantity.append(StarterQuantity.get())
This returns a None Type error - I can't seem to get the value out of the spin box.
Any ideas?
Here is the full code (it's very much an early WIP!)
from tkinter import *
from tkinter.font import Font
import sqlite3
DatabaseFile = 'RMS.db'
connDatabase = sqlite3.connect(DatabaseFile)
#Creating a cursor to run SQL Commands
DatabaseSelect = connDatabase.cursor()
#Selecting all Menu Data
DatabaseSelect.execute("SELECT * FROM MENU")
MenuData = DatabaseSelect.fetchall()
class Main(Tk): #This sets up the initial Frame in a Window called Main
def __init__(self): #This creates a controller to use the Frames
Tk.__init__(self) #This creates a Window within the controller
self._frame = None #This sets the frame to have a value of None - this makes sure the main Window doesn't get destroyed by the switch frame function
self.switch_frame(Home)
def switch_frame(self, frame_class): #This function is used to switch frames. Self is the master frame, frame_class is the name of the Class (page) being passed int
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy() #Destroy any frames except the master
self._frame = new_frame #Make a new frame
self._frame.grid(column=0, row=0) #Put the frame in the top left
class Home(Frame):
def __init__(self, master):
Frame.__init__(self, master)
Label(self, text="The White Horse").grid(column = 0, row = 0)
btnPage1 = Button(self, text="Orders", command=lambda: master.switch_frame(Orders)).grid(column = 1, row = 0)
#Making a blank page with a return home button
class Orders(Frame): #This sets up a class called Page1 - Each new page will need a new class.
def __init__(self, master): #This sets up a controller to put things into the Frame
Frame.__init__(self, master) #Make the frame using the controller
#Get list of Starters from Menu Data
aStarter = ["Starter 1", "Starter 2", "Starter 3"]
aMain = []
aDessert = []
for i in MenuData:
if i[3] == "Starters":
aStarter.append(i[1])
if i[3] == "Main":
aMain.append(i[1])
if i[3] == "Dessert":
aDessert.append(i[1])
def getOrders():
aStarterOrder = []
aMainOrder = []
aDessertOrder = []
for i in aStarterQuantity:
aStarterOrder.append(StarterQuantity.get())
print(aStarterOrder)
def callback():
print(StarterQuantity.get())
#Starter Section
boxes = []
aStarterQuantity = []
StarterQuantity = IntVar()
for i in range(len(aStarter)):
lbl = Label(self, text = aStarter[i]).grid(column = 0, row = 2 + i)
StarterQuantity = Spinbox(self, from_=0, to=20, width=5, command=callback, font=Font(family='Helvetica', size=20, weight='bold')).grid(column = 1, row = 2 + i)
aStarterQuantity.append(StarterQuantity.get())
#Mains Sections
for i in range(len(aMain)):
lbl = Label(self, text = aMain[i]).grid(column = 6, row = 2 + i)
MainQuantity = Spinbox(self, from_=0, to=20, width=5, font=Font(family='Helvetica', size=20, weight='bold')).grid(column = 7, row = 2 + i)
#Dessert Section
for i in range(len(aDessert)):
lbl = Label(self, text = aDessert[i]).grid(column = 12, row = 2 + i)
DessertQuantity = Spinbox(self, from_=0, to=20, width=5, font=Font(family='Helvetica', size=20, weight='bold')).grid(column = 13, row = 2 + i)
btnHome = Button(self, text="Home", command=lambda: master.switch_frame(Home)).grid(column = 0, row = 1) #Add a Button
btnSubmitEntries = Button(self, text = "Submit", command = getOrders).grid(column = 0, row= 20)
Main = Main()
Main.geometry("1200x800")
Main.mainloop()
The problem seems to be that the grid method doesn't return anything, so StarterQuantity gets assigned None i.e. the default return value for a function.
for i in range(len(aStarter)):
lbl = Label(self, text=aStarter[i])
lbl.grid(column=0, row=2 + i)
sq_font = Font(family='Helvetica',
size=20,
weight='bold')
StarterQuantity = Spinbox(self,
from_=0,
to=20,
width=5, command=callback,
font=sq_font)
StarterQuantity.grid(column=1, row=2 + i)
aStarterQuantity.append(StarterQuantity.get())
This works in my case. (Pulled out the Font argument for Spinbox to increase readability on mobile).
Unrelated note; I don't know what code style you prefer/have to maintain and it is up to you of course, but I thought it might be helpful to mention that the naming style convention in Python (PEP8) is to use CamelCase for class names, lower_case_w_underscores for variable names and functions/methods, and SCREAMING_SNAKE for constants.

ttk.treeview selection_set to the item with specific id

I want to edit an item in treeview by another Toplevel window and after editing want to refresh / reload items into list from database and set focus to the edited item.
The problem I am facing is to SET FOCUS TO THE EDITED ITEM IN TREEVIEW. Any help will be appreciated.
Here is the minimal sample code.
import tkinter as tk
from tkinter import ttk
class _tree(tk.Frame):
def __init__(self, *args):
tk.Frame.__init__(self, *args)
self.tree = ttk.Treeview(self, columns = ("id", "name"))
self.tree.heading("#0", text = "s.n")
self.tree.heading("#1", text = "id")
self.tree.heading("#2", text = "name")
self.tree.pack()
_items = [[52,"orange"],[61,"manggo"],[1437,"apple"]] # item with id 61 needs to be changed
sn = 1
for r in (_items):
self.tree.insert("", "end", text = str(sn), values = (r[0], r[1]))
sn += 1
self.tree.bind("<Double-Button-1>", self._item)
def _item(self, event):
global item_values
global item_id
global item_name
idx = self.tree.selection()
item_values = self.tree.item(idx)
print("item_values : %s" % item_values)
item_id = self.tree.set(idx, "#1")
item_name = self.tree.set(idx, "#2")
edit_item(self)
class edit_item(tk.Toplevel):
def __init__(self, master, *args):
tk.Toplevel.__init__(self, master)
self.master = master
global item_values
global item_name
lbl1 = tk.Label(self, text = "item name")
self.ent1 = tk.Entry(self)
btn1 = tk.Button(self, text = "update", command = self.update_item)
lbl1.place(x=0, y=10)
self.ent1.place(x=90, y=10)
btn1.place(x=90, y=100)
self.ent1.insert(0, item_name)
def update_item(self):
for i in self.master.tree.get_children():
self.master.tree.delete(i)
new_data = [[52,"orange"],[61,"mango"],[1437,"apple"]] # item with id 61 has been changed
sn = 1
for r in (new_data):
self.master.tree.insert("", "end", text = str(sn), values = (r[0], r[1]))
sn += 1
# Need to set focus on item with id 61
idx = self.master.tree.get_children(item_values['values'][0]) # HERE NEED HELP
self.master.tree.focus_set()
self.master.tree.selection_set(idx)
self.master.tree.focus(idx)
self.destroy()
def main():
root = tk.Tk()
app = _tree()
app.pack()
root.mainloop()
if __name__ == "__main__":
main()
`
I am receiving the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
return self.func(*args)
File "test_tree.py", line 55, in update_item
idx = self.master.tree.get_children(item_values['values'][0]) # HERE NEED HELP
File "/usr/lib/python3.8/tkinter/ttk.py", line 1225, in get_children
self.tk.call(self._w, "children", item or '') or ())
_tkinter.TclError: Item 61 not found
You don't need to delete the existing values in order to update the value. You can simply use the set() method to update your treeview.
syntax:
tree.set(iid, column=None, value=None)
If you specify only iid in set method it will return items as dict.
Here is a better way to do the same.
from tkinter import ttk
import tkinter as tk
titles={'Id': [1,2,3,4,5, 6, 7, 8, 9], 'Names':['Tom', 'Rob', 'Tim', 'Jim', 'Kim', 'Kim', 'Kim', 'Kim', 'Kim']}
def update(selected_index_iid, changed):
index = treev.index(selected_index_iid)# or just index = treev.index(treev.selection())
treev.set(selected_index_iid, 1, changed) # updating the tree
titles['Names'][index] = changed #updating the dictionary
print(titles)
def clicked(event):
global titles
top = tk.Toplevel(window)
label = tk.Label(top, text='Update: ')
label.pack()
entry = tk.Entry(top)
entry.insert(0, treev.set(treev.selection())['1']) #if you only specify the iid 'set' will return dict of items, ['1'] is to select 1st column
entry.pack()
button= tk.Button(top, text='Update', command=lambda :update(treev.selection(), entry.get()))
button.pack()
window = tk.Tk()
treev = ttk.Treeview(window, selectmode ='browse')
treev.bind('<Double-Button-1>', clicked)
treev.pack(side='left',expand=True, fill='both')
verscrlbar = ttk.Scrollbar(window,
orient ="vertical",
command = treev.yview)
verscrlbar.pack(side ='right', fill ='y')
treev.configure(yscrollcommand = verscrlbar.set)
treev["columns"] = list(x for x in range(len(list(titles.keys()))))
treev['show'] = 'headings'
for x, y in enumerate(titles.keys()):
treev.column(x, minwidth=20, stretch=True, anchor='c')
treev.heading(x, text=y)
for args in zip(*list(titles.values())):
treev.insert("", 'end', values =args)
window.mainloop()

How can i erase contents in a Label?

Sorry for the mess
so I am making a seating chart, and I cant seem to get it working properly... again. I am trying to make the label reset every time i press the run button, any ideas?
#commands: add name , Run
#imports
import random
from time import sleep
from tkinter import *
#Console and background Handlers
Tables = 6
Names = []
def AddNames():
NewNames = e.get("1.0", 'end -1c')
if NewNames in Names:
print("Name Already exists")
elif NewNames == "":
print("Empty")
else:
Names.append(NewNames)
print(Names)
e.delete(1.0, END)
def Random():
RandomNum = random.randrange(Tables)
if RandomNum == 0:
RandomNum = random.randrange(Tables)
return RandomNum
def run():
X = 0
for i in Names:
#print(Names[X])
print("Table: " + str(Random()))
X += 1
#text = Label(popup, text = "")
text = Label(popup, text= Names[X] + "\n" + "Table: " + str(Random()))
text.pack()
#GUI Handler
root = Tk()
root.geometry("1024x768")
e = Text(root, bd = 10, font=("Comic Sans MS", 50) ,width = 15, height = 2)
e.pack()
popup = Toplevel()
popup.title("Seating Chart")
AddNameButton = Button(root, text = ("Add Name"), width = 15, height = 5, command = AddNames)
AddNameButton.pack()
RunButton = Button(root, text = ("Run"), width = 15, height = 5, command = run)
RunButton.pack()
root.mainloop()
I am trying to reset text every time the user presses the run button
import tkinter
from tkinter import ttk
import random
class MyApp:
def __init__(self):
self.root = tkinter.Tk()
self.seatwindow = None
self.root.title('Add Names')
self.currentname = tkinter.StringVar()
self._maxtables = tkinter.StringVar()
self.addednames = []
self.commandframe = ttk.Labelframe(self.root, text='Commands')
self.nameentry = ttk.Entry(self.root, textvariable=self.currentname)
self.addbutton = ttk.Button(self.root, text='Add Name', command=self.addname)
self.maxtablabel = ttk.Label(self.root, text='Tables: ')
self.maxtabentry = ttk.Entry(self.root, textvariable=self._maxtables)
self.genbutton = ttk.Button(self.commandframe, text='Run', command=self.generate)
self.resetbutton = ttk.Button(self.commandframe, text='Reset', command=self.reset)
self._maxtables.set('6')
self.nameentry.grid(row=0, column=0)
self.addbutton.grid(row=0, column=1, sticky='nsew')
self.maxtabentry.grid(row=1, column=1, sticky='nsw')
self.maxtablabel.grid(row=1, column=0, sticky='nse')
self.genbutton.grid(row=0, column=0, sticky='nsew')
self.resetbutton.grid(row=0, column=1, sticky='nsew')
self.commandframe.grid(row=2, column=0, columnspan=2, sticky='nsew')
self.nameentry.bind('<Return>', self.addname)
self.root.bind('<Control-Return>', self.generate)
def addname(self, event=None):
name = self.currentname.get()
if not(name == '' or name in self.addednames):
self.addednames.append(name)
self.currentname.set('')
else:
self.currentname.set('Name already added!')
def generate(self, event=None):
if not self.seatwindow == None:
self.seatwindow.destroy()
self.currentname.set('')
self.seatwindow = tkinter.Toplevel()
random.shuffle(self.addednames)
tables = []
for i in range(self.maxtables):
tableframe = ttk.Labelframe(self.seatwindow, text='Table ' + str(i + 1) + ':')
tableframe.grid(column=i, row=0, sticky='nsew')
tables.append(tableframe)
for index, name in enumerate(self.addednames):
namelabel = ttk.Label(tables[index%self.maxtables], text=name)
namelabel.grid(column=0, row=index//self.maxtables + 1)
def reset(self):
self.currentname.set('')
self.maxtables = 6
self.addednames = []
def run(self):
self.root.mainloop()
#property
def maxtables(self):
return int(self._maxtables.get())
MyApp().run()

Tkinter - set label for listbox

I'm trying to do a simple GUI in Tkinter. I have a Listbox there and I want the user to know what kind of data is in the Listbox so I want to set a label for it (upper).
The problem is that when I set a label, this Listbox disappears.
l = Label(multiple_choose_days_listbox, textvariable=label_day_listbox , anchor=NW, justify='center')
l.pack()
The solution is probably obvious but I'm new in Tkinter.
Do you have any advices?
import Tkinter
import tkSimpleDialog
from Tkinter import *
import db
import ttkcalendar
class CalendarDialog(tkSimpleDialog.Dialog):
"""Dialog box that displays a calendar and returns the selected date"""
def __init__(self, master):
self.calendar = ttkcalendar.Calendar(master)
# self.calendar.pack()
#property
def result(self):
return self.calendar.selection
def pack(self,**kwargs):
self.calendar.pack(**kwargs)
states_list = db.get_states()
bought_days_before_list = db.get_bought_days_before()
multiple_choose_length_of_trips_list = db.get_lengths_of_trips()
def main():
root = Tkinter.Tk()
root.wm_title("CalendarDialog Demo")
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
root.geometry("1000x500")
top = Frame(root)
bottom = Frame(root)
top.pack(side=TOP)
bottom.pack(side=BOTTOM, fill=BOTH, expand=True)
cd_1 = CalendarDialog(root)
cd_2 = CalendarDialog(root)
cd_1.pack(in_=top, side=LEFT)
cd_2.pack(in_=top, side=LEFT)
multiple_choose_states_listbox = Listbox(root, selectmode=EXTENDED)
multiple_choose_states_listbox.grid(row=20, columns=1)
multiple_choose_days_listbox = Listbox(root, selectmode=EXTENDED)
multiple_choose_length_of_trips_list_listbox = Listbox(root, selectmode=EXTENDED)
label_day_listbox = StringVar()
label_day_listbox.set("LABEL")
l = Label(multiple_choose_days_listbox, textvariable=label_day_listbox , anchor=NW, justify='center')
l.pack()
multiple_choose_days_listbox.pack(in_=top,side=LEFT)
multiple_choose_states_listbox.pack()
multiple_choose_length_of_trips_list_listbox.pack()
for item in states_list:
multiple_choose_states_listbox.insert(END, item)
for item in bought_days_before_list:
multiple_choose_days_listbox.insert(END, item)
def get_result_dict():
date_from = cd_1.result
date_to = cd_2.result
states = [states_list[i] for i in multiple_choose_states_listbox.curselection()]
bought_days_before = [bought_days_before_list[i] for i in multiple_choose_days_listbox.curselection()]
length_of_trip = [states_list[i] for i in multiple_choose_length_of_trips_list.curselection()]
res_dict = {
'date_from': date_from,
'date_to': date_to,
'states': states,
'bought_days_before': bought_days_before,
'length_of_trip': length_of_trip,
}
return res_dict
button = Tkinter.Button(root, text="Generate", command=get_result_dict)
button.pack()
root.update()
root.mainloop()
if __name__ == "__main__":
main()
It should be
l = Tkinter.Label(root, text="Label")

Categories

Resources