对 tkinter 中给出的列表中的数据进行匹配排序

发布于 2025-01-10 11:12:21 字数 2561 浏览 2 评论 0原文

我正在做一个项目,其中有数据建议

,我在网上看到了很多方法,但没有一个能派上用场,我做了一点工作并按一些方法排序,这个自动建议工作正常但很笨拙,所以可以任何请说一下如何优化数据

# importing only  those functions
# which are needed
from tkinter import *

# creating tkinter window
root = Tk()
root.title('Sample')
root.geometry('400x400')

# this assigns the name value
name = StringVar()

# this is list values
list_box_data = ['Apple', "Ball", "Cat"]

name_lab = Label(root, width=15, text="Name")
name_lab.place(x=50, y=100)

Entry_box = Entry(root, width=15, textvariable=name)
Entry_box.place(x=150, y=100)

submit_but = Button(root, width=12, text='Print')
submit_but.place(x=150, y=150)

# there are listbox creation
list_box = Listbox(root, height=10, width=15)


def search_name(event):
    """when a key was pressed in entry box this method is called"""
    # list_box is placed
    list_box.place(x=150, y=120)

    # assigning the methods to listbox
    list_box.bind('<Leave>', curse_out)
    list_box.bind('<Double-1>', items_selected)
    list_box.bind('<Return>', items_selected)

    # this checks the list is existed or not
    if list_box_data is not None:
        # this checks for the match in phone numbers list and assigned as matched list
        match = [i for i in list_box_data if name.get() in i]

        # for inserting new data delete the old data
        list_box.delete(0, END)

        # this for add data to the listbox
        for c in match:
            list_box.insert(END, c)

        # if no existing match then the list box closes
        if not match:
            curse_out(None)

    # if the entry box is empty then it close the list box
    if name.get() == "":
        curse_out(None)


def items_selected(event):
    """when the no is selected from list box it aligned to
    the name and gives the data"""

    # this when selected the data to following happens
    for i in list_box.curselection():
        name_data = list_box.get(i)
        name.set(name_data)
        curse_out(None)


def print_text():
    print(name.get())


def curse_out(event):
    """this is the command whey the cursor is out form box it closes"""
    try:
        list_box.place_forget()
    except BaseException:
        pass


submit_but.config(command=print_text)
Entry_box.bind("<KeyRelease>", search_name)
Entry_box.bind("<Down>", lambda event: list_box.focus_set())

root.mainloop()

该代码运行良好,但几乎没有问题。

  1. 时,我们是否可以(集中)输入框和列表框
  2. 当列表框打开并在其他小部件上选择时,该框始终打开,而不是关闭,因此每次我想要此条目并建议整个代码应该 一次又一次地重复,我们可以通过仅传递(列表和条目)将其转换为类方法,这样它就不会笨拙

I am working on a project, where there is suggestion of data

I had seen many methods online, but none of them came handy, I worked a little bit and sort by little methods, this auto suggestion is working fine but clumsy, so can any one please say how to optimize the data

# importing only  those functions
# which are needed
from tkinter import *

# creating tkinter window
root = Tk()
root.title('Sample')
root.geometry('400x400')

# this assigns the name value
name = StringVar()

# this is list values
list_box_data = ['Apple', "Ball", "Cat"]

name_lab = Label(root, width=15, text="Name")
name_lab.place(x=50, y=100)

Entry_box = Entry(root, width=15, textvariable=name)
Entry_box.place(x=150, y=100)

submit_but = Button(root, width=12, text='Print')
submit_but.place(x=150, y=150)

# there are listbox creation
list_box = Listbox(root, height=10, width=15)


def search_name(event):
    """when a key was pressed in entry box this method is called"""
    # list_box is placed
    list_box.place(x=150, y=120)

    # assigning the methods to listbox
    list_box.bind('<Leave>', curse_out)
    list_box.bind('<Double-1>', items_selected)
    list_box.bind('<Return>', items_selected)

    # this checks the list is existed or not
    if list_box_data is not None:
        # this checks for the match in phone numbers list and assigned as matched list
        match = [i for i in list_box_data if name.get() in i]

        # for inserting new data delete the old data
        list_box.delete(0, END)

        # this for add data to the listbox
        for c in match:
            list_box.insert(END, c)

        # if no existing match then the list box closes
        if not match:
            curse_out(None)

    # if the entry box is empty then it close the list box
    if name.get() == "":
        curse_out(None)


