python - 在 Tkinter 的类之间传递值
问题描述
我正在开发一个小型 GUI 来从我们的 CMDB 查询信息以显示给用户。我遇到的麻烦是在一个类中的事件发生(按钮)之后,我想更新另一个类中的组合框。我想我应该使用 tk.StringVar() 来传递列表,但组合框只显示一个 'PC_VAR#' 值并且不会更新。有人可以提供任何帮助吗?
#!/usr/bin/python
import Tkinter as tk
import ttk
import signal
class LoginUI:
def __init__(self, frame):
self.frame = frame
# Set default list entry
self.dc_list = tk.StringVar()
self.dc_list.set(['Login first'])
# Add a button to log in
self.button = tk.Button(self.frame, text='Login', command=self.change_combobox)
self.button.grid(column=0, row=0, pady=5)
def change_combobox(self):
# Change combobox values
dc_list = ['Site_1', 'Site_2', 'Site_3']
self.dc_list.set(dc_list)
class QueryUI:
def __init__(self, frame, dc_list):
self.frame = frame
self.dc = tk.StringVar()
self.dc_list = tk.StringVar()
self.dc_list.set(dc_list)
# Create site combobox
tk.Label(self.frame, text='Site:').grid(column=0, row=0, sticky="w")
self.dc_combobox = ttk.Combobox(
self.frame,
textvariable=self.dc,
width=20,
state='readonly'
)
self.dc_combobox['values'] = self.dc_list.get()
self.dc_combobox.grid(column=1, row=0, sticky="w")
class App:
def __init__(self, root):
self.root = root
self.root.title('Logging Handler')
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
# Create the left frame panels
left_frame = tk.Frame(self.root, padx=5, pady=5)
login_frame = tk.LabelFrame(left_frame, text="Login", borderwidth=2, relief="groove", padx=5, pady=5)
query_frame = tk.LabelFrame(left_frame, text="Query", borderwidth=2, relief="groove", padx=5, pady=5)
# Align frames
left_frame.grid(row=0, column=0, sticky="nw")
login_frame.grid(row=0, column=0, pady=5, sticky="nw")
query_frame.grid(row=1, column=0, pady=5, sticky="nw")
# Initialize all frames
self.login = LoginUI(login_frame)
self.query = QueryUI(query_frame, self.login.dc_list)
self.root.protocol('WM_DELETE_WINDOW', self.quit)
self.root.bind('<Control-q>', self.quit)
signal.signal(signal.SIGINT, self.quit)
def quit(self, *args):
self.root.destroy()
def main():
root = tk.Tk()
app = App(root)
app.root.mainloop()
if __name__ == '__main__':
main()
解决方案
我在这里要做的是将控制类(应用程序)传递给更新组合框所需的类。这样我们可以在以后需要时与之交互。通过传递to,self
我们可以与from inside的类属性和方法进行交互。这使得更新组合框变得很简单。App
LoginUI
App
LoginUI
那就是说你真的不需要所有的 StringVars。只需将列表作为列表过去,您就可以开始了。
import Tkinter as tk
import ttk
import signal
class LoginUI:
def __init__(self, controller, frame):
self.controller = controller
self.frame = frame
self.dc_list = ['Login first']
self.button = tk.Button(self.frame, text='Login', command=self.change_combobox)
self.button.grid(column=0, row=0, pady=5)
def change_combobox(self):
self.controller.query.dc_combobox['values'] = ['Site_1', 'Site_2', 'Site_3']
self.controller.query.dc.set('Site_1')
class QueryUI:
def __init__(self, frame, dc_list):
self.frame = frame
self.dc = tk.StringVar()
tk.Label(self.frame, text='Site:').grid(column=0, row=0, sticky="w")
self.dc_combobox = ttk.Combobox(self.frame, textvariable=self.dc, width=20, state='readonly')
self.dc_combobox['values'] = dc_list
self.dc_combobox.grid(column=1, row=0, sticky="w")
class App:
def __init__(self, root):
self.root = root
self.root.title('Logging Handler')
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
left_frame = tk.Frame(self.root, padx=5, pady=5)
login_frame = tk.LabelFrame(left_frame, text="Login", borderwidth=2, relief="groove", padx=5, pady=5)
query_frame = tk.LabelFrame(left_frame, text="Query", borderwidth=2, relief="groove", padx=5, pady=5)
left_frame.grid(row=0, column=0, sticky="nw")
login_frame.grid(row=0, column=0, pady=5, sticky="nw")
query_frame.grid(row=1, column=0, pady=5, sticky="nw")
self.login = LoginUI(self, login_frame)
self.query = QueryUI(query_frame, self.login.dc_list)
self.root.protocol('WM_DELETE_WINDOW', self.quit)
self.root.bind('<Control-q>', self.quit)
signal.signal(signal.SIGINT, self.quit)
def quit(self, *args):
self.root.destroy()
if __name__ == '__main__':
root = tk.Tk()
app = App(root)
app.root.mainloop()