2017-02-13 70 views
0

我的代碼:入門嘗試一個AttributeError時IntVar()分配給一個變量

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
""" 
Created on Sun Jan 22 14:47:36 2017 

@author: Jose Chong 
""" 
import json 
try: 
    import tkinter as tk 
except ImportError: 
    import Tkinter as tk 

import os 
import pymsgbox 

filepath = os.path.expanduser(r'~\Documents\joseDzirehChongToDoList\toDoListSaveFile.json') 

checkboxList = [] 

def checkSaveFile(): 

    def checkExistenceOfSaveFile(): 
     if not os.path.isdir(os.path.expanduser(r'~\Documents\joseDzirehChongToDoList')): 
      os.makedirs(os.path.expanduser(r'~\Documents\joseDzirehChongToDoList'), 777) 

     if not os.path.isfile(filepath): 
      open(filepath, 'w') 
      open(filepath).close() 

    def checkIfSaveFileIsEmpty(): 
     global checkboxList 
     if os.path.getsize(filepath) == 0: 
      with open (filepath, 'w') as outfile: 
        json.dump(checkboxList, outfile) 


     with open(filepath) as infile:  
      checkboxList = json.load(infile) 
    checkExistenceOfSaveFile() 
    checkIfSaveFileIsEmpty() 
    try: 
     open(filepath, 'w') 
     open(filepath).close() 
    except (IOError, ValueError): 

     pymsgbox.alert("""You're not supposed to see this message ever. If you do, that means your save file is either missing or corrupted, and my methods of stopping that have failed. Please email me at '[email protected]' with a copy of your save file so I can tell what went wrong. 

Click the button below to exit, the red button in the corner doesn't work.""", 'Broken Save File') 

checkSaveFile() 

var = tk.IntVar() 

def loadToJSON(): 
    with open(filepath, 'w') as outfile: 
     json.dump(checkboxList, outfile) 

class CheckboxRow(tk.Frame): 
    def __init__(self, master, text): 
     self.text = text 
     tk.Frame.__init__(self, master) 
     checkbox = tk.Checkbutton(self, text=text, variable=var) 
     checkbox.pack(side=tk.LEFT) 

     deleteItem = tk.Button(self, text="x", bg="red", fg="white", 
           activebackground="white", activeforeground="red", 
           command=self.destroyCheckbox) 
     deleteItem.pack(side=tk.RIGHT) 
     newItem = [self.text, var.get()] 
     self.master.master.checkboxList.append(newItem) 
     loadToJSON() 

    def destroyCheckbox(self, text): 
     self.text = text 
     newItem = [self.text, var.get()] 
     self.master.master.checkboxList.remove(newItem) 
     self.destroy() 
     loadToJSON() 


class CheckboxArea(tk.Frame): 
    def add(self, name): 
     row = CheckboxRow(self, name) 
     row.pack(fill=tk.X) 

class InputStuff(tk.Frame): 
    def __init__(self, master=None, **kwargs): 
     tk.Frame.__init__(self, master, **kwargs) 

     prompt = tk.Label(self, text="What do you want your checkbox to be for?") 
     prompt.pack() 

     bottomInput = tk.Frame(self) 
     self.entry = tk.Entry(bottomInput, bd=3) 
     self.entry.pack(side=tk.LEFT) 
     buttonConfirm = tk.Button(bottomInput, text="Confirm", command=self.drawCheckbox) 
     buttonConfirm.pack(side=tk.LEFT) 
     bottomInput.pack() 

     buttonDone = tk.Button(self, text = "Close Input", command=master.hideInputStuff) 
     buttonDone.pack() 

    def drawCheckbox(self, event=None): 
     self.master.add(self.entry.get()) 
     self.entry.delete(0, tk.END) 