def items_selected(event):
    """when the no is selected from list box it aligned to
    the name and gives the data"""

    # this when selected the data to following happens
    for i in list_box.curselection():
        name_data = list_box.get(i)
        name.set(name_data)
        curse_out(None)


def print_text():
    print(name.get())


def curse_out(event):
    """this is the command whey the cursor is out form box it closes"""
    try:
        list_box.place_forget()
    except BaseException:
        pass


submit_but.config(command=print_text)
Entry_box.bind("<KeyRelease>", search_name)
Entry_box.bind("<Down>", lambda event: list_box.focus_set())

root.mainloop()

The code is working good in but with little issues.

  1. when the list box is open and selecting on other widgeds the box is open always, its not closing, so can we (focus in) entry box and list box at a time
  2. every time I want to have this entry and suggestion the whole code should be repeated again and again, can we convert it into class method by passing (list and entry) only so its wont be clumsy

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我一直都在从未离去 2025-01-17 11:12:21
  1. 对于你的第一个问题,这似乎是关于能力
    一次聚焦多个 tkinter 小部件,这是不可能的。这
    您当前使用的实现是您能做的最好的事情,即
    将向下箭头键绑定到将焦点置于
    列表框。

    Entry_box.bind("", lambda 事件: list_box.focus_set())
    

    除此之外,还可以绑定向上键
    列表框到一个函数,检查第一个项目当前是否
    选择,如果是这样,它将焦点切换到 Entry 小部件。

    def set_entry_focus(事件) :
        if list_box.curselection()[0] == 0 : Entry_box.focus_set()
        返回
    list_box.bind("<向上>", set_entry_focus)
    

    注意:在这里,我们使用 tkinter 列表框小部件的 curselection 方法来 获取当前选中的所有项目的索引
    以元组的形式,然后我们获取该假设的第 0 个索引
    列表框已设置为一次仅选择一项。

  2. 你提到的第二个问题不一定是问题,但是
    也许有待完成的事情,因为您的代码当前没有
    似乎正在定义任何类。如果给定一个可以使用的代码,并且
    需要解决的问题,我将非常乐意附上解决方案
    稍后在此答案的编辑部分中。

添加了条目焦点的完整代码将变为 -:

# importing only  those functions
# which are needed
from tkinter import *

# creating tkinter window
root = Tk()
root.title('Sample')
root.geometry('400x400')

# this assigns the name value
name = StringVar()

# this is list values
list_box_data = ['Apple', "Ball", "Cat"]

name_lab = Label(root, width=15, text="Name")
name_lab.place(x=50, y=100)

Entry_box = Entry(root, width=15, textvariable=name)
Entry_box.place(x=150, y=100)

submit_but = Button(root, width=12, text='Print')
submit_but.place(x=150, y=150)

# there are listbox creation
list_box = Listbox(root, height=10, width=15)


def search_name(event):
    """when a key was pressed in entry box this method is called"""
    # list_box is placed
    list_box.place(x=150, y=120)

    # assigning the methods to listbox
    list_box.bind('<Leave>', curse_out)
    list_box.bind('<Double-1>', items_selected)
    list_box.bind('<Return>', items_selected)

    # this checks the list is existed or not
    if list_box_data is not None:
        # this checks for the match in phone numbers list and assigned as matched list
        match = [i for i in list_box_data if name.get() in i]

        # for inserting new data delete the old data
        list_box.delete(0, END)

        # this for add data to the listbox
        for c in match:
            list_box.insert(END, c)

        # if no existing match then the list box closes
        if not match:
            curse_out(None)

    # if the entry box is empty then it close the list box
    if name.get() == "":
        curse_out(None)


