IntVar().trace() 不工作
Posted
技术标签:
【中文标题】IntVar().trace() 不工作【英文标题】:IntVar().trace() not working 【发布时间】:2017-06-08 17:12:41 【问题描述】:我刚刚开始使用 Python/Tkinter 编写一个小型 Pymol 插件。在这里,我试图有一个切换按钮并在单击它时报告其状态。按钮上下移动,但 toggleAVA
永远不会被调用。任何想法为什么?
from Tkinter import *
import tkMessageBox
class AVAGnome:
def __init__(self, master):
# create frames
self.F1 = Frame(rootGnome, padx=5, pady=5, bg='red')
# checkbuttons
self.AVAselected = IntVar()
self.AVAselected.trace("w", self.toggleAVA)
self.AVAbutton = Checkbutton(self.F1, text='AVA', indicatoron=0, variable=self.AVAselected)
# start layout procedure
self.layout()
def layout(self):
self.F1.pack(side=TOP, fill=BOTH, anchor=NW)
#entry and buttons
self.AVAbutton.pack(side=LEFT)
def toggleAVA(self, *args):
if (self.AVAselected.get()):
avastatus = "selected"
else:
avastatus = "unselected"
tkMessageBox.showinfo("AVA status", avastatus)
def __init__(self):
open_GnomeUI()
def open_GnomeUI():
# initialize window
global rootGnome
rootGnome = Tk()
rootGnome.title('AVAGnome')
global gnomeUI
gnomeUI = AVAGnome(rootGnome)
【问题讨论】:
Checkbutton
有选项command=
所以也许使用command=self.toggleAVA
而不是trace()
是的,但这只是一个非常基本的示例。如果self.AVAselected
通过其他方式,我可能希望更改状态。无论如何,我试图理解为什么应该工作的功能不起作用
另外,我确实尝试过(使用command
),无论按钮是向上还是向下,self.AVAselected
的状态都会报告为unselected
。
我试过你的代码,它作为独立程序工作。如果程序使用两个Tk()
和两个mainloop()
,我在其他程序中看到了类似的变量问题。也许您必须简单地使用Toplevel()
而不是Tk()
来创建窗口。
【参考方案1】:
我使用Pymol
测试了您的代码。
问题是因为您使用Tk()
创建您的窗口。您必须使用Toplevel()
,然后它才能与trace()
或command=
一起正常工作。
Pymol
是用tkinter
创建的,它只能用Tk()
创建一个窗口——它是程序中的主窗口。必须使用Toplevel()
创建所有其他窗口。
【讨论】:
就是这样!有趣的是,我试图通过删除一个已建立的 Pymol 插件并用我自己的功能填充它来避免这样的事情......显然有很多活的脏代码......【参考方案2】:我在下面附上了您的代码的工作版本。你可以参考它来了解你哪里出错了。一般来说,如果你使用类格式,你必须注意你的代码结构。这将帮助你更好地可视化你的代码和调试。你可以阅读这个discussion 来帮助你。
from Tkinter import *
import tkMessageBox
class AVAGnome(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
# create frames
self.F1 = Frame(self, padx=5, pady=5, bg='red')
# checkbutton
self.AVAselected = IntVar()
self.AVAselected.trace("w", self.toggleAVA)
self.AVAbutton = Checkbutton(
self.F1, text='AVA', indicatoron=0, width=10,
variable=self.AVAselected)
# start layout procedure
self.F1.pack(side=TOP, fill=BOTH, anchor=NW)
self.AVAbutton.pack(side=LEFT) #entry and buttons
def toggleAVA(self, *args):
if (self.AVAselected.get()):
avastatus = "selected"
else:
avastatus = "unselected"
tkMessageBox.showinfo("AVA status", avastatus)
if __name__ == '__main__':
rootGnome = Tk()
rootGnome.title('AVAGnome')
gnomeUI = AVAGnome(rootGnome)
gnomeUI.pack(fill="both", expand=True)
gnomeUI.mainloop()
更新:以上代码结构适用于独立的 tkinter 程序。我正在尝试将此工作代码转换为遵循 Pymol 插件示例。修改后的代码发布在下面,可能会进一步修改。
# https://pymolwiki.org/index.php/Plugins_Tutorial
# I adapted from the example in the above link and converted my previous code to
#
from Tkinter import *
import tkMessageBox
def __init__(self): # The example had a self term here.
self.open_GnomeUI()
class AVAGnome(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
# create frames
self.F1 = Frame(self, padx=5, pady=5, bg='red')
# checkbutton
self.AVAselected = IntVar()
self.AVAselected.trace("w", self.toggleAVA)
self.AVAbutton = Checkbutton(
self.F1, text='AVA', indicatoron=0, width=10,
variable=self.AVAselected)
# start layout procedure
self.F1.pack(side=TOP, fill=BOTH, anchor=NW)
self.AVAbutton.pack(side=LEFT) #entry and buttons
def toggleAVA(self, *args):
if (self.AVAselected.get()):
avastatus = "selected"
else:
avastatus = "unselected"
tkMessageBox.showinfo("AVA status", avastatus)
# Note, I added a "self" term throughout function.
# Try w/ & w/o "self" to see which works.
def open_GnomeUI(self):
self.rootGnome = Tk()
self.rootGnome.title('AVAGnome')
self.gnomeUI = AVAGnome(self.rootGnome)
self.gnomeUI.pack(fill="both", expand=True)
self.gnomeUI.mainloop()
【讨论】:
OP 不会创建独立程序,而是为 Pymol 创建可能需要不同结构的插件 - 它可能需要函数__init__
来运行它。(但我不确定)
@furas 感谢您的指出。我的错。话虽如此,我查看了一个 Pymol 插件示例,并尝试转换工作代码以遵循该示例。我希望它有效。我最初会期待一些接口问题,否则我认为类部分应该按原样工作。如果有效,将需要 ipetrik 进行反馈。在上面发布修改后的代码。
@Sun Bear - 谢谢。目前不像发布的那样工作,但它与初始化有关。我会修改并让它与你提供的课程一起工作,然后从那里开始。
P.S.你的第一个代码确实可以作为一个独立的 python 程序工作,所以这是一个开始。以上是关于IntVar().trace() 不工作的主要内容,如果未能解决你的问题,请参考以下文章
使用TRACE_EVENT宏添加Tracepoint(1/3部分)
使用TRACE_EVENT宏添加Tracepoint(1/3部分)
使用TRACE_EVENT宏添加Tracepoint(1/3部分)