Tkinter Treeview双击事件调用focus和item方法获取选中值为空问题排查
Tkinter Treeview双击无法获取选中项值的解决方案
问题根因
- 你提供的复现代码中
OnDoubleClick方法仅写了pass占位,没有任何取值输出逻辑,自然无法拿到数据 - 直接用
self.tree.focus()取值不可靠:如果用户双击Treeview的空白区域,focus()会返回空字符串,自然拿不到对应行数据 - 该问题和MySQL完全无关,你当前用的是SQLite数据库,就算切换为MySQL也不会影响Treeview的取值逻辑
解决方法
优先通过双击事件的坐标定位点击的行,避免空白点击异常,同时保证拿到的是用户实际点击的行数据,修改后的OnDoubleClick方法如下:
def OnDoubleClick(self, event): # 根据点击的y坐标定位对应行ID row_id = self.tree.identify_row(event.y) # 校验是否点击到有效行 if not row_id: return # 获取行的全部属性,其中values字段就是你插入的行数据,顺序和定义的columns顺序完全一致 row_info = self.tree.item(row_id) print("选中行数据:", row_info['values']) # 按需取对应列的值,示例:取ID、名称、输入数据 app_id, name, input_data = row_info['values'] print(f"ID: {app_id}, 名称: {name}, 输入数据: {input_data}")
get_children返回无序的解决方法
self.tree.get_children()返回的行顺序和你调用insert方法插入的顺序完全一致,如果你需要固定顺序,直接在SQL查询语句末尾加排序规则即可,比如按ID升序排列:
SELECT id_Application, (SELECT name_organisation FROM database_client WHERE database_client.email == database_client_application.email), input_data FROM database_client_application ORDER BY id_Application ASC -- 新增排序规则
修正后完整可运行代码
import sqlite3 import tkinter as tk from tkinter import ttk class Main(tk.Frame): def OnDoubleClick(self, event): # 根据点击的y坐标定位对应行ID row_id = self.tree.identify_row(event.y) # 校验是否点击到有效行 if not row_id: return # 获取行的全部属性,其中values字段就是你插入的行数据,顺序和定义的columns顺序完全一致 row_info = self.tree.item(row_id) print("选中行数据:", row_info['values']) # 按需取对应列的值,示例:取ID、名称、输入数据 app_id, name, input_data = row_info['values'] print(f"ID: {app_id}, 名称: {name}, 输入数据: {input_data}") def __init__(self, root): super().__init__(root) self.db = db toolbar = tk.Frame(bg='#d7d8e0', bd=2) toolbar.pack(side=tk.TOP, fill=tk.X) self.tree = ttk.Treeview(columns=('ID', 'Name', 'input_data'), height=60, show='headings') self.tree.column('ID', width=60, anchor=tk.CENTER) self.tree.column('Name', width=500, anchor=tk.CENTER) self.tree.column('input_data', width=500, anchor=tk.CENTER) self.tree.heading('ID', text='№') self.tree.heading('Name', text='Name') self.tree.heading('input_data', text='Input data') self.db.c.execute(''' SELECT id_Application, (SELECT name_organisation FROM database_client WHERE database_client.email == database_client_application.email), input_data FROM database_client_application ORDER BY id_Application ASC ''') # 清空旧数据 for i in self.tree.get_children(): self.tree.delete(i) # 插入新数据 for row in self.db.c.fetchall(): self.tree.insert('', 'end', values=row) self.tree.pack() self.tree.bind("<Double-1>", self.OnDoubleClick) class DB: def __init__(self): self.conn = sqlite3.connect('db.db') self.c = self.conn.cursor() if __name__ == "__main__": root = tk.Tk() db = DB() app = Main(root) w = root.winfo_screenwidth() // 2 h = root.winfo_screenheight() // 2 root.geometry('1000x900+{}+{}'.format(w - 500, h - 450)) root.mainloop()
内容的提问来源于stack exchange,提问作者Westfalen
相关产品推荐
相关产品推荐

