Tkinter - 双击获取条目文本(for循环)
Posted
技术标签:
【中文标题】Tkinter - 双击获取条目文本(for循环)【英文标题】:Tkinter - Get Entry text on double click (for loop) 【发布时间】:2019-06-19 20:21:24 【问题描述】:我正在制作一个使用 Pymysql 模块获取数据库记录的程序,然后我想在 Tkinter Entries 中显示这些记录。我已经有了执行此操作的代码,但我想添加一个功能。
我想为用户提供双击行的条目的功能,并获取该行的所有条目文本并将它们解析到我在 For 循环之前声明的文本框(用户 ID、名字等等)。 假设我每行有 5 个条目。如果用户双击(例如)第 1 行的第 2 项条目,我想从第 1 行的所有条目中获取文本并将它们分别解析到文本框中。
这是我目前拥有的代码:
window = tk.Tk()
window.title("Flexbase") #Give window a name
window.update_idletasks()
width = 640
height = 480
x = (window.winfo_screenwidth() // 2) - (width // 2)
y = (window.winfo_screenheight() // 2) - (height // 2)
window.geometry('++'.format(x, y))
GetRows_StringVariable = "SELECT * FROM SEC_USER"
cursor.execute(GetRows_StringVariable)
results = cursor.fetchall()
RowCounter = 1
ColumnCounter = -1
ListCounter = 0
RowListCounter = 0
rows = []
id_list = []
firstname_list = []
surname_list = []
username_list = []
email_list = []
password_list = []
tk.Label(window, text="Testing").grid(row=0, column=0, sticky=NSEW)
UserID_TextBox = tk.Entry(window, width=20, bg="white") #Create text box
UserID_TextBox.grid(row=1, column=0, sticky=W) #Give the text box a position in the window
FirstName_TextBox = tk.Entry(window, width=60, bg="white")
FirstName_TextBox.grid(row=2, column=0, sticky=W)
Surname_TextBox = tk.Entry(window, width=60, bg="white")
Surname_TextBox.grid(row=3, column=0, sticky=W)
Email_TextBox = tk.Entry(window, width=60, bg="white")
Email_TextBox.grid(row=4, column=0, sticky=W)
Username_TextBox = tk.Entry(window, width=20, bg="white")
Username_TextBox.grid(row=5, column=0, sticky=W)
Password_TextBox = tk.Entry(window, show="*", width=20, bg="white")
Password_TextBox.grid(row=6, column=0, sticky=W)
notebook = ttk.Notebook(window)
notebook.grid(row=7, column=0, sticky=NSEW)
page1 = ttk.Frame(notebook)
notebook.add(page1, text="Mass Editing Mode")
tk.Label(page1, text=SQL_ID, fg="black", font="Arial 8 bold").grid(row=0, column=0, sticky=W)
tk.Label(page1, text=SQL_FIRSTNAME, fg="black", font="Arial 8 bold").grid(row=0, column=1, sticky=W)
tk.Label(page1, text=SQL_SURNAME, fg="black", font="Arial 8 bold").grid(row=0, column=2, sticky=W)
tk.Label(page1, text=SQL_USERNAME, fg="black", font="Arial 8 bold").grid(row=0, column=3, sticky=W)
tk.Label(page1, text=SQL_EMAIL, fg="black", font="Arial 8 bold").grid(row=0, column=4, sticky=W)
for row in results: # Page 1 TAB
ColumnCounter += 1
id_list.append(row[SQL_ID])
a = tk.Entry(page1, fg="black", font="Arial 8 bold")
a.grid(row=RowCounter, column=ColumnCounter, sticky=W)
a.insert(0, row[SQL_ID])
ColumnCounter += 1
firstname_list.append(row[SQL_FIRSTNAME])
b = tk.Entry(page1, fg="black", font="Arial 8 bold")
b.grid(row=RowCounter,column=ColumnCounter,sticky=W)
b.insert(0, row[SQL_FIRSTNAME])
ColumnCounter += 1
surname_list.append(row[SQL_SURNAME])
c = tk.Entry(page1, fg="black", font="Arial 8 bold")
c.grid(row=RowCounter,column=ColumnCounter,sticky=W)
c.insert(0, row[SQL_SURNAME])
ColumnCounter += 1
username_list.append(row[SQL_USERNAME])
d = tk.Entry(page1, fg="black", font="Arial 8 bold")
d.grid(row=RowCounter, column=ColumnCounter, sticky=W)
d.insert(0, row[SQL_USERNAME])
ColumnCounter += 1
email_list.append(row[SQL_EMAIL])
e = tk.Entry(page1, fg="black", font="Arial 8 bold")
e.grid(row=RowCounter, column=ColumnCounter, sticky=W)
e.insert(0, row[SQL_EMAIL])
RowCounter += 1
ColumnCounter = -1
ListCounter += 1
RowListCounter += 1
此代码生成一个每行有 5 个条目的窗口。
【问题讨论】:
我认为您需要为您的问题添加足够的代码,以便它可以运行。这样,更多的人可能会努力为您提供答案。见How to create a Minimal, Complete, and Verifiable Example。 你可能想要treeview widget, Treeview widget inserting data @martineau 谢谢。我编辑了我的代码并使其可运行。 不清楚为什么需要解析行,因为显然,您已经将其拆分为每行多个条目小部件的单独值。 【参考方案1】:正如@Florian Weimer 已经解释的那样,您需要定义一个或多个回调函数并将其附加到每个Entry
。
除此之外,我认为您可以(并且应该)消除尽可能多的冗余代码,这将使其更小,并且更易于处理和增强。在软件开发中,这被称为DRY,代表“不要重复自己”的原则。
由于我没有你的数据库,我不得不添加这一行:
db_keys = results[0].keys() # Get list of keys from the first result.
获取每个记录/行中所需的键列表。您的数据库架构中可能已经有这样的列表,或者希望以不同的方式创建它。
import tkinter as tk
from tkinter import ttk
from tkinter.constants import *
window = tk.Tk()
window.title("Flexbase") #Give window entry name
window.update_idletasks()
width = 640
height = 480
x = (window.winfo_screenwidth() // 2) - (width // 2)
y = (window.winfo_screenheight() // 2) - (height // 2)
window.geometry('++'.format(x, y))
GetRows_StringVariable = "SELECT * FROM SEC_USER"
#cursor.execute(GetRows_StringVariable)
#results = cursor.fetchall()
db_keys = results[0].keys() # Get list of keys from the first result.
tk.Label(window, text="Testing").grid(row=0, column=0, sticky=NSEW)
# Create textbox Entry widgets.
textbox_ids = list(db_keys) + ['Password']
textbox_widths = 20, 60, 60, 60, 20, 20
textbox_shows = '', '', '', '', '', '*'
textboxes =
for i, (id, width, show) in enumerate(zip(textbox_ids, textbox_widths, textbox_shows), 1):
textboxes[id] = tk.Entry(window, width=width, show=show, bg="white")
textboxes[id].grid(row=i, column=0, sticky=W)
# Double-click callback function for items in result rows.
def double_click_cb(ev, row):
# Replace current values in textboxes with those from the selected row.
for key, value in row.items():
textboxes[key].delete(0, END)
textboxes[key].insert(0, value)
notebook = ttk.Notebook(window)
notebook.grid(row=7, column=0, sticky=NSEW)
page1 = ttk.Frame(notebook)
notebook.add(page1, text="Mass Editing Mode")
nb_font = "Arial 8 bold"
# Create header row.
for i, key in enumerate(db_keys):
tk.Label(page1, text=key, fg="black", font=nb_font).grid(row=0, column=i, sticky=W)
# Display results.
id_list = []
RowCounter = 1
for row in results:
for ColumnCounter, key in enumerate(db_keys):
id_list.append(row[key])
entry = tk.Entry(page1, fg="black", font=nb_font)
entry.grid(row=RowCounter, column=ColumnCounter, sticky=W)
entry.insert(0, row[key])
entry.bind("<Double-Button>", lambda e, r=row: double_click_cb(e, r))
RowCounter += 1
window.mainloop()
【讨论】:
【参考方案2】:您可以在创建 tk.Entry
对象后添加它:
for obj in (a, b, c, d):
def double_click(ev, RowCounter=RowCounter):
print("selected row:", RowCounter)
obj.bind("<Double-Button>", double_click)
(需要RowCounter=RowCounter
来捕获当前行值。)
有了行号,你应该可以从results
对象中得到你需要的东西。
【讨论】:
我是否在 for 循环之后添加它,在它的末尾之外? 不,必须为每一行调用它(这样所有条目小部件都会受到影响)。在递增RowCounter
之前需要调用bind
,这样行号值才正确。
如何将行数据解析到文本框中? (我编辑了我的问题)。
答案取决于您尝试解析的文本格式。以上是关于Tkinter - 双击获取条目文本(for循环)的主要内容,如果未能解决你的问题,请参考以下文章
OOP tkinter:如何将焦点(并添加文本)设置为条目?
在tkinter的treeview中的for循环中的每个父节点下添加子节点
python中tkinter treeview如何获取选中的条目