def items_selected(event):
    """when the no is selected from list box it aligned to
    the name and gives the data"""

    # this when selected the data to following happens
    for i in list_box.curselection():
        name_data = list_box.get(i)
        name.set(name_data)
        curse_out(None)


def print_text():
    print(name.get())


def curse_out(event):
    """this is the command whey the cursor is out form box it closes"""
    try:
        list_box.place_forget()
    except BaseException:
        pass

def set_entry_focus(event) :
    if list_box.curselection()[0] == 0 : Entry_box.focus_set()
    return

submit_but.config(command=print_text)
Entry_box.bind("<KeyRelease>", search_name)
Entry_box.bind("<Down>", lambda event: list_box.focus_set())
list_box.bind("<Up>", set_entry_focus)

root.mainloop()

另外,我注意到 OP 中提供的自动完成检查器并未按预期工作。它不是将条目文本与列表项的前几个字符匹配,而是将条目索引 1 处的字符与列表项匹配。它还以区分大小写的方式进行匹配。

注意:如果自动完成器的任何这些功能是有意的,那么上面提供的完整代码仍然包含以前使用的方法,并且本节牢记此答案能够帮助任何未来的访问者。

因此,我也对其进行了一些调整以更好地工作 -:

## NOW IT CHECKS THE FIRST N LETTERS OF EACH LIST ITEM, WHERE N IS THE LENGTH
## OF THE TEXT TYPED IN THE ENTRY, IT ALSO NOW DOES NOT DEPEND ON CAPS.
match = [i for i in list_box_data if name.get() in i[ : len(name.get())].lower()]

更改后的完整 search_name 函数将如下所示 -:

def search_name(event):
    """when a key was pressed in entry box this method is called"""
    # list_box is placed
    list_box.place(x=150, y=120)

    # assigning the methods to listbox
    list_box.bind('<Leave>', curse_out)
    list_box.bind('<Double-1>', items_selected)
    list_box.bind('<Return>', items_selected)

    # this checks the list is existed or not
    if list_box_data is not None:
        # this checks for the match in phone numbers list and assigned as matched list
        ## NOW IT CHECKS THE FIRST N LETTERS OF EACH LIST ITEM, WHERE N IS THE LENGTH
        ## OF THE TEXT TYPED IN THE ENTRY, IT ALSO NOW DOES NOT DEPEND ON CAPS.
        match = [i for i in list_box_data if name.get() in i[ : len(name.get())].lower()]

        # for inserting new data delete the old data
        list_box.delete(0, END)

        # this for add data to the listbox
        for c in match:
            list_box.insert(END, c)

        # if no existing match then the list box closes
        if not match:
            curse_out(None)

    # if the entry box is empty then it close the list box
    if name.get() == "":
        curse_out(None)
  1. For your first issue, which seems to be regarding the ability to
    focus multiple tkinter widgets, at once, it is not possible. The
    current implementation being used by you is the best you can do i.e.
    bind the down arrow key to a function that brings focus to the
    listbox.

    Entry_box.bind("<Down>", lambda event: list_box.focus_set())
    

    In addition to this, you can also bind the up arrow key of the
    listbox to a function that checks if the first item is currently
    selected, if so it switches focus to the Entry widget.

    def set_entry_focus(event) :
        if list_box.curselection()[0] == 0 : Entry_box.focus_set()
        return
    list_box.bind("<Up>", set_entry_focus)
    

    NOTE: Here, we use the curselection method of the tkinter listbox widget, to get the index of all the currently selected items
    in the form of a tuple, we then fetch the 0th index of that assuming
    that the listbox has been set to only select one item at a time.

  2. The second issue you mentioned is not necessarily an issue but
    something pending to do perhaps, as your code currently does not
    seem to be defining any classes. If given a code to work with, and a
    problem to fix, I will be more than happy to attach the solution
    later in the EDIT section of this answer.

The full code with the entry focus addition will become -:

# importing only  those functions
# which are needed
from tkinter import *

# creating tkinter window
root = Tk()
root.title('Sample')
root.geometry('400x400')

