2016-08-02 9 views
1

auf das Attribut einer Klasse zugreift Ich habe eine Hauptdatei, die hauptsächlich die GUI (Tkinter-Code) enthält. Ein Fenster mit Label, einem Text Bereich, in dem der Text aktualisiert wird, und einer Button.Python: Wie man von einem Modul

# ~/main.py 
import Tkinter 
import buttonevent 
from itertools import cycle 

msglist = ['main_msg1\n', 'main_msg2\n', 'main_msg3\n', 'main_msg4\n'] 


class Root(object): 

    def __init__(self, master): 
     self.msglist = cycle(msglist) 
     self.master = master 
     self.frame1 = Tkinter.Frame(master) 
     self.frame1.pack() 
     Root.status = Tkinter.StringVar() 
     self.status_info = Tkinter.Label(self.frame1, textvariable=Root.status) 
     self.status_info.pack() 
     Root.status.set("Set by constructor") 

     self.frame2 = Tkinter.Frame(master) 
     self.frame2.pack() 
     Root.textinfo = Tkinter.Text(self.frame2, width=20, height=10) 
     Root.textinfo.insert(Tkinter.END, 'message 1') 
     Root.textinfo.config(font='Arial') 
     Root.textinfo.pack() 
     Root.textinfo.config(bg=master.cget('bg'), relief=Tkinter.SUNKEN) 
     Root.textinfo.configure(state='disabled') 

     self.frame3 = Tkinter.Frame(master) 
     self.frame3.pack() 
     self.button = Tkinter.Button(self.frame3, text='Ok', command=self.ok) 
     self.button.pack() 

    def ok(self): 
     text_info(self.msglist.next()) 
     buttonevent.do_event() 
     buttonevent.do_stuff() 


def text_info(msg): 
    Root.textinfo.configure(state='normal') 
    Root.textinfo.insert(Tkinter.END, msg) 
    Root.textinfo.see(Tkinter.END) 
    Root.textinfo.configure(state='disabled') 


if __name__ == '__main__': 
    root = Tkinter.Tk() 
    main_window = Root(root) 
    root.mainloop() 

Die Benutzeraktionen sind in einer anderen Datei definiert.

Zuvor war der Code in einer einzigen Datei, jetzt versuche ich, es als eine multiple Datei basierend auf seiner Funktionalität zu schreiben. Wenn der Benutzer etwas tut, wird eine Nachricht im Bereich Text angezeigt. Da das Feld Text Nachricht anzeigt und einige Gemeinsamkeiten während jeder Anzeige/Aktivität/Aktualisierung aufweist, habe ich eine Funktion dafür in der Hauptdatei als text_info erstellt.

Sagen Sie, wenn ich eine andere Nachricht auf dem Text Feld senden möchte, um von einer anderen Datei zu aktualisieren, .. zum Beispiel von der Datei buttonevent.py, wie kann ich es erreichen.

, wenn ich es laufen bekomme ich Fehler als

$ python main.py 
do_msg1 

Exception in Tkinter callback 
Traceback (most recent call last): 
    File "/home/miniconda2/lib/python2.7/lib-tk/Tkinter.py", line 1537, in __call__ 
    return self.func(*args) 
    File "main.py", line 38, in ok 
    buttonevent.do_event() 
    File "/home/buttonevent.py", line 14, in do_event 
    main.text_info(xx) 
    File "/home/main.py", line 51, in text_info 
    Root.textinfo.configure(state='normal') 
AttributeError: type object 'Root' has no attribute 'textinfo' 
  1. Wie kann ich eine Funktion in der Haupt-py-Datei aus einer anderen py-Datei aufrufen.
  2. was der beste Weg ist, würde ich die Verwendung eines class oder function für die text_info in der main.py Datei
  3. machen Wenn dies Code nicht der richtige Weg ist, bitte korrigieren Sie mich.
+0

'textinfo' ist ein Klasse-Attribut, das nicht eingestellt ist, bis Sie mindestens eine Instanz der Root-Klasse initialisiert haben .. Sie müssen eine Instanz der Root-Klasse in Ihrer ursprünglichen Datei, bevor Sie erstellen kann die Funktion text_info verwenden. Der Code in der Methode "__init__" wird niemals ausgeführt, wenn nicht mindestens ein Objekt instanziiert wird. Aha. Das Problem ist, dass Sie haben 'if __name__ == '__main __':' was bedeutet, dass alles danach nicht ausgeführt wird, wenn Sie Main importieren ... –

Antwort

1

können Sie erreichen, was Sie wollen, indem Sie einen Verweis von der Root-Instanz als Parameter für Ihre Funktionen geben:

Statt auf die Root-Klasse zuzuweisen:

