使用 window.after 将函数的返回值分配给变量
我正在学习 100 Days of Code: Python 中的第 89 天。我需要构建一个 Tkinter 应用程序,持续监视文本输入,如果检测到 10 秒内没有输入任何内容,则会删除代码。我尝试使用以下代码来执行此操作:
def get_wordcount(self):
start_num_char = len(self.entry_box.get(1.0, "end-1c"))
new_num_char = self.after(5000, self.get_wordcount)
if new_num_char <= start_num_char:
return True
else:
return False
我也尝试过:
def get_wordcount(self):
start_num_char = len(self.entry_box.get(1.0, "end-1c"))
new_num_char = self.after(5000, len(self.entry_box.get(1.0, "end-1c")))
if new_num_char <= start_num_char:
return True
else:
return False
问题是 new_num_char 等于“after#0”、“after#1”、“after#2”等,而不是等于新字符数。如何获取每五秒的新字数?如果我这样做:
def get_wordcount(self):
start_num_char = len(self.entry_box.get(1.0, "end-1c"))
self.after(5000)
new_num_char = len(self.entry_box.get(1.0, "end-1c")
if new_num_char <= start_num_char:
return True
else:
return False
这只会冻结整个窗口,并且在五秒钟结束之前我无法在输入框中键入内容。我真的很感激对此的一些帮助;这几天我一直在试图弄清楚。完整代码如下:
from tkinter import *
from tkinter.scrolledtext import ScrolledText
class App(Tk):
def __init__(self):
super().__init__()
self.title("Focus Writer")
self.background_color = "#EAF6F6"
self.config(padx=20, pady=20, bg=self.background_color)
self.font = "Arial"
self.start = False
self.time_left = 10
self.title_label = Label(text="Focus Writer",
bg=self.background_color,
font=(self.font, 26))
self.title_label.grid(row=0, column=0, columnspan=2)
self.explain = Label(text="Welcome to the Focus Writer app. You need to continuously input content in order to "
"keep the app from erasing your data. If the app detects that you haven't written "
"anything for more than 10 seconds, it will wipe everything, and you will need to "
"start over. \n\nPress the start button when you are ready to begin.\n",
bg=self.background_color,
font=(self.font, 18),
wraplength=850,
justify="left",)
self.explain.grid(row=1, column=0, columnspan=2)
self.start_img = PhotoImage(file="play-buttton.png")
self.start_button = Button(image=self.start_img,
height=50,
command=self.check_writing)
self.start_button.grid(row=2, column=0)
self.time_left_label = Label(text=self.time_left,
bg=self.background_color,
font=(self.font, 36))
self.time_left_label.grid(row=2, column=1)
self.entry_box = ScrolledText(width=80,
height=20,
wrap=WORD,
font=(self.font, 14))
self.entry_box.grid(row=3, column=0, columnspan=2)
def countdown(self):
if self.time_left > 0:
self.time_left -= 1
self.time_left_label.configure(text=self.time_left)
self.after(1000, self.countdown)
else:
if self.get_wordcount():
self.entry_box.delete(1.0, "end-1c")
else:
self.time_left = 0
return False
def get_wordcount(self):
start_num_char = len(self.entry_box.get(1.0, "end-1c"))
new_num_char = self.after(5000, len(self.entry_box.get(1.0, "end-1c")))
if new_num_char <= start_num_char:
return True
else:
return False
def check_writing(self):
self.start = True
self.start_button["state"] = DISABLED
self.entry_box.focus()
self.get_wordcount()
app = App()
app.mainloop()
I'm working on day 89 of 100 Days of Code: Python. I need to build a Tkinter app that constantly monitors a text entry and will delete the code if it detects that nothing's been typed for 10 seconds. I've tried to do so using this code:
def get_wordcount(self):
start_num_char = len(self.entry_box.get(1.0, "end-1c"))
new_num_char = self.after(5000, self.get_wordcount)
if new_num_char <= start_num_char:
return True
else:
return False
I have also tried:
def get_wordcount(self):
start_num_char = len(self.entry_box.get(1.0, "end-1c"))
new_num_char = self.after(5000, len(self.entry_box.get(1.0, "end-1c")))
if new_num_char <= start_num_char:
return True
else:
return False
The problem is that new_num_char equals "after#0", "after#1", "after#2", etc. instead of equaling the new character count. How can I grab the new word count every five seconds? If I do:
def get_wordcount(self):
start_num_char = len(self.entry_box.get(1.0, "end-1c"))
self.after(5000)
new_num_char = len(self.entry_box.get(1.0, "end-1c")
if new_num_char <= start_num_char:
return True
else:
return False
This just freezes the whole window and I can't type into the entry box until the five seconds are up. I'd really appreciate some help on this; I've been trying to figure it out for a few days now. Full code below:
from tkinter import *
from tkinter.scrolledtext import ScrolledText
class App(Tk):
def __init__(self):
super().__init__()
self.title("Focus Writer")
self.background_color = "#EAF6F6"
self.config(padx=20, pady=20, bg=self.background_color)
self.font = "Arial"
self.start = False
self.time_left = 10
self.title_label = Label(text="Focus Writer",
bg=self.background_color,
font=(self.font, 26))
self.title_label.grid(row=0, column=0, columnspan=2)
self.explain = Label(text="Welcome to the Focus Writer app. You need to continuously input content in order to "
"keep the app from erasing your data. If the app detects that you haven't written "
"anything for more than 10 seconds, it will wipe everything, and you will need to "
"start over. \n\nPress the start button when you are ready to begin.\n",
bg=self.background_color,
font=(self.font, 18),
wraplength=850,
justify="left",)
self.explain.grid(row=1, column=0, columnspan=2)
self.start_img = PhotoImage(file="play-buttton.png")
self.start_button = Button(image=self.start_img,
height=50,
command=self.check_writing)
self.start_button.grid(row=2, column=0)
self.time_left_label = Label(text=self.time_left,
bg=self.background_color,
font=(self.font, 36))
self.time_left_label.grid(row=2, column=1)
self.entry_box = ScrolledText(width=80,
height=20,
wrap=WORD,
font=(self.font, 14))
self.entry_box.grid(row=3, column=0, columnspan=2)
def countdown(self):
if self.time_left > 0:
self.time_left -= 1
self.time_left_label.configure(text=self.time_left)
self.after(1000, self.countdown)
else:
if self.get_wordcount():
self.entry_box.delete(1.0, "end-1c")
else:
self.time_left = 0
return False
def get_wordcount(self):
start_num_char = len(self.entry_box.get(1.0, "end-1c"))
new_num_char = self.after(5000, len(self.entry_box.get(1.0, "end-1c")))
if new_num_char <= start_num_char:
return True
else:
return False
def check_writing(self):
self.start = True
self.start_button["state"] = DISABLED
self.entry_box.focus()
self.get_wordcount()
app = App()
app.mainloop()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我会用另一种方式解决这个问题。创建函数会取消之前任何清除该函数的尝试,然后安排在 10 秒内调用该函数。然后,创建一个绑定,在每次按键释放时调用此按钮。整个机制只需要六行代码。
这是一个例子:
I would solve this another way. Create a function cancels any previous attempt to clear the function and then schedules this function to be called in 10 seconds. Then, create a binding that calls this button on every key release. The entire mechanism takes only a half dozen lines of code.
Here's an example:
首先,我将分成两个函数
,第一个函数设置
self.start_num_char
并在一段时间后运行self.get_wordcount()
第二个函数 (self.get_wordcount) 获取
new_num_char< /code>,与
self.start_num_char
进行比较 - 但它不使用return
- 它直接重置计时器 -self.time_left = 10
- 当条目中的文本较长(或更短)时。最后,它将new_num_char
保留在self.start_num_char
中,并在短时间内再次运行,同时计数器显示新时间并清理
entry
当 < code>self.time_left is0
仅当您不输入时才计算 10 秒。
但它有一个小问题 - 因为
counter
和get_wordcount
单独运行,所以有时counter
在时将时间更改为
正在重置变量,它可以显示9
>get_wordcount9
但不应该。也许它应该使用实时,并且应该保留按下最后一个键时的时间,并使用该值来计算计数器。编辑:
您可以尝试使用
self.entry_box.bind('<>', function)
来执行function(event)< /code> 文本更改时。但在我的 Linux 上,它仅在第一次更改时运行。
编辑:
我添加了
time.time()
来检查更改之间的时间,现在它可以更好地显示计数器。First I would split in two functions
First which set
self.start_num_char
and runself.get_wordcount()
after some timeSecond (self.get_wordcount) which get
new_num_char
, compare withself.start_num_char
- but it doesn't usereturn
- it directly resets timer -self.time_left = 10
- when text in entry is longer (or shorter). And finally it keepnew_num_char
inself.start_num_char
and runs again after short timeAnd at the same time counter display new time and clean
entry
whenself.time_left
is0
This count 10 seconds only when you don't type.
But it has small problem - because
counter
andget_wordcount
run separatelly so sometimescounter
changes time to9
whenget_wordcount
is reseting variable and it can display9
but it shouldn't. Maybe it should use real time and it should keep time when last key was pressed and use this value to calculate counter.EDIT:
You may try to use
self.entry_box.bind('<<Modified>>', function)
to executefunction(event)
when text was changed. But on my Linux it runs only on first change.EDIT:
I added
time.time()
to check time betwin changes and now it better display counter.