如果有其他讨论已经解决了这个问题,但我没有找到任何东西,我先向您道歉。我是Python的新手(因此,除了90年代的Pascal一点点编程之外)。
我正在构建一个带有tk输入框的GUI,供用户输入值,然后将其存储在sqlite数据库中。我希望用户能够从列表框中的一个字段中单击值,然后将使用所选记录的所有字段的值重新填充tk Entry框。我已经能够做到这一点,但是当我将列表框绑定到填充Button-1上的tk Entry框的函数时,它仅在第二次单击时有效。第一次单击会产生以下错误,我已经在其他问题中看到了该错误,但是我无法将这些答案转化为我的情况:
错误:
追踪(最近通话):在call中的文件“ ... \ Python \ Python38-32 \ lib \ tkinter__init __。py”,行1883返回self.func(* args)selectitem中的文件“ fe.py”,第108行selecteditem.append(lb1.get(ndex))在get中的文件“ ... \ Python \ Python38-32 \ lib \ tkinter__init __。py”,行3182返回self.tk.call(self._w,'get',first)_tkinter.TclError:列表框索引错误“”:必须处于活动状态,锚点,结尾,@ x,y或数字
这里是复制错误的示例代码-要使用,请首先通过Setup-> Items菜单添加几个值,方法是填写VAL和REF框,然后单击Add Item按钮。然后单击列表框中的一项。第一次单击应产生上面的错误。当您第二次单击时,“输入”框应填充:
```
import sqlite3
import itertools
import tkinter as tk
from tkinter import ttk
INTRO_FONT = ("Arial", 72)
LARGE_FONT = ("Arial", 12)
NORMAL_FONT = ("Arial", 10)
SMALL_FONT = ("Arial", 8)
#Function to create database
def create_db():
conn = sqlite3.connect("demo.db")
cur = conn.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS demotable (id INTEGER PRIMARY KEY, val TEXT, ref TEXT)")
conn.commit()
conn.close()
#Create database
create_db()
#Main Class to manage frames
class demo(tk.Tk):
def __init__(self,*args,**kwargs):
tk.Tk.__init__(self,*args,**kwargs)
container = tk.Frame(self)
container.pack(side="top",fill="both",expand=True)
container.grid_rowconfigure(0,weight=1)
container.grid_columnconfigure(0,weight=1)
menubar = tk.Menu(container)
filemenu = tk.Menu(menubar,tearoff=0)
filemenu.add_command(label="Exit", command=quit)
menubar.add_cascade(label="File", menu=filemenu)
setupmenu = tk.Menu(menubar, tearoff=0)
setupmenu.add_command(label="Items",command = lambda: self.show_frame(Itemsetuppage))
menubar.add_cascade(label="Setup", menu=setupmenu)
tk.Tk.config(self, menu=menubar)
self.frames={}
for F in (Itemsetuppage,Itemsetuppage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(Itemsetuppage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
# Frame that inserts and loads values
class Itemsetuppage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
#Function to populate listbox with values
def popitemlist(self):
lb1.delete(0, tk.END)
for item in itemlist():
lb1.insert(tk.END, item)
#Function to add new item to database
def additem():
additem_db(val.get(), ref.get())
val_entry.delete(0, 'end')
ref_entry.delete(0, 'end')
popitemlist(self)
#Function used to populate tk.Entry boxes from database when item in listbox is clicked
def selectitem(event):
global selecteditem
selecteditem = []
ndex = lb1.curselection()
selecteditem.append(lb1.get(ndex))
itemquery = select_item(selecteditem)
val_entry.delete(0, 'end')
val_entry.insert(0, itemquery[1])
ref_entry.delete(0, 'end')
ref_entry.insert(0, itemquery[2])
#Function to query database for values to populate lb1
def itemlist():
conn = sqlite3.connect("demo.db")
cur = conn.cursor()
cur.execute("SELECT DISTINCT val FROM demotable")
results = cur.fetchall()
itemlist = list(itertools.chain(*results))
conn.commit()
conn.close()
return itemlist
#Function to insert values from tk.Entry boxes to database
def additem_db(val, ref):
conn = sqlite3.connect("demo.db")
cur = conn.cursor()
cur.execute("INSERT OR IGNORE INTO demotable VALUES (NULL, ?, ?)",(val,ref))
conn.commit()
conn.close()
#Function to query database for individual record to populate tk.Entry boxes when item is clicked in lb1
def select_item(val):
conn = sqlite3.connect("demo.db")
cur = conn.cursor()
cur.execute("SELECT * FROM demotable WHERE val=?",(val))
results = cur.fetchall()
itemdetail = list(itertools.chain(*results))
conn.commit()
conn.close()
return itemdetail
l1 = tk.Label(self, text="Values in database:")
l1.grid(row=0, column=0, padx=5, pady=5)
lb1 = tk.Listbox(self, selectmode=tk.SINGLE)
lb1.grid(row=1, column=0, padx=5, pady=5)
popitemlist(self)
lb1.bind("<Button-1>", selectitem)
l2 = tk.Label(self, text="Type val into entry box to store:")
l2.grid(row=0, column=1, padx=5, pady=5)
val = tk.StringVar(self)
val_entry = tk.Entry(self, textvariable=val)
val_entry.grid(row=0, column=2, padx=5, pady=5)
l2 = tk.Label(self, text="Type ref into entry box to store:")
l2.grid(row=1, column=1, padx=5, pady=5)
ref = tk.StringVar(self)
ref_entry = tk.Entry(self, textvariable=ref)
ref_entry.grid(row=1, column=2, padx=5, pady=5)
b1 = tk.Button(self, text="Add item",command=additem)
b1.grid(row=2, column=2, padx=5, pady=5)
app = demo()
app.geometry("480x240")
app.mainloop()
```
谢谢,如果我的代码冒犯了任何人,我们深表歉意!
由于我没有sqlite3数据库,所以没有运行您的代码,可能会很遥远,但是当选择一个可以绑定到的值<<ListboxSelect>>
时,列表框会生成一个虚拟事件。尝试替换:
lb1.bind("<Button-1>", selectitem)
with
lb1.bind("<<ListboxSelect>>", selectitem)