简体   繁体   English

用作类对象时的 tkinter 列表框错误

[英]tkinter Listbox error when used as class object

I want to create a class of Listbox object so that it can be used anywhere it is needed but it throws TypeError error, here is my code:我想创建一个Listbox对象类,以便它可以在任何需要的地方使用,但会引发TypeError错误,这是我的代码:

import tkinter as tk

class cls_list(tk.Listbox):
    def __init__(self, master, callfrom):
        tk.Listbox.__init__(self, master, callfrom)

        callfrom.bind("<KeyRelease>", self.show_list)

    def show_list(self, event):
        x = callfrom.winfo_x()
        y = callfrom.winfo_y()
        h = callfrom.winfo_height()
        self.place(x = x, y = y+h)
        self.insert('end',*('Banana','Orange','Apple','Mango'))

if __name__ == '__main__':
    root = tk.Tk()
    ent = tk.Entry(root, font = (None, 20))
    lst = cls_list(root, ent)
    ent.pack()
    root.mainloop()

Can someone correct me what I am doing wrong?有人可以纠正我我做错了什么吗? Here is complete Exception occurred:这是完整的异常发生:

  File "/home/waheed/env_pinpoint/lib/python3.9/site-packages/test_listbox.py", line 5, in __init__
    tk.Listbox.__init__(self, master, callfrom)
  File "/usr/lib/python3.9/tkinter/__init__.py", line 3162, in __init__
    Widget.__init__(self, master, 'listbox', cnf, kw)
  File "/usr/lib/python3.9/tkinter/__init__.py", line 2566, in __init__
    BaseWidget._setup(self, master, cnf)
  File "/usr/lib/python3.9/tkinter/__init__.py", line 2537, in _setup
    if 'name' in cnf:
  File "/usr/lib/python3.9/tkinter/__init__.py", line 1652, in cget
    return self.tk.call(self._w, 'cget', '-' + key)
TypeError: can only concatenate str (not "int") to str

This is what I have achieved so far.这是我迄今为止所取得的成就。

import tkinter as tk

if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('400x400')
    ent = tk.Entry(root, font = (None, 20))
    lst = tk.Listbox(root, font = (None, 20))
    ent.pack()
    ent.focus_set()

    def hide_list(event):
        index = int(lst.curselection()[0])
        val = lst.get(index)
        ent.delete(0,'end')
        ent.insert(0,val)
        lst.place_forget()

    def show_list(event):
        ent.update_idletasks()
        x = ent.winfo_x()
        y = ent.winfo_y()
        h = ent.winfo_height()
        lst.place(x = x, y = y+h)
        items = ['Banana','Orange','Apple','Mango']
        searchkey = ent.get()
        lst.delete(0, "end")
        for item in items:
            if searchkey.lower() in item.lower():
                lst.insert("end", item)
        n = lst.size()
        if n < 15:
            lst.config(height = 0)
        else:
            lst.config(height = 15)

    ent.bind("<KeyRelease>", show_list)
    lst.bind("<<ListboxSelect>>", hide_list)
    root.mainloop()

And now I want to make it an object (separate class) for using in multiple scripts.现在我想让它成为一个对象(单独的类)以在多个脚本中使用。

I hope now I have explained my question properly.我希望现在我已经正确解释了我的问题。

I'm not sure exactly what you're trying to do, so the following probably doesn't "work", but the changes shown will get rid of the TypeError which was because of passing the wrong number of arguments to the base class __init__() method.我不确定您到底要做什么,因此以下内容可能“不起作用”,但显示的更改将消除TypeError ,这是因为将错误数量的参数传递给基类__init__()方法。

import tkinter as tk


class ClsList(tk.Listbox):
    def __init__(self, master, callfrom):
        tk.Listbox.__init__(self, master)  # Initialize base class.
        self.callfrom = callfrom  # Save for use in other methods.
        self.callfrom.bind("<KeyRelease>", self.show_list)

    def show_list(self, event):
        x = self.callfrom.winfo_x()       # Refer to attribute self.callfrom.
        y = self.callfrom.winfo_y()       # Refer to attribute self.callfrom.
        h = self.callfrom.winfo_height()  # Refer to attribute self.callfrom.
        self.place(x=x, y=y+h)
        self.insert('end', *('Banana','Orange','Apple','Mango'))


if __name__ == '__main__':
    root = tk.Tk()
    ent = tk.Entry(root, font=(None, 20))
    lst = ClsList(root, ent)
    ent.pack()
    lst.pack()  # Added.
    root.mainloop()

I also made a few other cosmetic changes to make the code conform more the the PEP 8 - Style Guide for Python Code guidelines.我还进行了一些其他外观更改,以使代码更符合PEP 8 - Python 代码指南的样式指南

The specific error you're asking about is caused because you're passing callfrom here: tk.Listbox.__init__(self, master, callfrom) .你问一下具体的错误是因为,您将造成callfrom这里: tk.Listbox.__init__(self, master, callfrom)

The listbox widget doesn't know what to do with callfrom , it expects the second positional argument to be a dictionary.列表框小部件不知道如何处理callfrom ,它期望第二个位置参数是字典。

The proper way to initialize the class is without callfrom .初始化类的正确方法是不使用callfrom You will need to save callfrom as an instance attribute if you need to use it outside of the __init__ .如果您需要在__init__之外使用它,则需要将callfrom保存为实例属性。

def __init__(self, master, callfrom):
    tk.Listbox.__init__(self, master)
    self.callfrom = callfrom
    ...


def show_list(self, event):
    x = self.callfrom.winfo_x()
    y = self.callfrom.winfo_y()
    h = self.callfrom.winfo_height()
    ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM