【问题标题】:Deleting a specific widget in tkinter在 tkinter 中删除特定的小部件
【发布时间】:2021-11-03 09:06:03
【问题描述】:
#importing modules required
import tkinter as tk
import tkinter.messagebox
import tkcalendar as tkcal

#initializing global variables
x,y=50,100 
tables={}
dateoftable=''
dateslist=[]
statusbartext = 'Status: Press on the button to create a new table'
btnnumber=0

#creating the main window
root=tk.Tk()
root.title("Time Table")
root.geometry("800x600")

#Label that says the instruction
mainLabel=tk.Label(root,text="Select Timetable below")
mainLabel.place(x=10,y=10)

#button to create a new table
newtablebtn=tk.Button(root,text="+Create Table")
newtablebtn.place(x=320,y=50,width=90,height=30)

#button to delete a table
deletetablebtn=tk.Button(root,text="X Delete All Tables")
deletetablebtn.place(x=430,y=50,width=100,height=30)

#status bar at the bottom right
statusbar=tk.Label(root,text=statusbartext)
statusbar.place(x=500,y=570)

#function opens a new window to choos date and creates a button in main window for that date
def createtable():
    global dateoftable,dateslist,btnnumber
    
    #initializing the window containing the date picker
    calframe=tk.Tk()
    calframe.title("Date Picker")
    calframe.geometry('400x400')

    #Creating the calendar widget
    cal = tkcal.Calendar(calframe, year=2021, month=1, day=1, selectmode='day',
                         showothermonthdays=False, date_pattern='dd-mm-y')
    cal.place(x=70,y=20)

    #Creating the button to pick the date
    getdatebtn=tk.Button(calframe, text="Get Date")
    getdatebtn.place(x=160,y=260)

    #function that gets the date and creates a new table
    def grad_date():
        global y, x, tables, dateoftable, statusbartext, dateslist,btnnumber

        #Storing the date picked into the global variable
        dateoftable=cal.get_date() 

        #checking if date  picked already exists
        if dateoftable not in dateslist:
            
            dateslist.append(dateoftable)
            btnnumber+=1
            #Creating the button for that specific date
#THIS IS THE PART WHERE THE btn.number AND STUFF COMES IN
            btn = tk.Button(root, text=dateoftable)
            btn.number=btnnumber
            btn.place(x=x, y=y, width=100, height=100)

            #Appending the button object to a list
            tables[btnnumber]=btn

            #for the button to not go beyond the main window's border
            if y <= 400: 
                y += 120
            else:
                if x < 600:
                    x += 120
                    y = 100
                #if both boundaries limit's are reached 
                else:
                    statusbartext = 'Status: No more tables can be created!'
                    newtablebtn.configure(command=None)
                    statusbar.configure(text=statusbartext)

            #destroying the date picker window once the date is picked
            calframe.destroy()

        else:

            tkinter.messagebox.showwarning("Warning", "Table for the date picked already exists. Please choose another date.")
            calframe.destroy()
        

    getdatebtn.configure(command=grad_date)
    
    calframe.mainloop()

    
#function that deletes all the created tables
def deletetables():
    global tables,x,y,dateoftable,dateslist,statusbartext,btnnumber
    
    for table in tables.values():
        table.destroy()
    #resetting the global variables
    tables.clear()
    btnnumber=0
    dateoftable=''
    dateslist.clear()
    statusbartext = 'Status: Press on the button to create a new table'
    statusbar.configure(text=statusbartext)
    x,y=50,100


#I just kept this function as a placeholder action to occur when the button is clicked
def tableclick():
    tkinter.messagebox.showinfo("Warning", "Table for the date picked already exists. Please choose another date.")



#configuring buttons to perform actions
newtablebtn.configure(command=createtable)
deletetablebtn.configure(command=deletetables)

for button in tables.values():
    button.configure(command=tableclick)
 
root.mainloop()

所以在deletetables() 函数中,我希望删除按钮在单击时调用它。

我什么都可以,要么一次删除所有表格(按钮),要么在单击时一个一个删除每个表格(按钮)。我还想知道如何访问单独创建的每个表(按钮),因为我希望它们有自己的属性。

【问题讨论】:

  • 题外话:您可以使用newtablebtn.configure(command=None) 甚至newtablebtn.configure(command=lambda: None) 删除与创建表按钮关联的命令。
  • 非常感谢!我忘记了 null 关键字是在 java 中而不是在 python 中:]
  • @martineau 如果您希望命令为无。你不能设置它。默认为无。只需省略newtablebtn.configure(command=None) 这一行。
  • @Random_Pythoneer59:在 OP 的代码中,他们以过于复杂的方式禁用了以前设置为某物的命令,这就是我发表评论的原因。
  • @martineau 哦,我的错。

标签: python python-3.x user-interface tkinter


【解决方案1】:

创建一个全局列表来存储所有表,然后将它们从列表中删除。

