Python Tk/Tkinter中的事件流故障

Python Tk/Tkinter中的事件流故障,python,tkinter,wait,tk,Python,Tkinter,Wait,Tk,我正在使用Python3.1和Tk将一些东西组合起来 我想循环使用我在这里定义的“NewDataFrame”对象的不同方法: from tkinter import * from tkinter import ttk import string root = Tk() mainframe = ttk.Frame(root) mainframe.grid(column=0, row=0, sticky=(N, W, E, S)) mainframe.columnconfigure(0, wei

我正在使用Python3.1和Tk将一些东西组合起来

我想循环使用我在这里定义的“NewDataFrame”对象的不同方法:

from tkinter import *
from tkinter import ttk
import string

root = Tk()

mainframe = ttk.Frame(root)
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)

value = StringVar()
dataname = StringVar()

class MenuFrame:
    def __init__(self, parent):
        self.myParent = parent
        self.menuFrame = ttk.Frame(self.myParent)
        self.newButton = ttk.Button(self.myParent, text="new dataset", command=self.newClick)
        self.loadButton = ttk.Button(self.myParent, text="load dataset", command=self.loadClick)
        self.menuFrame.grid(column=0, row=0)
        self.newButton.grid()
        self.loadButton.grid()

    def newClick(self):
        self.instructions = ttk.Label(self.menuFrame, text="enter a name for your new dataset")
        self.instructions.grid()
        self.nameEntry = ttk.Entry(self.menuFrame, textvariable=dataname)
        self.enterName = ttk.Button(self.menuFrame, text="enter", command=self.newData)
        self.nameEntry.grid()
        self.enterName.grid()
类NewDataFrame:

def __init__(self, parent, dataname):
    self.myParent = parent
    self.newDataFrame = ttk.Frame(parent)
    self.dataSet = DataSet(dataname)
    self.instructions = ttk.Label(self.newDataFrame)
    self.instructions.configure(text="enter aspects of %s, separated by commas" % (self.dataSet.getName()))
    self.enterBar = ttk.Entry(self.newDataFrame, textvariable=value)
    self.enterButton = ttk.Button(self.newDataFrame, text="ENTER", command=self.enterClick)
    self.doneButton = ttk.Button(parent, text="DONE", command=self.createAspects)
    self.newDataFrame.grid()
    self.enterBar.grid()
    self.goingOn.grid()
    self.instructions.grid()
    self.enterButton.grid()
    self.doneButton.grid()
我希望doneButton循环使用几个不同的命令,正如您在newDataSet框架的这些方法中看到的:

def createAspects(self):
    for asp in (value.get().split(',')):
        aspect = Aspect(self.dataSet.getName(), asp)
        self.dataSet.addAspect(aspect)
    for a in self.dataSet.getAspects():
        self.createFile(i=a.getName())
        self.instructions.configure(text="enter groups of %s, separated by commas" % (a.getName()))
        self.doneButton.configure(command=self.createGroups(aspect=a))

def createGroups(self, aspect=""):
    for gro in (value.get().split(',')):
        print(gro)
        group = Group(self.dataSet.getName(), aspect.getName(), gro)
        aspect.addGroup(group)
    for group in aspect.getGroups():
        self.createFile(i=aspect.getName(), j=group.getName())
        self.instructions.configure(text="enter members of %s, separated by commas" % (group.getName()))
        self.doneButton.configure(command=self.createMembers(aspect=aspect, group=group))

def createMembers(self, aspect="", group=""):
    for mem in (value.get().split(',')):
        member = Member(self.dataSet.getName(), aspect.getName(), group.getName(), mem)
        group.addMember(member)
    for mem in group.getMembers():
        self.createFile(i=aspect.getName(), j=group.getName(), k=mem.getName())

menuFrame = MenuFrame(mainframe)

root.mainloop()
我是个大傻瓜,但这需要我做很多工作,我真的被困在原地,所以我需要一些创造性的投入。我希望此程序暂停帧,并允许用户在值变量中为以下每种对象类型输入内容:方面,将包含组,将包含成员(按树形图组织)

目前,程序不会在createGroup执行级别等待(我希望它会等待再次单击以继续执行createMember部分),而是要求用户在输入方面后立即输入成员


我希望这不是太抽象,非常感谢所有试图提供帮助的人。

让我们从主要错误开始:

self.doneButton.configure(command=self.createGroups(aspect=a))
当Python到达这一行时,它计算self.createGroups(aspect=a)并将返回值传递给
命令
。 因此,
self.createGroups(aspect=a)
最终被调用。相反,您确实希望将回调函数传递给
命令
,以便稍后调用(当按下next中的
done
按钮时)

试图通过重新配置
done
回调来管理控制流会带来麻烦。我们不仅要创建已经绑定了正确参数(例如,
aspect=a
)的函数,这样我们就有了一个需要零参数的函数,就像done回调所期望的那样,而且(更困难的是)我们还必须识别何时从createMembers到createGroups重置
done
回调,回到CreateSpect。我们将对控制流程进行微观管理

如果我们能让Python来处理这些细节,那不是很好吗

您正在寻找的是一个可以调用、暂停、稍后返回并在先前暂停的位置恢复的函数。 Python正好有这样一种函数——a

比如说,

def gen():
    for i in range(5):
        print(i)
        yield

mygen = gen().next
mygen()
mygen()
屈服

0
1
请注意,每次调用
mygen()
时,执行都会继续,直到Python达到
yield
表达式。因此,第一次调用
mygen()
时,打印
0
,但第二次打印
1
。Python会记住它最后一次屈服的地方,并在那个时候恢复

因此,要将此想法应用到您的情况中,您可以尝试使用以下方法:

class NewDataFrame:
    def __init__(self, parent, dataname):
        ...
        self.on_done = self.cycle_done().next
        self.doneButton = ttk.Button(parent, text="DONE", command=self.on_done)

    def cycle_done(self):
        while True:
            for asp in (value.get().split(',')):
                aspect = Aspect(self.dataSet.getName(), asp)
                self.dataSet.addAspect(aspect)
            for aspect in self.dataSet.getAspects():
                self.createFile(i=aspect.getName())
                self.instructions.configure(
                    text="enter groups of %s, separated by commas" % (aspect.getName()))
                yield
                for gro in (value.get().split(',')):
                    print(gro)
                    group = Group(self.dataSet.getName(), aspect.getName(), gro)
                    aspect.addGroup(group)
                for group in aspect.getGroups():
                    self.createFile(i=aspect.getName(), j=group.getName())
                    self.instructions.configure(
                        text="enter members of %s, separated by commas" % (group.getName()))
                    yield
                    for mem in (value.get().split(',')):
                        member = Member(self.dataSet.getName(), aspect.getName(), group.getName(), mem)
                        group.addMember(member)
                    for mem in group.getMembers():
                        self.createFile(i=aspect.getName(), j=group.getName(), k=mem.getName())
            yield

这将
createAspect
createGroup
createMembers
中的大部分代码组合到一个生成器中。可以重构
循环_done
(到在(较小的)生成器上迭代的生成器中),但这样做会增加解决方案的复杂性。让我们先让这个解决方案起作用,然后(如果您感兴趣的话)我们可以担心重构。

这不是一个太抽象或太不抽象的问题。相反,您必须提供最少的代码来重现您遇到的问题。这样做还可以帮助你发现/理解问题,其他人也可以有效地研究具体问题。非常感谢你为我指明了正确的方向。我将在这方面做一段时间,看看是否能完全理解。