2016-08-02 10 views
1

私は主にGUI(Tkinterコード)を含むメインファイルを持っています。 LabelTextのユーザーアクションでテキストが更新される領域、およびButtonのウィンドウ。Python:モジュールからクラスの属性にアクセスする方法

# ~/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() 

ユーザーアクションは別のファイルで定義されています。

# ~/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) 


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


def do_stuff(): 
    # do something 
    print 'doing stuff' 

は、以前のコードでは、今、その機能に基づいて、複数のファイルとして作成しようとイム、1つのファイルにありました。基本的には、ユーザーが何か操作をすると、Textエリアにメッセージが表示されます。 Textフィールドはメッセージを表示し、すべてのディスプレイ/アクティビティ/アップデート中にいくつかの共通点を持っているので、メインファイルにtext_infoという関数を作成しました。

Textフィールドに別のメッセージを送信して、別のファイルから更新する場合は、たとえばbuttonevent.pyファイルからどうすれば実現できますか。

私はそれを実行したときに、私は別のPY-ファイルからメインPY-ファイル内の関数を呼び出すことができますどのように

$ 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. としてエラーが発生します。これは、コードに正しい方法ではない場合の最良の方法は何か
  2. が、私はmain.pyファイル
  3. text_infoためclassまたはfunctionの使用をしなければならない、私を修正してください。

    代わりのルートクラスに割り当てる:

    Root.status = Tkinter.StringVar() 
    

    はそれを割り当てる

+0

'textinfo'は、あなたがルートクラスの少なくとも一つのインスタンスを初期化するまで設定されていないクラス属性です..あなたがあなたの前にあなたの元のファイルのルートクラスのインスタンスを作成する必要がありますtext_info関数を使用できます。少なくとも1つのオブジェクトがインスタンス化されない限り、 '__init__'メソッドのコードは実行されません。ああ。問題はあなたが '' __name__ == '__main __': 'を持っているということです。それは、あなたがメインのものをインポートしたときに、それ以降のすべてが実行されないことを意味します... –

答えて

1

あなたの関数へのパラメータとしてルートインスタンスの参照を与えることによって、あなたが望むものを達成することができますルートインスタンス:

self.status = Tkinter.StringVar() 

インスタンスselfではなくルートクラスに割り当てる理由はありません。所有権は、Rootインスタンスの一部でもあります。これは、更新するイベントを発生させるRootインスタンス(Tkinterパーツ)のコンポーネントです。次に、あなたのbuttoneventへのパラメータとしての自己を与えることができる :

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

そして、あなたは、あなたのクラスのtext_info一部にすることができます。

class Root(object): 

    ... 

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

を、これにbuttoneventを変更します。

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

すべて "ルート" 「自己」と変わった。 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() 

buttonevent。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

あなたが変更したものを説明すれば、それ以外の場合は、各行を元のコードと比較しながら、コードを1行ずつ読み込む必要があります。 –

+0

text_info関数は不要です。この関数を削除できます。 – redratear

+0

問題は可変転送です。 buttonevent.pyスクリプトに "curmsg"変数を追加しました。 Rootクラスの "ok"関数で 'buttonevent.curmsg'と呼びます。ルートクラスを初期化する際にクリックイベントを "OK"と定義したので、buttonevent.pyスクリプトのdo_event関数から関数呼び出しを削除してください。ボタン "OK"をクリックすると、buttoneventスクリプトからcurrentmsgが呼び出されます。 – redratear

関連する問題