2016-08-22 373 views
0

任何人都可以告诉我什么是错误的去下面的代码?我尝试构建一个tkinker.listbox,可以使用.config命令更改维度,但失败。相反,它会产生“AttributeError:'MovListbox'对象没有属性'tk'”的错误。下面附上代码供您参考。python 3.5 tkinter.listbox更改大小

非常感谢。

import tkinter 

def test(): 
    root = tkinter.Tk() 

    list = [' 1','2',' 3','4','5',' 6','7','8',' 9','10'] 
    a = MovListbox(root, list) 
    a._setup_style(200, 200, EXTENDED) 

class MovListbox(tkinter.Listbox):  

    def __init__(self, master=None, inputlist=None): 
#  super(MovListbox, self).__init__() 

     global NewsClassify_catList 
     NewsClassify_catList = tkinter.Listbox(master) 
     NewsClassify_catList.grid(row = 0 , column = 0, columnspan=2, sticky=N)  

     '''populate the news category onto the listbox''' 
     for i in range (0, inputlist.__len__()): 
      NewsClassify_catList.insert(END, inputlist[i]) 

     master.mainloop() 

    def _setup_style(self, height=100, width=100, mode=EXTENDED): 
     self.config(height=height, width=width, selectmode=mode) 

if __name__ == '__main__': 
    test()  
+0

我对Tkinter并不十分熟悉,但我不认为你应该使用'_setup_style'方法。以下划线开头的属性通常不被视为public api的一部分,你知道'a._setup_style'在窗口关闭之前没有达到,因为你正在'MovListBox'构造函数中执行'master.mainloop()'? –

+0

谢谢Raw的评论。很好的提醒你把主循环侧。我已经完成了这一工作,并在_setup_style(即setup_style)之前删除了下划线。但属性错误信息仍然显示。我想知道如果问题是关于如何告诉计算机找到配置的列表框,即self.config(height = height,width = width,selectmode = mode))任何人有想法吗? –

+0

糟糕,我只是意识到'_setup_style'是你自己的功能,而不是Tkinter的功能。 –

回答

1

我对代码做了一些修改;这可能不是你想要的,但你应该觉得它有帮助。

列表框宽度和高度选项不是像素测量;它们用字符指定尺寸,所以height=12使得列表框12的文本行高,并且width=40使得列表框40个字符宽。

import tkinter as tk 

def test(): 
    root = tk.Tk() 
    lst = [' 1', '2', ' 3', '4', '5', ' 6', '7', '8', ' 9', '10'] 
    a = MovListbox(root, lst) 
    a.grid(row=0, column=0, columnspan=2, sticky=tk.N) 
    a.setup_style(12, 40, tk.EXTENDED) 
    root.mainloop() 

class MovListbox(tk.Listbox): 
    def __init__(self, master=None, inputlist=None): 
     super(MovListbox, self).__init__(master=master) 

     # Populate the news category onto the listbox 
     for item in inputlist: 
      self.insert(tk.END, item) 

    def setup_style(self, height=10, width=20, mode=tk.EXTENDED): 
     self.config(height=height, width=width, selectmode=mode) 

if __name__ == '__main__': 
    test() 

如果你愿意,你可以删除a.setup_style(12, 40, tk.EXTENDED)呼叫test(),而是做

self.setup_style(12, 40, tk.EXTENDED) 

MovListbox.__init__()方法结束。

我已将您的list变量更改为lstlist对于变量名不是一个好的选择,因为它会掩盖内置的list类型,这可能会造成混淆,并且还会导致不可思议的错误。


super内置函数用于访问父类的方法。从the docs

super([type[, object-or-type]])

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. The search order is the same as that used by getattr() except that the type itself is skipped.

因此

super(MovListbox, self).__init__(master=master) 

说调用父类的MovListbox类的__init__方法,换句话说,tk.Listbox.__init__方法。我们需要这样做,因为MovListbox是从tk.Listbox派生的,我们需要为我们的MovListbox实例设置所有常用的Listbox内容,然后才能开始使用它,例如从inputlist插入字符串。

如果派生类没有定义自己的__init__方法,则在创建派生类的实例时,会自动调用父项的__init__方法。但是因为我们已经为MovListbox定义了一个__init__方法,所以新的__init__被调用。因此,为了使MovListbox能够正常执行Listbox初始化,我们需要手动调用Listbox的__init__,而惯用的方法是使用super

实际上,在Python 3,那super调用可以简化为:

super().__init__(master) 

我以前使用的形式是在Python 2。但是必要的,super仅适用于新的样式类(唯一的那种Python 3支持的类),但不幸的是,Python 2 Tkinter使用古老的旧式类作为它的小部件,并且在这样的类上调用super会产生TypeError异常。:(当与老式类的工作,我们必须明确指定的父类,这样做呼叫:

tk.Listbox.__init__(self, master) 

这句法也是在Python 3有效的,但它通常最好使用super时,它的可用

+0

非常感谢。这正是我正在寻找的。好像你通过添加“super(MovListbox,self).__ init __(master = master)”来解决问题,我不知道它是什么。你能详细解释一下吗? –

+0

@ CL.L:我添加了一些关于'super'的更多细节。如果我的回答对你有帮助,请考虑[接受](http://meta.stackexchange.com/a/5235)。 –

+0

很酷,很详细的解释。我现在明白了,非常感谢你! –