2015-04-06 3 views
0

Надеюсь, это не дублированный вопрос, так как было предложено решение here, с которым мне трудно работать. (В качестве альтернативы я мог бы отправить это в той же дискуссии)Tkinter parent to child data exchange

Цель:

В главном окне пользователя ввести некоторые данные, если нажата, появится новое окно ребенка с родителем данными, в конечном счете работает на них, затем отправляет результат родительским виджетам.

enter image description here

код используется:

from Tkinter import * 

class trackApp(Frame): 

    def __init__(self, master): 
     Frame.__init__(self, master) 

     self.mainVar1 = IntVar() 
     self.mainVar2 = IntVar() 

     self.mainVar1.set(100) 
     self.mainVar2.set(100) 
     self.master = master 
     self.master.geometry('400x200+100+200') 
     self.master.title('MAIN WINDOW') 

     self.label1=Label(self.master,text='Variable1 : ').grid(row=1,column=1) 
     self.mainEntry1=Entry(self.master,textvariable=self.mainVar1).grid(row=1,column=2) 

     self.label2=Label(self.master,text='Variable2 : ').grid(row=2,column=1) 
     self.mainEntry2=Entry(self.master,textvariable=self.mainVar2).grid(row=2,column=2) 

     self.button1=Button(self.master,text='Child',command=self.dialogWindow).grid(row=7,column=2) 


    def new_data(self, data): 
     self.mainEntry1.delete(0,END) 
     self.mainEntry1.insert(0,self.data['var1']) 
     self.mainEntry2.delete(0,END) 
     self.mainEntry2.insert(0,self.data['var2']) 


    def dialogWindow(self): 
     # Build a list from control variables used in the main window text entry boxes 
     mainList = [self.mainVar1.get(),self.mainVar2.get()] 

     top=Toplevel(self.master) 
     childDialog=childWindow(top,mainList, self.master) 


class childWindow(Frame): 

    # Pass data (list) to the child 
    def __init__(self, master, list, app): 

     self.list = list 

     self.app = app 
     self.master = master 
     self.master.geometry('300x100+150+250') 
     self.master.title('CHILD WINDOW') 

     # Define control variabels to be used with child window text entry widgets 
     self.childvar1 = IntVar() 
     self.childvar2 = IntVar() 

     # Fill child window text entry widgets with inf. from parent window 
     self.childvar1.set(list[0]) 
     self.childvar2.set(list[1]) 

     # Text entry widgets 
     self.label1=Label(self.master,text='Enter New value 1').grid(row=0,column=1) 
     self.childEntry1=Entry(self.master,textvariable=self.childvar1).grid(row=0,column=2) 

     self.label2=Label(self.master,text='Enter New value 2').grid(row=1,column=1) 
     self.childEntry2=Entry(self.master,textvariable=self.childvar2).grid(row=1,column=2) 

     self.button1=Button(self.master,text='OK',command=self.childDestroy).grid(row=3,column=1) 


    def childDestroy(self): 

     self.data = {} 
     self.data['var1'] = self.childvar1.get() 
     self.data['var2'] = self.childvar2.get() 

     trackApp.app.new_data(self, self.data) # <<<<<<<<< How to call the parent new_data method 

     self.master.destroy() 


def main(): 
    root = Tk() 
    app = trackApp(root) 
    root.mainloop() 

if __name__ == "__main__": 
    main() 

Вопрос:

Как обратиться к родительскому методу (new_data) от ребенка?

Ошибка:

/usr/bin/python2.7 /<path>/child-dialog.py 
Exception in Tkinter callback 
Traceback (most recent call last): 
    File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1489, in __call__ 
    return self.func(*args) 
    File "/<path>/child-dialog.py", line 77, in childDestroy 
    trackApp.app.new_data(self, self.data) # <<<<<<<<< How to call the parent new_data method 
AttributeError: class trackApp has no attribute 'app' 

ответ

1

Сообщение об ошибке говорит вам именно то, что проблема: он говорит, что trackApp не имеет атрибута 'app', и, глядя на определение этого класса я не вижу никакого атрибута 'app'.

Для вашего дочернего окна, чтобы узнать его родителя, вам необходимо дать ему ссылку на родителя. Таким образом, при создании окна вы передаете ссылку, а внутри дочернего окна вы используете ссылку.

Похоже, вы пытаетесь это сделать, но вы передаете неправильное значение, а затем вы не используете значение. Вам необходимо изменить код, чтобы он выглядел так:

class trackApp(Frame): 
    ... 
def dialogWindow(self): 
    ... 
    childDialog=childWindow(top,mainList, self) 

class childWindow(Frame): 
    def childDestroy(self): 
     ... 
     self.app.new_data(self, self.data) 
     ... 
-1

Спасибо Брайан за ответ. Вот изменения, которые я сделал, соответственно:

Передайте родителю (Self) в дочернем окне

def dialogWindow(self): 
    childDialog=childWindow(top,mainList, self) 

вызова родительский метод с использованием родительского экземпляра (само)

def childDestroy(self)  
    self.app.new_data(self.data) 

и следующее для обновления виджетов главного окна:

def new_data(self, data): 
    self.mainVar1.set(data['var1']) 
    self.mainVar2.set(data['var2']) 

Цените свою помощь.