2017-12-29 22 views
0

私のプログラムスニペットでは、2つのフィールドと3つのボタンを持つpythonウィンドウを作成します。左の2つのボタンがいくつかのアクションを実行する必要がありますが、代わりにエラーがスローされます。python AttributeError:NoneTypeには属性がありません

Exception in Tkinter callback 
Traceback (most recent call last): 
    File "/usr/lib64/python3.4/tkinter/__init__.py", line 1538, in __call__ 
    return self.func(*args) 
    File ".../GuiFile.py", line 11, in <lambda> 
    self.F[2] = ButtonClass().make_button(stacked="left",buttontext= "Action button", buttoncommand = lambda: cf.mainButtons.doButtonAction1(self)) 
    File ".../ClassFile.py", line 11, in doButtonAction1 
    print(gf.StartGui.F[0].textField.get("1.0","end-1c")) 
AttributeError: 'NoneType' object has no attribute 'textField' 

なぜdictの項目F [0](GuiFile.pyの9行目で作成された)テキストとして認識されていない()クラスは、属性でありますtextField(GuiFile.pyの43行目で定義されています)?

MainProgramFile.py

#!/usr/bin/env python3 

import sys 
import ClassFile 
import GuiFile as gf 

if __name__== '__main__': 
    gf.StartGui().mainloop() 

GuiFile.py

import sys 
from tkinter import * 
import ClassFile as cf 

class StartGui(Frame): 
    F = {} 
    def __init__(self,parent=None): 
     Frame.__init__(self, parent) 
     self.F[0] = FieldTextClass().make_field(labeltext="Label of field 1", fieldtext="veld 1", fieldheight=90) 
     self.F[1] = FieldTextClass().make_field(labeltext="Label of field 2", fieldtext="veld 2") 
     self.F[2] = ButtonClass().make_button(stacked="left",buttontext= "Action button", buttoncommand = lambda: cf.mainButtons.doButtonAction1(self)) 
     self.F[3] = ButtonClass().make_button(stacked="left", buttontext= "Exchange button", buttoncommand = lambda: cf.mainButtons.doButtonSwitchValues(self)) 
     self.F[4] = ButtonClass().make_button(stacked="right",buttontext= "Quit button",buttoncommand = lambda: cf.mainButtons.doButtonQuit(self)) 
     self.pack(expand=True, fill=BOTH, anchor="nw", side=LEFT) 
     #for i in range(self.F.__len__()): print(self.F[i].__class__,self.F[i].objectType) 


class ButtonClass (Frame, Button): 
    objectType = "button" 

    def make_button(self, parent=None, stacked="horizontal", buttontext="Button", buttonwidth=120, buttonheight=32, buttoncommand=""): 
     self.buttonwidth=buttonwidth 
     self.buttonheight=buttonheight 
     self.buttontext=buttontext 
     self.buttoncommand=buttoncommand 

     if stacked=="vertical": 
      BUTTONSTACK = TOP 
     elif stacked=="right": 
      BUTTONSTACK = RIGHT 
     elif stacked=="horizontal" or stacked=="left": 
      BUTTONSTACK = LEFT 
     else: 
      BUTTONSTACK = LEFT 

     self.top = Frame(parent, height=self.buttonheight, width=self.buttonwidth) 
     self.top.pack_propagate(False) 
     self.top.pack(side=BUTTONSTACK)  
     button = Button(self.top, text=self.buttontext, command=self.buttoncommand,height=self.buttonheight, width=self.buttonwidth) 
     button.pack(fill=BOTH) 

class FieldTextClass(Frame,Text,Label): 
    textField = None 
    objectType = "inputField" 

    def make_field(self, parent=None, labeltext="Empty", fieldtext="Empty", fieldwidth=600, fieldheight=20, labelwidth=120, labelheight=20): 
     self.fieldheight=fieldheight 
     self.fieldwidth=fieldwidth 
     self.fieldtext=fieldtext 
     self.labeltext=labeltext 
     self.labelheight=labelheight 
     self.labelwidth=labelwidth 
     self.top = Frame(parent) 

     #create the label, whith the text shifted left/top in a separate Frame 
     labelFrame = Frame(self.top, height = self.labelheight,width=self.labelwidth) 
     label = Label(labelFrame, text=self.labeltext, fg="black", anchor="nw") 
     label.pack(expand=True, fill=BOTH, anchor="nw", side=LEFT) 
     labelFrame.pack_propagate(False) 
     labelFrame.pack(side=LEFT, anchor="nw") 

     #create the text field, packed in a separate Frame 
     fieldFrame = Frame(self.top, height = self.fieldheight,width=self.fieldwidth) 
     self.textField = Text(fieldFrame, fg="black",bg="white") 
     self.textField.insert(INSERT,self.fieldtext) 
     self.textField.pack(expand=True, fill=BOTH, side=LEFT) 
     fieldFrame.pack_propagate(False) 
     fieldFrame.pack(side=LEFT) 

     self.top.pack(side=TOP) 

ClassFile.py

import sys 
from tkinter import * 
import GuiFile as gf 

class mainButtons(): 
    def doButtonQuit(self): 
     print("Quitting test via ClassFile") 
     self.quit() 

    def doButtonAction1(self): 
     print(gf.StartGui.F[0].textField.get("1.0","end-1c")) 
     print(gf.StartGui.F[1].textField.get("1.0","end-1c")) 
     gf.StartGui.F[0].textField.delete("1.0","end") 
     gf.StartGui.F[0].textField.insert(INSERT, "New text") 

    def doButtonSwitchValues(self): 
     tmp0=gf.StartGui.F[0].textField.get("1.0","end-1c") 
     tmp1=gf.StartGui.F[1].textField.get("1.0","end-1c") 
     gf.StartGui.F[0].textField.delete("1.0","end") 
     gf.StartGui.F[0].textField.insert(INSERT, tmp1) 
     gf.StartGui.F[1].textField.delete("1.0","end") 
     gf.StartGui.F[1].textField.insert(INSERT, tmp0) 
+1

ここにはたくさんの問題があります。クラスとインスタンスの違い、クラス属性とインスタンス属性の違いを理解する必要があります。 –

答えて

1

あなたがButtonClass().make_button()(またはFieldTextClass.make_field())を行うと、Pythonはの値を返します。関数、はありません the instanクラスのce。この関数はNoneを返します。したがって、辞書の要素はNoneです。

カスタムクラスを使用する方法は非常に奇妙です。特殊な関数を作成する代わりに、そのコードを__init__に置き、他のクラスと同じようにクラスを使用します。例えば

class ButtonClass (Frame): 
    def __init__(self, parent=None, stacked="horizontal", 
       buttontext="Button", buttonwidth=120, buttonheight=32, 
       buttoncommand=""): 
     Frame.__init__(self, parent) 
     self.buttonwidth=buttonwidth 
     ... 

... 
self.F[2] = ButtonClass(stacked="left",buttontext= "Action button", buttoncommand = lambda: cf.mainButtons.doButtonAction1(self)) 

注:このようにそれをやったとき、あなたは__init__内の別のフレームを作成する必要はありません(例:self.top)、selfはすでにフレーム自体であるため、 。

+0

OK、それは明らかです。できます。ただし、Frame .__ init __(親)を使用すると、この行にエラーがスローされます。AttributeError: 'NoneType'オブジェクトに 'widgetName'属性がありません。私は何が欠けていますか? – Mike

+0

@Mike:申し訳ありませんが、私は 'Frame .__ init__'にパラメータを残しました。私は答えを更新しました。 –

+0

Thx Bryan、これは今は正常です! – Mike

関連する問題