Python tkinter列表框绑定在 仅在第二次单击上有效

问题描述 投票:0回答:1

如果有其他讨论已经解决了这个问题,但我没有找到任何东西,我先向您道歉。我是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()

``` 

谢谢,如果我的代码冒犯了任何人,我们深表歉意!

python sqlite tkinter listbox bind
1个回答
0
投票

由于我没有sqlite3数据库,所以没有运行您的代码,可能会很遥远,但是当选择一个可以绑定到的值<<ListboxSelect>>时,列表框会生成一个虚拟事件。尝试替换:

lb1.bind("<Button-1>", selectitem)

with

lb1.bind("<<ListboxSelect>>", selectitem)
© www.soinside.com 2019 - 2024. All rights reserved.