【问题标题】:How can I listen for a button press in Tkinter如何在 Tkinter 中收听按钮按下
【发布时间】:2011-03-22 14:32:26
【问题描述】:

如何在 Tkinter 中监听按钮按下?我需要监听按钮而不是运行函数,但我想运行监听按钮的函数。

更新 代码如下:

#!/usr/bin/env python
import time
import thread

from Tkinter import *

class at(Frame):
    def __init__(self, *args, **params):
    ## Standard heading: initialization
    apply(Frame.__init__, (self,) + args, params)
    self._parent = None
    if len(args) != 0: self._parent = args[0]
    self._init_before()
    self.v = StringVar()
    ## Widget creation
    self._widgets = {}
    self._widgets['button#1'] = Button(self, name='button#1', text='up',)
    self._widgets['button#1'].grid(column=1, row=1)
    self._widgets['entry#1'] = Entry(self, name='entry#1', textvariable=self.v)
    self._widgets['entry#1'].grid(column=2, row=1)
    self._widgets['button#2'] = Button(self, name='button#2', text='down',)
    self._widgets['button#2'].grid(column=1, row=2)
    ## Scroll commands
    ## Resize behavior(s)
    self.grid_rowconfigure(1, weight=0, minsize=30)
    self.grid_rowconfigure(2, weight=0, minsize=31)
    self.grid_columnconfigure(1, weight=0, minsize=30)
    self.grid_columnconfigure(2, weight=0, minsize=65)
    self.pack(side=TOP, fill=BOTH, expand=1)
    ## Call to post-init method
    self._init_after()

  def _init_before(self):
    self._init_specificBefore()

  def _init_after(self):
    self._init_specificAfter()

  def u(self):
    if self.listening==True:
        self.u=True
        self.listening=False

  def d(self):
    if self.listening==True:
        self.d=True
        self.listening=False

  def listen(self):
    #listen for self.u and self.d

  def _init_specificBefore(self):
    pass

  def _init_specificAfter(self):
        range=[0,100]
    current_guess=range[1]/2
    n=1
    x=""
    while 1:
    self.v.set(str(current_guess)+"?")
    x=self.listen()
    if x=="u":
        range[0]=current_guess
        if range[0]==0:
            current_guess=round(current_guess+round(range[1]/2))
        else:
            current_guess=round(current_guess+round((range[1]-range[0])/2))
    elif x=="d":
        range[1]=current_guess
        if range[0]==0:
            current_guess=round(round(range[1]/2))
        else:
            current_guess=range[0]+(round((range[1]-range[0])/2))
    elif x=="y":
        print "It took me "+str(n)+" guesses."
        break
    n=n+1



if __name__ == '__main__':
  root = Tk()
  o = at(root)
  o.pack(side=TOP, fill=BOTH, expand=1)
  root.mainloop()

【问题讨论】:

  • 什么?!?听起来有点像戴帽子的猫在学习 Python 时会说的话……我认为您正在寻找某种事件循环?
  • 听起来您想创建自己的事件循环,但目的是什么? Tkinter 已经有一个完美可用的事件循环。为什么你认为你需要自己写?也许如果您能更好地了解您要完成的工作,我们可以给您一个体面的答案。
  • 你的代码缩进搞砸了——那个代码不能像发布的那样工作。

标签: python button tkinter listener


【解决方案1】:

您要完成的工作尚不清楚,但听起来您误解了 GUI 编程的一般工作原理,并且只是提出了错误的问题。一般来说,如果您认为需要轮询按钮按下而不是利用事件循环,那您就错了。

因此,“我如何才能监听按钮而不运行函数”的最佳答案是“你不能”。这有点像在问“我怎样才能用锤子把这个螺丝钉在墙上?”。你可以,但它不是使用该工具的正确方法,因此出于所有实际目的,你不能也不应该被教如何使用。

在我看来,您正在做一个猜谜游戏,并且我认为您希望用户在每次猜测后按下向上或向下按钮。那是对的吗?如果是这样,为什么不让向上和向下按钮调用一个进行单一猜测的函数呢?

【讨论】:

  • @jmeyer10 我会同意这一点。对于提供的示例,您对此进行了大量过度工程。只需调用一个函数,你就完成了。虽然在某些情况下我的解决方案是必要的(我仍然希望删除反对票),但这确实是基本的东西。
  • 我同意,但在我的程序中,没有真正的事件循环
  • @jmeyer10:“没有真正的事件循环”是什么意思?你认为root.mainloop() 是什么? 所有 GUI 程序都有事件循环。它们不仅用于用户事件(按钮按下等),而且当窗口被覆盖或未覆盖、调整大小等时,小部件知道如何重绘自己。你有一个事件循环,所以使用它。
【解决方案2】:

您需要沿着while not exiting 的行创建一个循环,其中exiting 在开始时被声明为False,并在退出应用程序时被切换。然后在该循​​环中,您可以放置​​检查某些状态并更新其他状态的函数。每次循环它都会运行这些函数中的每一个。神奇的是让这些函数中的每一个都足够快,以至于它们看起来像是在不断地运行。

【讨论】:

  • 非常糟糕的建议。 GUI 已经在运行一个循环,即事件循环。根本没有理由编写自己的无限循环。
  • @Bryan 有时你不想用长时间的操作来阻塞 gui,结果证明它们是不可避免的。然后它会派上用场,以适应制作自己的事件循环。请删除我的反对票。
  • @BiggAl:有比这更好的解决方案。我不知道在 python 中是否可行,但大多数语言中普遍接受的方法是为长时间运行的后台任务启动一个新线程。
  • @BiggAl 我犯了同样的错误。我尝试启动程序,但它无法启动!
  • @Bryan 我认为你没有在 python 中尝试过这个,否则你会遇到 GIL,所以你需要使用进程,所以你需要一种更重量级的方式来与它们通信- 大多数情况下,您最终会得到至少一个事件循环。
猜你喜欢
  • 2017-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-23
  • 1970-01-01
相关资源
最近更新 更多