在新窗口中根据另一个StringVar值更新包含StringVar的输入框值
就像标题说的,我想根据另一个StringVar变量的值来更新一个StringVar变量,这两个变量在不同的窗口中。你会看到的。我知道代码可能会有点乱,但请耐心点。最开始我们创建了几个按钮,这些按钮会生成我写好的SQL脚本。当我按下一个按钮时,会打开一个新窗口,我在里面输入数据库名称、表名、列名等等。当我在entry2这个输入框中输入正确的表名时,函数show_columns会打印出数据库中的正确列名,并把它们放在一个叫str的字符串变量里。假设数据库的名字是DATABASE。我想把str变量的内容放到一个和entry3输入框绑定的列变量里。我该怎么做呢?
def show_columns(table):
query = f"select * from [DATABASE].[dbo].[{table}] where 1=0"
cursor = conn.cursor()
str = ''
try:
cursor.execute(query)
column_names = [column[0] for column in cursor.description]
for column in column_names: str += f"[{column}],"
print(str)
except:
print('Error!')
def open_window(text, button):
# Create a new window
new_window = Toplevel()
# Set the window title and size
new_window.title(text)
new_window.geometry("600x460")
new_window.config(bg="light gray")
new_window.resizable(False, False)
database = StringVar()
table = StringVar()
column = StringVar()
# Create some text fields
label1 = Label(new_window, text="Database name:").grid(row=0, column=0, pady=5)
entry1 = Entry(new_window, textvariable=database).grid(row=0, column=1, padx=5, pady=5)
label2 = Label(new_window, text="Table name:").grid(row=1, column=0, pady=5)
entry2 = Entry(new_window, textvariable=table).grid(row=1, column=1, padx=5, pady=5)
label3 = Label(new_window, text="Column name:").grid(row=2, column=0, pady=5)
entry3 = Entry(new_window, textvariable=column).grid(row=2, column=1, padx=5, pady=5)
table.trace_add('write', lambda name, index, mode, sv=table: show_columns(sv.get()))
window = Tk()
#code for connecting to database
#Set the window title, size and oclor
window.title('SQL script generator')
window.geometry("800x600")
window.config(bg="gray")
window.resizable(False, False)
command_names = ['Delete duplicates while keeping the original',
'Delete duplicates without keeping the original',
'Retrive all data from table',
'Check for duplicates',
'Delete table',
'Copy data from one table to another',
'Update values',
'Add new column to exisitng table']
canvas = Canvas(window)
canvas.pack(side='left', fill='both', expand=True)
# Create two frames
search_frame = Frame(canvas)
search_frame.pack(side='top')
buttons_frame = Frame(canvas)
buttons_frame.pack(side='bottom')
canvas.create_window((0, 0), window=buttons_frame, anchor='nw')
i = 0
for i, text in enumerate(command_names):
Button(buttons_frame, text=command_names[i], width=40, height=2, command=lambda text = text, index = i: open_window(text, index)).grid(row=i+1, column=0, pady=5, padx=5)
i += 1
buttons_frame.update_idletasks()
window.mainloop()
1 个回答
我把你的代码改成了面向对象编程的方式。在我看来,这样更容易阅读,而且你可以用实例变量在类的方法之间交换值,而不需要直接传递它们。比如,你可以在 __init__
方法里引入 database
、table
和 column
这些变量,并在前面加上 self
,然后在 show_columns
方法里,直接用 self.column.set(str)
来设置变量。
注意,在我的代码里,我把 str
替换成了 output
,因为 str
已经在标准库中被使用了。这一版本在 show_columns_v2
方法中展示。
你也可以把 entry3
传入 show_columns
方法,然后用 insert
方法把结果放入 entry
中。这里要注意的是,你是把 entry3
赋值为 grid
方法的返回值,而不是 entry
。在我的代码中,我先创建了 entry3
,然后再对它应用 grid
方法。
注意:因为我没有你的数据库,所以我在 except
语句块里设置了变量或插入了值到 entry
中。
这是我的代码:
from tkinter import Tk, Toplevel, Label, Entry, Canvas, Frame, Button, StringVar
class GUI(Tk):
def __init__(self): # create own GUI class which inherits from Tk → window is now self
super().__init__()
# Set the window title, size and oclor
self.title('SQL script generator')
self.geometry("800x600")
self.config(bg="gray")
self.resizable(False, False)
command_names = ['Delete duplicates while keeping the original',
'Delete duplicates without keeping the original',
'Retrive all data from table',
'Check for duplicates',
'Delete table',
'Copy data from one table to another',
'Update values',
'Add new column to exisitng table']
canvas = Canvas(self)
canvas.pack(side='left', fill='both', expand=True)
# Create two frames
search_frame = Frame(canvas)
search_frame.pack(side='top')
buttons_frame = Frame(canvas)
buttons_frame.pack(side='bottom')
canvas.create_window((0, 0), window=buttons_frame, anchor='nw')
# Create instance variables
self.database = StringVar(self, value='')
self.table = StringVar(self, value='')
self.column = StringVar(self, value='')
# Create Buttons with loop
for i, text in enumerate(command_names):
Button(buttons_frame, text=command_names[i], width=40, height=2,
command=lambda: self.open_window(text)).grid(row=i + 1, column=0, pady=5, padx=5)
def open_window(self, text):
# Create a new window
new_window = Toplevel()
# Set the window title and size
new_window.title(text)
new_window.geometry("600x460")
new_window.config(bg="light gray")
new_window.resizable(False, False)
# Create some text fields
Label(new_window, text="Database name:").grid(row=0, column=0, pady=5)
entry1 = Entry(new_window, textvariable=self.database)
entry1.grid(row=0, column=1, padx=5, pady=5)
Label(new_window, text="Table name:").grid(row=1, column=0, pady=5)
entry2 = Entry(new_window, textvariable=self.table)
entry2.grid(row=1, column=1, padx=5, pady=5)
Label(new_window, text="Column name:").grid(row=2, column=0, pady=5)
entry3 = Entry(new_window, textvariable=self.column)
entry3.grid(row=2, column=1, padx=5, pady=5)
#self.table.trace_add('write', lambda name, index, mode, entry=entry3: self.show_columns(sv.get(), entry))
# version to set by changing self.column directly
self.table.trace_add('write', lambda name, index, mode: self.show_columns_v2())
# version without instance vaiable by inserting to entry directly
def show_columns(self, entry3):
table = self.table.get()
query = f"select * from [DATABASE].[dbo].[{table}] where 1=0"
output = ''
try:
cursor = conn.cursor()
cursor.execute(query)
column_names = [column[0] for column in cursor.description]
for column in column_names:
output += f"[{column}],"
print(output)
except:
print(f'Error for Table {table}!')
# test to set entry
output = 'test'
entry3.insert(0, output)
# version 2 setting StringVar directly
def show_columns_v2(self):
table = self.table.get()
query = f"select * from [DATABASE].[dbo].[{table}] where 1=0"
output = ''
try:
cursor = conn.cursor()
cursor.execute(query)
column_names = [column[0] for column in cursor.description]
for column in column_names:
output += f"[{column}],"
print(output)
except:
print(f'Error for Table {table}!')
# test to set entry
output = 'test'
self.column.set(output)
if __name__ == '__main__':
gui = GUI()
gui.mainloop()
顺便说一下:也许你不应该通过 table.trace_add('write'...
来触发 show_columns
方法,除非你把表名复制到这个字段里。因为如果你每输入一个字母,函数就会被触发。相反,你可以插入一个按钮,比如“搜索列”,这样就可以触发 show_columns
方法。