class MainWindow(tk.Frame): 
    def __init__(self, master=None, **kwargs): 
     tk.Frame.__init__(self, master, **kwargs) 

     self.checkboxList = [] 

     self.checkboxArea = CheckboxArea(self) 
     self.checkboxArea.pack(fill=tk.X) 

     self.inputStuff = InputStuff(self) 
     self.addButton = tk.Button(self, text="Add Item", command=self.showInputStuff) 

     self.hideInputStuff() # start with "add" button active 

     self.load() 

    def load(self): 
     for savedCheckbox in checkboxList: 
      checkboxRow = tk.Frame(checkboxArea) 
      checkboxRow.pack(fill=tk.X) 
      checkbox1 = tk.Checkbutton(checkboxRow, text=savedCheckbox[0], variable=var) 
      checkbox1.pack(side=tk.LEFT) 
      deleteItem = tk.Button(checkboxRow, text="x", bg="red", fg="white", 
           activebackground="white", activeforeground="red", 
           command=lambda c=savedCheckbox, r=checkboxRow: destroyCheckbox(c, r)) 
      deleteItem.pack(side=tk.RIGHT) 

      loadToJSON() 

    def add(self, name): 
     self.checkbox_area.add(name) 
     self.checkboxList.append(name) 

    def showInputStuff(self): 
     self.addButton.pack_forget() 
     self.input_stuff.pack() 
     self.input_stuff.entry.focus() 
     self.master.bind('<Return>', self.input_stuff.drawCheckbox) 

    def hideInputStuff(self): 
     self.inputStuff.pack_forget() 
     self.addButton.pack() 
     self.master.unbind('<Return>') 

def main(): 
    master = tk.Tk() 
    master.title("To-Do List (with saving!)") 
    master.geometry("300x300") 
    win = MainWindow(master) 
    win.pack(fill=tk.X) 
    master.mainloop() 

if __name__ == "__main__": 
    main() 

它的可怕壞了,我知道了。我不想幫助其他任何東西,只是AttributeError。

完整的錯誤:

runfile('C:/Users/Josalina/Desktop/Coding/Language - Python/to-do-list-to-compile/toDoListToCompile.py', wdir='C:/Users/Josalina/Desktop/Coding/Language - Python/to-do-list-to-compile') 
Traceback (most recent call last): 

    File "<ipython-input-78-a1f8f63a42cc>", line 1, in <module> 
    runfile('C:/Users/Josalina/Desktop/Coding/Language - Python/to-do-list-to-compile/toDoListToCompile.py', wdir='C:/Users/Josalina/Desktop/Coding/Language - Python/to-do-list-to-compile') 

    File "C:\Users\Josalina\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 866, in runfile 
    execfile(filename, namespace) 

    File "C:\Users\Josalina\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile 
    exec(compile(f.read(), filename, 'exec'), namespace) 

    File "C:/Users/Josalina/Desktop/Coding/Language - Python/to-do-list-to-compile/toDoListToCompile.py", line 51, in <module> 
    var = tk.IntVar() 

    File "C:\Users\Josalina\Anaconda3\lib\tkinter\__init__.py", line 351, in __init__ 
    Variable.__init__(self, master, value, name) 

    File "C:\Users\Josalina\Anaconda3\lib\tkinter\__init__.py", line 233, in __init__ 
    self._root = master._root() 

AttributeError: 'NoneType' object has no attribute '_root' 

我不知道這意味着什麼。 IntVar()不是Tkinter的標準部分嗎?爲什麼會引發錯誤?我如何解決它?另外,修復這個錯誤可能不會讓程序運行,它只會讓我轉向下一個錯誤。提前致謝!

回答

0

在Tkinter程序中,您需要通過創建一個根窗口來初始化Tkinter,然後再執行其他操作。但是,在創建根窗口之前,您的代碼嘗試創建該StringVar。

FWIW,我們可以重現幾行的錯誤:

import tkinter as tk 
var = tk.IntVar() 

導致

Traceback (most recent call last): 
    File "./qtest.py", line 4, in <module> 
    var = tk.IntVar() 
    File "/opt/python3.6/lib/python3.6/tkinter/__init__.py", line 499, in __init__ 
    Variable.__init__(self, master, value, name) 
    File "/opt/python3.6/lib/python3.6/tkinter/__init__.py", line 314, in __init__ 
    self._root = master._root() 
AttributeError: 'NoneType' object has no attribute '_root' 

所以,你需要的是執行master = tk.Tk()調用後定義var。它仍然可以是一個全局變量,但是您應該儘量避免這種情況,尤其是因爲您已經在使用類來構造數據。

相關問題