【问题标题】:Set Default Text for Autocomplete Entry Widget in Tkinter在 Tkinter 中为自动完成条目小部件设置默认文本
【发布时间】:2020-05-21 17:36:27
【问题描述】:

我正在使用具有一些简单字段的 tkinter 构建一个 GUI。我想出了如何使用 Entry 小部件的 textvariable 参数为它们默认值(我将这些值从 .pickle 文件加载到字典),但是我构建了一个字段以在用户输入值时使用自动完成.这是一个单独的类,我使用了我找到的代码here

我已经尝试了很多方法来在启动应用程序时加载这个小部件中的值,比如返回值和使用 set() 方法,但我没有成功。我要么得到错误,要么什么也没发生。我在小部件中输入的值确实会成功保存到我的 pickle 文件中。

我还在学习使用 python 进行面向对象编程,所以请放轻松。那么如何修改下面的代码来显示默认值呢?

from Tkinter import *
import re

lista = ['a', 'actions', 'additional', 'also', 'an', 'and', 'angle', 'are', 'as', 'be', 'bind','bracket', 'brackets', 'button', 'can', 'cases', 'configure', 'course', 'detail', 'enter', 'event', 'events', 'example', 'field', 'fields', 'for', 'give', 'important', 'in', 'information', 'is', 'it', 'just', 'key', 'keyboard', 'kind', 'leave', 'left', 'like', 'manager', 'many', 'match', 'modifier', 'most', 'of', 'or', 'others', 'out', 'part', 'simplify', 'space', 'specifier', 'specifies', 'string;', 'that', 'the', 'there', 'to', 'type', 'unless', 'use', 'used', 'user', 'various', 'ways', 'we', 'window', 'wish', 'you']


class AutocompleteEntry(Entry):
    def __init__(self, lista, *args, **kwargs):

        Entry.__init__(self, *args, **kwargs)
        self.lista = lista        
        self.var = self["textvariable"]
        if self.var == '':
            self.var = self["textvariable"] = StringVar()

        self.var.trace('w', self.changed)
        self.bind("<Right>", self.selection)
        self.bind("<Up>", self.up)
        self.bind("<Down>", self.down)

        self.lb_up = False

    def changed(self, name, index, mode):  

        if self.var.get() == '':
            self.lb.destroy()
            self.lb_up = False
        else:
            words = self.comparison()
            if words:            
                if not self.lb_up:
                    self.lb = Listbox()
                    self.lb.bind("<Double-Button-1>", self.selection)
                    self.lb.bind("<Right>", self.selection)
                    self.lb.place(x=self.winfo_x(), y=self.winfo_y()+self.winfo_height())
                    self.lb_up = True

                self.lb.delete(0, END)
                for w in words:
                    self.lb.insert(END,w)
            else:
                if self.lb_up:
                    self.lb.destroy()
                    self.lb_up = False

    def selection(self, event):

        if self.lb_up:
            self.var.set(self.lb.get(ACTIVE))
            self.lb.destroy()
            self.lb_up = False
            self.icursor(END)

    def up(self, event):

        if self.lb_up:
            if self.lb.curselection() == ():
                index = '0'
            else:
                index = self.lb.curselection()[0]
            if index != '0':                
                self.lb.selection_clear(first=index)
                index = str(int(index)-1)                
                self.lb.selection_set(first=index)
                self.lb.activate(index) 

    def down(self, event):

        if self.lb_up:
            if self.lb.curselection() == ():
                index = '0'
            else:
                index = self.lb.curselection()[0]
            if index != END:                        
                self.lb.selection_clear(first=index)
                index = str(int(index)+1)        
                self.lb.selection_set(first=index)
                self.lb.activate(index) 

    def comparison(self):
        pattern = re.compile('.*' + self.var.get() + '.*')
        return [w for w in self.lista if re.match(pattern, w)]

if __name__ == '__main__':
root = Tk()

