尝试开发用于工作的应用程序,我想将UI和主控制器类代码分开。我应该如何处理?
我创建了MainUi类。
class MainUi:
store_number = ''
tld_date = ''
def __init__(self, root):
self.root = root
root.title("TacoBell TLD Tool")
self.store_number = IntVar()
self.tld_date = IntVar()
self.lblstore_number = Label(root, text="Store Number (XXXXXX): ")
self.lbltld_date = Label(root, text="TLD Date(MM/DD/YYYY): ")
self.lblstore_number.grid(row=0, sticky=E) # Sticky align text North(N), East(E), South(S), West(W0
self.lbltld_date.grid(row=1, sticky=E)
self.entStore = Entry(self.root, textvariable=self.store_number)
self.entDate = Entry(self.root, textvariable=self.tld_date)
self.entStore.grid(row=0, column=1)
self.entDate.grid(row=1, column=1)
我需要定义getter和setter吗?我希望这些条目存储在我的主类中的两个变量中,以便我可以将主类中的变量传递给其他函数。
import paramiko
import os
import csv
import tools
from ui import MainUi
from tkinter import *
root = Tk()
ui = MainUi(root)
# get store number and date data from UI.py and store them as variables here
root.mainloop()
答案 0 :(得分:1)
是的,您可以通过更改类变量store_number
和tld_date
来使它们分开。为此,您需要从输入框中获取数字并将其保存为变量。我们可以方便地调用self.store_number = self.entStore.get()
或self.tld_date = self.entDate.get()
from tkinter import *
class LaunchMainUi:
store_number = ''
tld_date = ''
def __init__(self, root):
self.root = root
root.title("TacoBell TLD Tool")
self.store_number = IntVar()
self.tld_date = IntVar()
Label(root, text="Store Number (XXXXXX): ").grid(row=0, sticky=E) # Sticky align text North(N), East(E), South(S), West(W)
Label(root, text="TLD Date(MM/DD/YYYY): ").grid(row=1, sticky=E)
self.entStore = Entry(self.root)
self.entDate = Entry(self.root)
self.entStore.grid(row=0, column=1)
self.entDate.grid(row=1, column=1)
self.confirm = Button(root, text="Confirm", command=self.save)
self.confirm.grid(row=2, column=1)
def save(self, event=None):
storeNumber = self.entStore.get()
tldDate = self.entDate.get()
#Saved as method variables ^ in order to perform necessary validation checks easier
#If entered items are valid:
self.store_number = storeNumber
self.tld_date = tldDate
self.root.destroy()
我首先更改了类的名称,以使文件名和类名不冲突。然后,我创建了一个名为self.confirm
的按钮,并将其命令设置为self.save
。在将类变量设置为所输入的值并销毁根窗口之前,此函数将两个变量存储为storeNumber
和tldDate
。
import MainUI
from tkinter import *
root = Tk()
ui = MainUI.LaunchMainUi(root)
root.mainloop() #Keeps the ui instance running until closed, then the rest of the code is run
storeNum = ui.store_number
tldDate = ui.tld_date
print('Store Number: {}\nTLD Date: {}'.format(storeNum, tldDate)) #This line is to show that the variables can be accessed
因为我们破坏了根实例,所以返回了mainloop()
函数,这意味着它下面的任何代码都将运行。只要用户界面处于打开状态,它下面的代码就不会运行。因此,当关闭根窗口时,将运行其下面的代码,并保存两个变量供以后使用。您应该在注释掉的地方添加一些错误检查代码。
我个人不使用.grid()
,因为这样做可能会造成一些混乱。相反,我喜欢使用.pack()
和封装。如果您想使用.pack()
,那么这里的另一个__init__
的用法也一样。在此__init__
上,我还使GUI看起来不太标准,并带有一些TacoBell颜色:)
def __init__(self, root):
self.root = root
self.root.title("TacoBell TLD Tool")
self.root.geometry('600x300')
font20 = 'Calibri 20'
bfont20 = font20 + ' bold'
Label(self.root, text='TacoBell TLD Tool', font=bfont20, fg='purple').pack()
topItems = Frame(self.root)
Label(topItems, text="Store Number (XXXXXX): ", font=font20).pack(side=LEFT) # Sticky align text North(N), East(E), South(S), West(W)
self.entStore = Entry(topItems, font=font20)
self.entStore.pack(side=RIGHT)
topItems.pack(pady=20)
lowItems = Frame(self.root)
Label(lowItems, text="TLD Date(MM/DD/YYYY): ", font=font20).pack(side=LEFT)
self.entDate = Entry(lowItems, font=font20)
self.entDate.pack(side=RIGHT)
lowItems.pack(pady=20)
self.confirm = Button(root, text="Confirm", bg='purple', fg='white', font=bfont20, width=30, command=self.save)
self.confirm.pack()
答案 1 :(得分:0)
最好的方法是使用组件。使用tkinter,您应该通过扩展Frame
类来定义组件。因此您的代码应如下所示:
class StoreForm(tkinter.Frame):
store_number = ''
tld_date = ''
def __init__(self, root, **kw):
super().__init__(**kw)
root.title("TacoBell TLD Tool")
self.store_number = tkinter.IntVar()
self.tld_date = tkinter.IntVar()
self.lblstore_number = tkinter.Label(self, text="Store Number (XXXXXX): ")
self.lbltld_date = tkinter.Label(self, text="TLD Date(MM/DD/YYYY): ")
self.lblstore_number.grid(row=0, sticky=E) # Sticky align text North(N), East(E), South(S), West(W0
self.lbltld_date.grid(row=1, sticky=E)
self.entStore = tkinter.Entry(self, textvariable=self.store_number)
self.entDate = tkinter.Entry(self, textvariable=self.tld_date)
self.entStore.grid(row=0, column=1)
self.entDate.grid(row=1, column=1)
请注意,root
参数不是您的根目录,而是该框架的预期容器。
这样,您就有了一个可重复使用的独立图形组件。该组件管理视图逻辑(显示窗口小部件,如果需要,它们之间的交互),但不管理应用程序逻辑,这是控制器的工作。但是要使用该控制器,您应该能够从该组件获取数据和/或提供一些数据。为此,您应该添加方法。即使我使用类似的名称,我也不会称它们为getter和setter。
def get_data(self):
return self.store_number.get(), self.tld_date.get()
def set_data(self, store_number_value, tld_date_value):
self.store_number.set(store_number_value)
self.tld_date.set(tld_date_value)
现在,在主模块中,您可以添加类似内容
MAIN_UI = tkinter.Tk()
form = StoreForm(MAIN_UI).pack()
我让您选择是在模块的根目录还是在类内部进行。这就是控制器应该在的地方。控制器是您的业务逻辑在图形组件之外的组件。
使用相框可让您: