CL. L
CL. L

Reputation: 257

python 3.5 tkinter.listbox change size

Could anyone advise me what's wrong go with the following code? I try to build a tkinker.listbox with dimensions can be changed with .config command, yet failed. Instead, it produce the error of "AttributeError: 'MovListbox' object has no attribute 'tk'" The code is attached below for your reference.

Many thanks.

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()     

Upvotes: 0

Views: 3490

Answers (1)

PM 2Ring
PM 2Ring

Reputation: 55469

I've made a few modifications to your code; it's probably not exactly what you want, but you should find it helpful.

The Listbox width and height options are not pixel measurements; they specify dimensions in terms of characters, so height=12 makes the Listbox 12 text lines high, and width=40 makes the Listbox 40 characters wide.

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()

If you like, you can remove the a.setup_style(12, 40, tk.EXTENDED) call in test() and instead do

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

at the end of the MovListbox.__init__() method.

I've changed your list variable to lst. list is not a good choice for a variable name as that shadows the built-in list type, which can be confusing, and it can also lead to mysterious bugs.


The super built-in function is used to access methods of the parent class. From 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.

Thus

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

says to call the __init__ method of the parent class of the MovListbox class, in other words, the tk.Listbox.__init__ method. We need to do this because MovListbox is derived from tk.Listbox and we need all the usual Listbox stuff to be set up for our MovListbox instance before we start doing extra stuff with it, like inserting the strings from inputlist.

If a derived class doesn't define its own __init__ method then the __init__ method from the parent is called automatically when you create an instance of the derived class. But because we've defined an __init__ method for MovListbox that new __init__ gets called instead. So to get the usual Listbox initialization performed for MovListbox we need to manually call Listbox's __init__, and the customary way to do that gracefully is to use super.

Actually, in Python 3, that super call can be simplified:

super().__init__(master)

The form I used earlier is necessary in Python 2. However, super only works on new-style classes (the only kind of class that Python 3 supports), but unfortunately Python 2 Tkinter uses the ancient old-style classes for its widgets, and calling super on such classes raises a TypeError exception. :( When working with old-style classes we have to do the call by explicitly specifying the parent class, like this:

tk.Listbox.__init__(self, master)

That syntax is also valid in Python 3, but it's generally preferred to use super when it's available.

Upvotes: 2

Related Questions