entry = AutocompleteEntry(lista, root)
entry.grid(row=0, column=0)
Button(text='nothing').grid(row=1, column=0)
Button(text='nothing').grid(row=2, column=0)
Button(text='nothing').grid(row=3, column=0)

root.mainloop()

【问题讨论】:

  • @BryanOakley 抱歉 - 现在已修复..我认为

标签: python python-3.x tkinter tkinter-entry


【解决方案1】:

有一个现有的 AutocompleteEntry 小部件。

例子:

from ttkwidgets.autocomplete import AutocompleteEntry
import tkinter as tk

window = tk.Tk()

Label1 = tk.Label(window, text="Entry:")
Label1.pack(side='left', padx=10, pady=10)

test_values = ['one', 'two', 'three']

test_var = tk.StringVar(window)
test_var.set('Default Value')

Entry1 = AutocompleteEntry(window, width=20, textvariable=test_var, completevalues=test_values)
Entry1.pack(side='left', padx=10, pady=10)

window.mainloop()

【讨论】:

    【解决方案2】:

    好吧,在分析这段代码几个小时后,我想出了如何使用insert() 方法将值设为默认值。这样做后我的第一个问题是列表框在应用程序启动时默认也是活动的。通过将另一个 if 条件添加到 changed 函数,它不会打开列表框,直到值被清除。当我添加条件语句时,self.lb.destroy() 行在清除字段时会抛出错误:

    AttributeError: 'AutocompleteEntry' 对象没有属性 'lb'

    我不知道为什么会抛出这个错误,因为它在我添加条件之前就起作用了。但是,lb 没有在类或函数的其他任何地方定义。删除该行修复了错误,一切似乎都按预期工作。这是我所做的更改。如果其他人有更好的解决方案,请告诉我。

    class AutocompleteEntry(Entry):
        # add settings argument which is True or False    
        def __init__(self, lista, settings, *args, **kwargs):
    
            Entry.__init__(self, *args, **kwargs)
            self.lista = lista
            # define the self.settings object
            self.settings = settings
            self.var = self["textvariable"]
            if self.var == '':
                self.var = self["textvariable"] = StringVar()
            self.var.trace('w', self.changed)
            self.bind("<Return>", self.selection)
            self.bind("<Up>", self.up)
            self.bind("<Down>", self.down)
    
            self.lb_up = False
    
        def changed(self, name, index, mode):
    
            if self.var.get() == '':
                # self.lb.destroy() - removed this line
                self.lb_up = False
                # change this variable to False once the field is cleared
                self.settings = False 
            # add if condition - field is not empty and settings is True
            elif self.var.get() != '' and self.settings == True:
                self.lb_up = False
            else:
                words = self.comparison()
                if words:
                    if not self.lb_up:
                        self.lb = Listbox()
                        self.lb.bind("<Double-Button-1>", self.selection)
                        self.lb.bind("<Return>", self.selection)
                        self.lb.place(x=self.winfo_x(), y=self.winfo_y()+self.winfo_height())
                        self.lb_up = True
    
                    self.lb.delete(0, END)
                    for w in words:
                        self.lb.insert(END,w)
                else:
                    if self.lb_up:
                        self.lb.destroy()
                        self.lb_up = False
    

    最后一部分:

    if __name__ == '__main__':
        root = Tk()
        # define settings variable and add to AutoCompleteEntry arguments
        settings = True
        entry = AutocompleteEntry(lista, settings, root)
        entry.insert(END, "this is the default value")
        entry.grid(row=0, column=0)
        Button(text='nothing').grid(row=1, column=0)
        Button(text='nothing').grid(row=2, column=0)
        Button(text='nothing').grid(row=3, column=0)
    
        root.mainloop()
    

    【讨论】:

      猜你喜欢
      • 2013-12-06
      • 2016-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-17
      • 2015-12-11
      • 1970-01-01
      相关资源
      最近更新 更多