#python #python-3.x #user-interface #tkinter
Вопрос:
#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()
функции, я хотел бы, чтобы кнопка удаления вызывала это при нажатии.
Меня бы устроило все, что угодно, либо удаление всех таблиц (кнопок) сразу, либо удаление каждой таблицы (кнопки) по одной при нажатии. Я также хотел бы знать, как получить доступ к каждой таблице (кнопке), которая была создана отдельно, потому что я хочу, чтобы у них были свои собственные атрибуты.
Комментарии:
1. Не по теме: Вы можете удалить команду, связанную с кнопкой создать таблицу, с помощью
newtablebtn.configure(command=None)
или дажеnewtablebtn.configure(command=lambda: None)
.2. Большое спасибо! Я забыл, что ключевое слово null было в java, а не в python :]
3. @martineau, если вы хотите, чтобы команда была none. Вы просто не могли его установить. По умолчанию его нет. Просто опустите строку
newtablebtn.configure(command=None)
.4. @Random_Pythoneer59: В коде операции они отключают команду, которая ранее была настроена на что-то чрезмерно сложным образом, поэтому я сделал свой комментарий.
5. @martineau О, боже мой, как плохо.
Ответ №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)
(без скобок).
Комментарии:
1. Привет! Большое спасибо, это действительно решило мою проблему!! У меня есть еще одно сомнение, что делать, если я хочу получить доступ к каждой из этих кнопок, которые создаются отдельно и дают свои собственные характеристики. Должен ли я перебирать список таблиц, чтобы получить имена объектов кнопок, а затем назначить их атрибуты?
2. ДА. Вы можете просмотреть список и назначить свои атрибуты. Вы могли бы присвоить им номер с
btn.number = 1
помощью . А затем повторите список, найдите свой btn и измените его атрибуты по своему усмотрению. Вы также можете использовать словарь, какbtns_dict = {1: btn1, 2: btn2}
тогда, при удалении, вы можете использоватьbtns_dict.value()
и удалять их. И очистите диктант сbtns_dict.clear()
помощью .3. Привет еще раз, я изменил переменную, хранящую кнопки, на дикт вместо списка.
for table in tables.items(): print(table)
Поэтому вывод этого кода был(1, <tkinter.Button object .!button3>)
таким: как мне получить доступ к этой кнопке. а также что вы подразумеваете подbtns_dict = {1: btn1, 2: btn2}
тем, как btn1 может ссылаться на первую кнопку, которую я создал. и еще одна вещьbtn.number=1
, куда девается код? У меня много сомнений 🙁 Я получил часть об удалении, так что большое спасибо за это :]4. Если вы хотите отредактировать первую кнопку, то вы можете сделать это как —
btn1 = btns_dict[1]
и вы получите кнопку с клавишей 1. И так далее…5.
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()
Комментарии:
1. Привет! Большое спасибо, я проверил это решение, и это тоже решило мою проблему! Подобно моему комментарию к ответу @Random_Pythoneer59, я хочу знать, есть ли способ получить доступ к объектам кнопок, не проходя через
frame1.winfochildren()
деталь. А также, когда я проходил по циклу, чтобы узнать имена ссылок, созданных сfor widgets in frame1.winfo_children(): print(widgets)
именами, которые были заданы как.!button1
и т.д., Но разве это не недопустимые имена переменных? Любая помощь будет признательна! :]2. Это не имена переменных. Они просто представляют объект в виде строки с помощью
__str__
метода.3. @Random_Pythoneer59, не могли бы вы предложить, чтобы это решение было лучше, чем то, что вы дали выше, с точки зрения того, что могло бы решить мою проблему доступа к каждой кнопке отдельно.
4. Вы могли бы получить доступ ко всем кнопкам
frame.winfo_children()
и получить к ним доступ, предварительно указав их параметры. Но я бы предпочел придерживаться списков или диктовок.