# this assigns the name value
name = StringVar()

# this is list values
list_box_data = ['Apple', "Ball", "Cat"]

name_lab = Label(root, width=15, text="Name")
name_lab.place(x=50, y=100)

Entry_box = Entry(root, width=15, textvariable=name)
Entry_box.place(x=150, y=100)

submit_but = Button(root, width=12, text='Print')
submit_but.place(x=150, y=150)

# there are listbox creation
list_box = Listbox(root, height=10, width=15)


def search_name(event):
    """when a key was pressed in entry box this method is called"""
    # list_box is placed
    list_box.place(x=150, y=120)

    # assigning the methods to listbox
    list_box.bind('<Leave>', curse_out)
    list_box.bind('<Double-1>', items_selected)
    list_box.bind('<Return>', items_selected)

    # this checks the list is existed or not
    if list_box_data is not None:
        # this checks for the match in phone numbers list and assigned as matched list
        match = [i for i in list_box_data if name.get() in i]

        # for inserting new data delete the old data
        list_box.delete(0, END)

        # this for add data to the listbox
        for c in match:
            list_box.insert(END, c)

        # if no existing match then the list box closes
        if not match:
            curse_out(None)

    # if the entry box is empty then it close the list box
    if name.get() == "":
        curse_out(None)


def items_selected(event):
    """when the no is selected from list box it aligned to
    the name and gives the data"""

    # this when selected the data to following happens
    for i in list_box.curselection():
        name_data = list_box.get(i)
        name.set(name_data)
        curse_out(None)


def print_text():
    print(name.get())


def curse_out(event):
    """this is the command whey the cursor is out form box it closes"""
    try:
        list_box.place_forget()
    except BaseException:
        pass

def set_entry_focus(event) :
    if list_box.curselection()[0] == 0 : Entry_box.focus_set()
    return

submit_but.config(command=print_text)
Entry_box.bind("<KeyRelease>", search_name)
Entry_box.bind("<Down>", lambda event: list_box.focus_set())
list_box.bind("<Up>", set_entry_focus)

root.mainloop()

Also, I noticed that the autocomplete checker provided in the OP, was not working as probably intended. Instead of matching the entry text with the first few characters of the list item, it matched the character at entry index 1 to the list items. It also was matching in a case sensitive manner.

NOTE: Incase any of these features of the autocompleter were intended, then the above provided full code still contains the approach previously used and this section is keeping in mind the ability of this answer to help any future visitors.

I have thus also tweaked it a little bit to work better -:

## NOW IT CHECKS THE FIRST N LETTERS OF EACH LIST ITEM, WHERE N IS THE LENGTH
## OF THE TEXT TYPED IN THE ENTRY, IT ALSO NOW DOES NOT DEPEND ON CAPS.
match = [i for i in list_box_data if name.get() in i[ : len(name.get())].lower()]

The full search_name function after the change would look like this -:

def search_name(event):
    """when a key was pressed in entry box this method is called"""
    # list_box is placed
    list_box.place(x=150, y=120)

    # assigning the methods to listbox
    list_box.bind('<Leave>', curse_out)
    list_box.bind('<Double-1>', items_selected)
    list_box.bind('<Return>', items_selected)

    # this checks the list is existed or not
    if list_box_data is not None:
        # this checks for the match in phone numbers list and assigned as matched list
        ## NOW IT CHECKS THE FIRST N LETTERS OF EACH LIST ITEM, WHERE N IS THE LENGTH
        ## OF THE TEXT TYPED IN THE ENTRY, IT ALSO NOW DOES NOT DEPEND ON CAPS.
        match = [i for i in list_box_data if name.get() in i[ : len(name.get())].lower()]

        # for inserting new data delete the old data
        list_box.delete(0, END)

        # this for add data to the listbox
        for c in match:
            list_box.insert(END, c)

        # if no existing match then the list box closes
        if not match:
            curse_out(None)

    # if the entry box is empty then it close the list box
    if name.get() == "":
        curse_out(None)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文