草庐IT

关于 python:Tkinter 参数通过私有属性传递给处理程序 – 可以吗?

codeneng 2023-03-28 原文

Tkinter argument passing to handler via private attributes - is this OK?

我已经看到了几种将附加参数传递给以不同方式使用package函数的 Tkinter 事件处理程序的解决方案。但是对于在事件中传递一些额外静态数据的简单情况,这样做有什么缺点:

widget.my_private_attribute = my_private_data

并在事件处理程序中从事件中恢复数据:

private_data = event.widget.my_private_attribute

我已经尝试过了,它可以工作,但它没有出现在我见过的任何建议的解决方案中,所以我担心存在一些我不知道的缺点。

这是一个代码示例。重新评论"私人"的含义,我想这是误导。我的意思是"由我组成,不是标准的 tk 属性之一"。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
:
:
def onClickPosition(event):
    print"you clicked on", event.widget.grid_position
    if event.widget.cget("bg") =="red":
        event.widget.config(bg="yellow")
    else:
        event.widget.config(bg="red")

root = tk.Tk()

buttonList = []

for i in range(16):
    for j in range(16):
        square = tk.PhotoImage(file="small_square_30x30pix.gif")
        l = tk.Label(root, image=square, borderwidth=0, bg="yellow")
        l.save_image = square
        l.grid_position=(i,j)
        l.bind("<1>", onClickPosition)
        l.grid(row=i, column=j)
        buttonList.append(l)
:
:

"grid_position"是我所指的数据。

我在以下位置看到了解决方案的几种变体:

http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/extra-args.html

但我的做法似乎更简单。

  • "私人的"?你是什??么意思,"私人"?无论如何,我会将数据存储在有意义的地方。如果它无助于形成小部件,它不应该是小部件的属性。发布一个小代码示例来描述问题以及您如何处理它。
  • 对不起,代码的格式不好,这是我第一次来这里,我在编辑器上苦苦挣扎
  • 啊……我想现在修好了


如果值在任何有意义的意义上"属于"小部件,那么是的,不仅将其作为属性附加是安全的,而且是惯用的。

文档中有很多例子。

一方面,每个使用子类化 Frame 的"标准 Tkinter OO 习惯用法"在 __init__ 方法或其他地方添加属性的示例都在做你正在做的事情。您没有子类的事实无关紧要。这是同一个想法。

如果您不购买,请参阅 Tkinter Book 的 PhotoImage 页面:

Note: When a PhotoImage object is garbage-collected by Python (e.g. when you return from a function which stored an image in a local variable), the image is cleared even if it’s being displayed by a Tkinter widget.

To avoid this, the program must keep an extra reference to the image object. A simple way to do this is to assign the image to a widget attribute, like this:

1
2
3
label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()

label 不是 label 的子类,它有另一个名为 image 的属性,它只是一个 label,我们只是动态添加了另一个属性,这很好。

这只是我在浏览几秒钟后发现的第一个例子。

但也可以将值"部分"放入回调本身,就像 TigerhawkT3 的回答一样。*

* 事实上,我相信这是让 Guido 相信 Python 3.x 仍然需要 lambdapartial 的论点之一。

那么,您如何决定使用哪一个?这是一个判断电话。以下是我的想法:

  • 该值自然是小部件的成员,还是那种延伸?
  • 您是否已经在使用小部件子类?
  • 您是否有多个回调都需要访问相同的值?
  • 是否可以想象该值还有其他用途(例如,在调试输出中),或者这没有任何意义?

如果这些都没有帮助,那么您最终需要一些默认策略来处理密切判断调用。我喜欢两种方式都写,然后看看哪个看起来更易读,或者想象一下向刚刚注册帮助我维护代码的新手解释这两种方式。如果我仍然无法决定,我在交互式解释器中输入 random.random() < 0.5。 :)


代替:

1
2
3
4
5
6
7
l.grid_position=(i,j)
l.bind("<1>", onClickPosition)

...

def onClickPosition(event):
    print"you clicked on", event.widget.grid_position

尝试:

1
2
3
4
5
6
l.bind("<1>", lambda event, i=i, j=j: onClickPosition(event, i, j))

...

def onClickPosition(event, i, j):
    print"you clicked on", (i,j)

lambda 定义了一个内联匿名函数,允许我们向 onClickPosition() 发送更多参数。将 i=i, j=j 放入定义中会使这些变量在定义函数时而不是在调用函数时解析 - lambda event, i, j 将始终产生 (15, 15).

的点击位置

有关关于 python:Tkinter 参数通过私有属性传递给处理程序 – 可以吗?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  3. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  4. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  5. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  6. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  7. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  8. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  9. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  10. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

随机推荐