如何让脚本等待按下按钮?
How can I make a script wait for a button press?
如果这个问题的答案很明显,我深表歉意,但我不熟悉 Python 的内部工作原理。
基本场景:我有一个 Python 脚本可以做一些事情。定期地,当满足某些条件时(如设置标志变量),我希望脚本暂停并等待用户按下 GUI 按钮。
我该如何实现?
澄清一下,我希望它像 input() 那样工作,因为它暂停一切并等待函数调用被解析,除了我不希望它绑定到文本,而是一个 GUI按钮。我打算使用 Tkinter 制作按钮。
我最初的想法是制作一个类似这样的 while 循环:
x = 2
while (x > 1):
#do nothing
然后按钮将调用一个设置 x = 0 的函数
这是执行此操作的正确方法吗?有没有更好的办法?我是否遗漏了一些明显的东西?
示例代码:
class Displayable(object):
max_display_level = 1 # can be overridden in subclasses
manual_step = False # can be overridden in subclasses
def display(self,level,*args,**kwargs):
-Do stuff unrelated to the question-
if (self.manual_step):
if level <= self.max_display_level:
input("Waiting for input: ")
这背后的想法是对象将扩展 class 可显示对象并设置它们自己的 max_display_level 和 manual_step 值。更高的 max_display_level 意味着将显示更多消息(即,如果我调用 display() 级别 = 1、2、3 和 4,如果我的 max_display_level ==2,则只有前 2 个调用将执行所有逻辑。这是一种允许用户设置执行详细程度的方法。它存在的原因我不会深入,但它应该保留。)如果特定对象具有 manual_step == true 并且水平满足,它应该在调用 display() 时等待用户输入。诀窍是我希望它等待按下按钮而不是文本+输入。
如果您打算使用 GUI 按钮(尤其是 tkinter),您不需要做任何事情 - GUI 倾向于 运行 它们自己的无限循环来处理绘图和处理事件。当你为 tkinter 使用 .mainloop() 时,除了回调和 tkinter 事件之外,代码中的任何内容都不会执行;即:
root= Tk()
root.mainloop()
print("This won't be printed until root window is closed")
最佳做法是将按下按钮时应该发生的事情作为 command/callback 绑定到该按钮。 (Button(master, ... command=callback OR command=lambda *e: callback())
)
如您所愿,我建议在较长的 运行ning 代码开头放置一个 Button.disable()
(这样按钮看起来不可点击),然后是Button.enable()
在最后,所以你可以点击它。或者 create/show 在函数末尾执行下一步的按钮(即时创建该按钮可以让您通过 lambda 将此函数的结果直接传递到下一个函数的回调中)
def cb_1(root_window, btn_to_disable):
btn_to_disable.disable()
foo = complex_algorithm()
# Create a button for the next part
Button(root_window, text='do cb_2 with foo',
command=lambda e, arg=foo, r=root_window: cb_2(r, arg)).pack()
def cb_2(root, argument):
print("This is foo, from cb_1:",argument) # prints foo
root = Tk()
btn = Button(root, text="do cb_1",
command=lambda *e: cb_1(root, btn))
btn.pack()
root.mainloop()
print("This isn't printed until the GUI is closed!")
编辑:根据您的最新编辑,似乎 after()
将成为您的朋友 - 它允许函数通过 tkinter 的主循环再次安排自己,而不会阻止 GUI 的操作。即在 Displayable
:
def display(self, level, *args, **kwargs):
#unrelated#
self.wait_for_next(level, *args, **kwargs)
def wait_for_next(self, level, *args, **kwargs)
if self.manual_step:
if (level <= self.max_display_level):
if self.button_set_value:
# Do something with button-set value
print('FOO')
else:
# set ourselves to re-check after 1000 ms
self.root.after(1000,
lambda *e:self.wait_for_next(level, *args, **kwargs))
大概,无论您的按钮在哪里,它们都会设置一些值(或只是设置一个标志)。当该值为真时,将打印 "FOO"
。此时您可能会再次调用 display()。
另一种方法是简单地将 display()
作为按钮的回调,因此当按下按钮时,将调用 display
。
如果这个问题的答案很明显,我深表歉意,但我不熟悉 Python 的内部工作原理。
基本场景:我有一个 Python 脚本可以做一些事情。定期地,当满足某些条件时(如设置标志变量),我希望脚本暂停并等待用户按下 GUI 按钮。
我该如何实现?
澄清一下,我希望它像 input() 那样工作,因为它暂停一切并等待函数调用被解析,除了我不希望它绑定到文本,而是一个 GUI按钮。我打算使用 Tkinter 制作按钮。
我最初的想法是制作一个类似这样的 while 循环:
x = 2
while (x > 1):
#do nothing
然后按钮将调用一个设置 x = 0 的函数
这是执行此操作的正确方法吗?有没有更好的办法?我是否遗漏了一些明显的东西?
示例代码:
class Displayable(object):
max_display_level = 1 # can be overridden in subclasses
manual_step = False # can be overridden in subclasses
def display(self,level,*args,**kwargs):
-Do stuff unrelated to the question-
if (self.manual_step):
if level <= self.max_display_level:
input("Waiting for input: ")
这背后的想法是对象将扩展 class 可显示对象并设置它们自己的 max_display_level 和 manual_step 值。更高的 max_display_level 意味着将显示更多消息(即,如果我调用 display() 级别 = 1、2、3 和 4,如果我的 max_display_level ==2,则只有前 2 个调用将执行所有逻辑。这是一种允许用户设置执行详细程度的方法。它存在的原因我不会深入,但它应该保留。)如果特定对象具有 manual_step == true 并且水平满足,它应该在调用 display() 时等待用户输入。诀窍是我希望它等待按下按钮而不是文本+输入。
如果您打算使用 GUI 按钮(尤其是 tkinter),您不需要做任何事情 - GUI 倾向于 运行 它们自己的无限循环来处理绘图和处理事件。当你为 tkinter 使用 .mainloop() 时,除了回调和 tkinter 事件之外,代码中的任何内容都不会执行;即:
root= Tk()
root.mainloop()
print("This won't be printed until root window is closed")
最佳做法是将按下按钮时应该发生的事情作为 command/callback 绑定到该按钮。 (Button(master, ... command=callback OR command=lambda *e: callback())
)
如您所愿,我建议在较长的 运行ning 代码开头放置一个 Button.disable()
(这样按钮看起来不可点击),然后是Button.enable()
在最后,所以你可以点击它。或者 create/show 在函数末尾执行下一步的按钮(即时创建该按钮可以让您通过 lambda 将此函数的结果直接传递到下一个函数的回调中)
def cb_1(root_window, btn_to_disable):
btn_to_disable.disable()
foo = complex_algorithm()
# Create a button for the next part
Button(root_window, text='do cb_2 with foo',
command=lambda e, arg=foo, r=root_window: cb_2(r, arg)).pack()
def cb_2(root, argument):
print("This is foo, from cb_1:",argument) # prints foo
root = Tk()
btn = Button(root, text="do cb_1",
command=lambda *e: cb_1(root, btn))
btn.pack()
root.mainloop()
print("This isn't printed until the GUI is closed!")
编辑:根据您的最新编辑,似乎 after()
将成为您的朋友 - 它允许函数通过 tkinter 的主循环再次安排自己,而不会阻止 GUI 的操作。即在 Displayable
:
def display(self, level, *args, **kwargs):
#unrelated#
self.wait_for_next(level, *args, **kwargs)
def wait_for_next(self, level, *args, **kwargs)
if self.manual_step:
if (level <= self.max_display_level):
if self.button_set_value:
# Do something with button-set value
print('FOO')
else:
# set ourselves to re-check after 1000 ms
self.root.after(1000,
lambda *e:self.wait_for_next(level, *args, **kwargs))
大概,无论您的按钮在哪里,它们都会设置一些值(或只是设置一个标志)。当该值为真时,将打印 "FOO"
。此时您可能会再次调用 display()。
另一种方法是简单地将 display()
作为按钮的回调,因此当按下按钮时,将调用 display
。