python - How to access individual Button tkinter?
问题描述
Goal : dynamically create label and button (represents a task) and when I click this button it should destroy the label and button.
Problem : Unable to access buttons individually
Here is my code :
class Gui:
# constructor
def __init__(self, root):
self.root = root
self.root.title("TASKS")
self.root.geometry("300x700")
self.root.resizable(width=False, height=False)
self.clock = Label(self.root, fg="blue")
self.clock.grid(row = 0,column = 0,padx = 80,pady = 40)
self.update_clock()
self.new_button = Button(self.root, text="New",command = self.newwindow).grid(row = 0, column =1)
self.r =0
# clock
def update_clock(self):
now = strftime("%H:%M:%S")
self.clock.configure(text=now)
self.clock.after(1000, self.update_clock)
# label creator
def label(self, txt):
self.l = Label(self.root, text=txt, fg="red",pady =15)
self.l.grid(row = self.r, column =0)
# button creator
def donebutton(self):
self.b = Button(self.root, text="Done",command = lambda : self.del_task())
self.b.grid(row = self.r,column = 1)
# create a task
def task(self,txt):
self.r +=1
self.label(txt)
self.donebutton()
# delete task
def del_task(self):
self.l.destroy()
self.b.destroy()
# display gui method
def display(self):
self.root.mainloop()
# new window
def newwindow(self):
self.newwindow = Toplevel(self.root)
self.newwindow.title("NEW TASK")
self.newwindow.geometry("300x200")
self.newwindow.resizable(width=False, height=False)
Label(self.newwindow,text="Task").grid()
self.t1 = Text(self.newwindow,height = 2,width = 36)
self.t2 = Text(self.newwindow,height = 2,width = 10)
self.t1.grid()
Label(self.newwindow, text="Time").grid()
self.t2.grid()
self.c_b=Button(self.newwindow,text = "CREATE",command = lambda : self.task(self.t1.get("1.0",END)))
self.c_b.grid()
if __name__ == '__main__':
a = Gui(Tk())
a.display()
Requesting help with the code and I do not mind changing the whole code.
解决方案
You keep overwriting the button. You said you don't care if the code is written completely different so, I changed a bunch.
- Windows, Clock and Tasks are separated into classes
- no targetable references to windows or buttons are held
- the
command
for the "New Button" creates theNewTasks
window - the
command
for the "Done Button" destroys its parent - the
command
for the "Create Button" creates aTask
in the main window - a scrollable frame was added so tasks can never vertically overflow the main window
- start, pause, done and remove
Buttons
were included - a scrollable output panel was included
- ability to reposition tasks in the display is included
- task labels can be clicked to show their content in the output panel
- start, pause and done report to the output, and done includes elapsed time
- once a task is started it cannot be removed
- a task can only be "done" if it is running
- a modicum of widget/grid formatting was applied to stop the display from jumping around as tasks were created/removed
I got bored and built your app ... probably.
from tkinter import Tk, Button, Label, Toplevel, Text, Frame, Canvas, Scrollbar
from time import strftime, time
class Task(Frame):
def __init__(self, master, text, output, move, **kwargs):
Frame.__init__(self, master, **kwargs)
self.grid_columnconfigure(0, weight=1)
self.stored = []
self.starttime = 0
self.send_output= output
self.lbl = Label(self, text=text, height=1, anchor='nw', fg='blue', font='calibri 14')
self.lbl.grid(row=0, column=0, sticky='nswe')
self.lbl.bind('<1>', self.output)
font = 'consolas 10 bold'
self.b1 = Button(self, font=font, text=chr(9654), command=self.start)
self.b2 = Button(self, font=font, text=chr(10073)+chr(10073), state='disabled', command=self.pause)
self.b3 = Button(self, font=font, text=chr(10006), state='disabled', command=self.done)
self.b4 = Button(self, font=font, text=chr(9866), command=self.destroy)
self.b5 = Button(self, font=font, text=chr(9650), command=lambda: move(self, -1))
self.b6 = Button(self, font=font, text=chr(9660), command=lambda: move(self, 1))
self.b1.grid(row=0, column=1) #start
self.b2.grid(row=0, column=2) #pause
self.b3.grid(row=0, column=3) #done
self.b4.grid(row=0, column=4) #remove
self.b5.grid(row=0, column=5) #move up
self.b6.grid(row=0, column=6) #move down
def start(self):
self.b1['state'] = 'disabled'
self.b2['state'] = 'normal'
self.b3['state'] = 'normal'
self.b4['state'] = 'disabled'
self.starttime = time()
self.send_output(f"{self.lbl['text']}", f"{strftime('%I:%M:%S')} STARTED: ")
def pause(self):
self.b1['state'] = 'normal'
self.b2['state'] = 'disabled'
self.b3['state'] = 'disabled'
self.stored.append(time() - self.starttime)
self.send_output(f"{self.lbl['text']}", f"{strftime('%I:%M:%S')} PAUSED: ")
def done(self):
self.stored.append(time() - self.starttime)
t = sum(self.stored)
self.send_output(f"{self.lbl['text']}\telapsed time: {self.etime(t)}\n", f"{strftime('%I:%M:%S')} FINISHED: ")
self.destroy()
def etime(self, s):
h = int(s//3600)
s -= 3600*h
m = int(s//60)
s -= 60*m
return f'{h:02}:{m:02}:{int(s):02}'
def output(self, event):
self.send_output(self.lbl['text'], 'Task: ')
class NewTasks(Toplevel):
WIDTH = 416
HEIGHT = 50
def __init__(self, master, slave, output, move, **kwargs):
Toplevel.__init__(self, master, **kwargs)
self.title("New Task")
self.geometry(f'{NewTasks.WIDTH}x{NewTasks.HEIGHT}')
self.resizable(width=False, height=False)
Label(self, text="Task").grid(row=0, column=0)
txt = Text(self, height=2, width=36, font='consolas 12')
txt.grid(row=0, column=1)
Button(self, text="CREATE", command=lambda: self.create(slave, output, move, txt)).grid(row=0, column=2, sticky='e', padx=4, pady=12)
def create(self, target, output, move, txt):
t = Task(target.frame, txt.get("1.0",'end'), output, move)
t.grid(column=0, sticky='nswe')
target.update(t)
class ScrollFrame(Canvas):
def __init__(self, master, **kwargs):
Canvas.__init__(self, master, **kwargs)
vsb = Scrollbar(self, orient='vertical', command=self.yview)
vsb.pack(side='right', fill='y')
self.configure(yscrollcommand=vsb.set)
self.frame = Frame(self, height=0)
self.frame.grid_columnconfigure(0, weight=1)
self.frame.bind('<Configure>', lambda e:self.configure(scrollregion=self.bbox("all")))
self.create_window((0,0), width=App.WIDTH-20, window=self.frame, anchor="nw")
self.movelist = []
def update(self, target):
self.movelist.append(target)
def move_item(self, elem, dir=1):
c = self.frame.winfo_children()
i = self.movelist.index(elem)
if i+dir in range(0, len(self.movelist)):
e = self.movelist.pop(i)
self.movelist.insert(i+dir, e)
for n in range(len(self.movelist)):
while n < len(self.movelist) and self.movelist[n] not in c:
self.movelist.pop(n)
if n < len(self.movelist):
self.movelist[n].grid(row=n, column=0, sticky='nswe')
continue
break
class Clock(Label):
def __init__(self, master, **kwargs):
Label.__init__(self, master, **kwargs)
self.update()
def update(self):
self['text'] = strftime('%I:%M:%S')
self.after(1000, self.update)
class App(Tk):
WIDTH = 600
HEIGHT = 447
def __init__(self, **kwargs):
Tk.__init__(self, **kwargs)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
Clock(self, fg="blue", font='calibri 18').grid(row=0, column=0, ipady=10, sticky='nswe')
sf = ScrollFrame(self, highlightthickness=0)
sf.grid(row=1, column=0, columnspan=3, sticky='nswe')
command = lambda: NewTasks(self, sf, self.output, sf.move_item)
Button(self, text="New", font='calibri 12', command=command).grid(row=0, column=1, columnspan=2)
self.out = Text(self, height=8, font="calibri 14")
self.out.grid(row=2, column=0, columnspan=2)
self.out.tag_configure("bold", font="calibri 12 bold")
vsb = Scrollbar(self, orient='vertical', command=self.out.yview)
vsb.grid(row=2, column=2, sticky='ns')
self.out.configure(yscrollcommand=vsb.set)
def output(self, text, btext=''):
self.out.insert('end', btext, 'bold')
self.out.insert('end', text)
if __name__ == '__main__':
app = App()
app.title("Task Scheduler")
app.geometry(f'{App.WIDTH}x{App.HEIGHT}')
app.resizable(width=False, height=False)
app.mainloop()
推荐阅读
- android - 多次调用Android Vibrator振动功能停止振动
- windows - 无法在您的路径中找到liquidsoap_binary
- ajax - 在所有图像加载之前显示 ajax 调用成功
- python - NLTK WordNetLemmatizer 中的多线程?
- mongodb - 我们如何在 MongoDB shell 中更新数组对象值
- go - http.Server.ListenAndServe 崩溃“逗号太多”仅在 Minikube 上
- wordpress - Wordpress 音频播放器只播放第一个附件
- javascript - 旧 VB .Net 应用程序和 Javascript 事件中的回发
- python - 比较 Pandas 系列和 Python 列表之间的数据
- excel - 如果存在特殊字符,则删除单元格?