tables = []
#...
def createtable():
    global y, x
    
    btn=tk.Button(root,text="Table")
    btn.place(x=x,y=y,width=100,height=100)
    tables.append(btn) #Append it to tables

    #for the button to not go beyond the main window's border
    if y <= 400:
        y += 120
    else:
        if x<600:
            x += 120
            y = 100
        else:
            newtablebtn.configure(command=nocommand)
            statusbar.configure(text="Status: No more tables can be created!")
#...
def deletetables():
    global tables, x, y
    for table in tables:
        table.destroy()
    tables.clear()
    x, y = 50, 100

还要注意deletetablebtn.configure(command=deletetables)中的一个错误(没有括号)。

【讨论】:

  • 嗨!非常感谢这确实解决了我的问题!!我还有一个疑问,如果我想访问这些单独创建的按钮中的每一个并赋予它们自己的特征怎么办。我应该遍历表格列表以获取按钮对象的名称,然后分配它们的属性吗?
  • 是的。您可以遍历列表并分配您的属性。您可以使用btn.number = 1 为他们分配一个号码。然后遍历列表,找到您的 btn 并根据需要更改其属性。您也可以使用像btns_dict = {1: btn1, 2: btn2} 这样的字典,然后在删除时您可以使用btns_dict.value() 并删除它们。并使用btns_dict.clear() 清除字典。
  • 再次嗨,我将存储按钮的变量更改为字典而不是列表。for table in tables.items(): print(table) 所以这段代码的输出是(1, &lt;tkinter.Button object .!button3&gt;) 我如何访问这个按钮。还有btns_dict = {1: btn1, 2: btn2} 是什么意思,btn1 如何能够引用我创建的第一个按钮。还有一件事btn.number=1 在代码中的位置是什么?我有很多疑问:(我得到了删除部分,非常感谢:]
  • 如果你想编辑第一个按钮,那么你可以这样做 - btn1 = btns_dict[1],你会得到带有键 1 的按钮。依此类推......
  • for button in tables.values(): button.configure(command=tableclick) 这就是我遍历我创建的所有按钮并将它们分配给command=tableclick 的方法,但它仍然不起作用。我应该在问题中在这里上传我编辑的代码吗?这会帮助你理解我的担忧吗@Random_Pythoneer59
【解决方案2】:

将按钮放置在新框架中,并使用 - 清除框架

for widget in frame.winfo_children():
    widget.destroy()

不推荐使用全局变量,但我仍然使用它们 -

import tkinter as tk 

x,y=10,100 #global variables for positions

root=tk.Tk()
root.title("Time Table")
root.geometry("800x600")

frame1 = tk.Frame(root,width=750,height=600)
frame1.place(x=25,y=30)

mainLabel=tk.Label(root,text="Select Timetable below")
mainLabel.place(x=10,y=10)

#button to create a new table
newtablebtn=tk.Button(root,text="+Create Table")
newtablebtn.place(x=320,y=50,width=90,height=30)

#button to delete a table
deletetablebtn=tk.Button(root,text="X Delete All Tables")
deletetablebtn.place(x=430,y=50,width=100,height=30)

#status bar at the bottom right
statusbar=tk.Label(root,text='Status: ')
statusbar.place(x=550,y=570)

#Using this function for buttons that shouldn't perform any function;command=Null didn't work
def nocommand():
    pass

#function creates buttons, as a placeholder for tables
def createtable():
    global y
    global x
    
    btn=tk.Button(frame1,text="Table")
    btn.place(x=x,y=y,width=100,height=100)
    
    #for the button to not go beyond the main window's border
    if y <= 400:
        y += 120
    else:
        if x<600:
            x += 120
            y = 100
        else:
            newtablebtn.configure(command=nocommand)
            statusbar.configure(text="Status: No more tables can be created!")
    
#THE FUNCTION I NEED HELP WITH 
def deletetables():
    global x,y
    x,y=10,100
    for widgets in frame1.winfo_children():
        widgets.destroy()

#configuring buttons to perform actions
newtablebtn.configure(command=createtable)
deletetablebtn.configure(command=deletetables)

root.mainloop()

【讨论】:

  • 嗨!非常感谢,我检查了这个解决方案,这也解决了我的问题!类似于我对@Random_Pythoneer59 的回答的评论,我想知道是否有一种方法可以访问按钮对象而无需遍历frame1.winfochildren() 部分。而且当我遍历循环以找出使用for widgets in frame1.winfo_children(): print(widgets) 创建的引用的名称时,这些名称被指定为.!button1 等,但这些不是无效的变量名吗?任何帮助,将不胜感激! :]
  • 它们不是变量名。它们就是通过__str__ 方法将对象表示为字符串的方式。
  • @Random_Pythoneer59,你会建议这个解决方案比你上面给出的更好,因为它可以解决我分别访问每个按钮的问题。
  • 您可以从frame.winfo_children() 获取所有按钮,然后通过预先给它们参数来访问它们。但我更愿意坚持使用列表或字典。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 2012-09-04
  • 1970-01-01
相关资源
最近更新 更多