Root.status = Tkinter.StringVar() 

es die Weisen Root-Instanz:

Es gibt keinen Grund für die Zuordnung zu Root-Klasse anstelle der Instanz selbst, weil seine Ownership ist ebenfalls Teil der Root-Instanz: Es sind die Komponenten der Root-Instanz (die Tkinter-Teile), die das zu aktualisierende Ereignis auslösen. Sie könnten dann selbst als Parameter für Ihre Button geben:

def ok(self): 
    text_info(self.msglist.next()) 
    buttonevent.do_event(self) 
    buttonevent.do_stuff(self) 

Und Sie können dann text_info Teil Ihrer Klasse machen:

class Root(object): 

    ... 

    def text_info(self, msg): 
     self.textinfo.configure(state='normal') 
     self.textinfo.insert(Tkinter.END, msg) 
     self.textinfo.see(Tkinter.END) 

Und die Button Um dies zu ändern:

def do_event(root_instance): 
    # do something 
    root_instance.text_info(msg.next()) 
1

Alle "Root". geändert als "Selbst" main.py

# ~/main.py 
import Tkinter 
import buttonevent 
from itertools import cycle 
curwin=None 
msglist = ['main_msg1\n', 'main_msg2\n', 'main_msg3\n', 'main_msg4\n'] 
class Root(object): 

    def __init__(self, master): 
     self.msglist = cycle(msglist) 
     self.master = master 
     self.frame1 = Tkinter.Frame(master) 
     self.frame1.pack() 
     self.status = Tkinter.StringVar() 
     self.status_info = Tkinter.Label(self.frame1, textvariable=self.status) 
     self.status_info.pack() 
     self.status.set("Set by constructor") 
     self.curmsg='message 1\n' 
     self.frame2 = Tkinter.Frame(master) 
     self.frame2.pack() 
     self.textinfo = Tkinter.Text(self.frame2, width=20, height=10) 
     self.textinfo.insert(Tkinter.END, 'message 1\n') 
     self.textinfo.config(font='Arial') 
     self.textinfo.pack() 
     self.textinfo.config(bg=master.cget('bg'), relief=Tkinter.SUNKEN) 
     self.textinfo.configure(state='disabled') 

     self.frame3 = Tkinter.Frame(master) 
     self.frame3.pack() 
     self.button = Tkinter.Button(self.frame3, text='Ok', command=self.ok) # "Ok" function defined for click event 
     self.button.pack() 

    def ok(self): 
     #self.text_info(buttonevent.curmsg) 
     self.textinfo.configure(state='normal') 
     self.textinfo.insert(Tkinter.END, buttonevent.curmsg) # get message from buttonevent.py and set for window. Fisrst clicking will get initalized curmsg value. if you want get value after click write buttonevent.do_event() above this codes. 
     self.textinfo.see(Tkinter.END) 
     self.textinfo.configure(state='disabled') 
     buttonevent.do_event() # calling buttonevent's do_event function so it means global message will be changed. next click you will see new value for message. 
     buttonevent.do_stuff() 

if __name__ == '__main__': 
    root = Tkinter.Tk() 
    curwin=Root(root) 
    root.mainloop() 

Button.py

# ~/buttonevent.py 

from itertools import cycle 
import main 

do_msg = ['do_msg1\n', 'do_msg2\n', 'do_msg3\n', 'do_msg4\n'] 
msg = cycle(do_msg) 
curmsg=msg.next() # Add this variable to call main.py to first click event 

def do_event(): 
    # do something 
    global curmsg #to edit variable value you must call it as global 
    curmsg=msg.next() #Changing variable value for each click 
    #Removed text_info function from main.py it is not necessary. 
def do_stuff(): 
    # do something 
    print 'doing stuff' 
+0

Ihre Antwort wäre viel, viel besser, wenn Sie erläutert, was Sie geändert haben. Andernfalls müssen wir Ihren Code zeilenweise lesen und jede Zeile mit dem Original vergleichen. –

+0

text_info Funktion ist nicht notwendig Sie können diese Funktion löschen. – redratear

+0

Ihr Problem ist die variable Übertragung. Ich habe die Variable "curmsg" im Skript buttonevent.py hinzugefügt. und nennen Sie es in der "ok" -Funktion der Root-Klasse als "buttonevent.curmsg". und entfernen Sie jeden Funktionsaufruf von der Funktion do_event im Skript buttonevent.py, nachdem Sie das Ereignis click als "Ok" beim Initialisieren der Root-Klasse definiert haben. Wenn Sie also auf die Schaltfläche "ok" klicken, wird die Funktion currentmsg von buttonevent script aufgerufen. – redratear

Verwandte Themen