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() 不工作的主要内容,如果未能解决你的问题,请参考以下文章

Trace32 ubuntu(linux) 下的安装

使用TRACE_EVENT宏添加Tracepoint(1/3部分)

使用TRACE_EVENT宏添加Tracepoint(1/3部分)

使用TRACE_EVENT宏添加Tracepoint(1/3部分)

使用TRACE_EVENT宏添加Tracepoint(1/3部分)

来自文件的 C# Stackdriver Trace 凭据