簡體   English   中英

Python Tkinter與類

[英]Python Tkinter with classes

嘗試開發用於工作的應用程序,我想將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()

是的,您可以通過更改類變量store_numbertld_date來使它們分開。 為此,您需要從輸入框中獲取數字並將其另存為變量。 我們可以通過調用self.store_number = self.entStore.get()self.tld_date = self.entDate.get()來方便地完成此操作

MainUI.py

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 在將類變量設置為所輸入的值並銷毀根窗口之前,此函數將兩個變量存儲為storeNumbertldDate

Controller.py

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()函數,這意味着它下面的任何代碼都將運行。 只要用戶界面處於打開狀態,它下面的代碼就不會運行。 因此,當關閉根窗口時,將運行其下面的代碼,並保存兩個變量供以后使用。 您應該在其中注釋掉一些錯誤檢查代碼。


使用.pack()

我個人不使用.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()

最好的方法是使用組件。 使用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參數不是您的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()

我讓您選擇是否應該在模塊的根目錄或類內部進行。 這就是控制器應該在的地方。 控制器是您的業務邏輯在圖形組件之外的組件。

使用框架可讓您:

  • 將UI邏輯與業務邏輯分開
  • 混合布局(表格框架中的網格,外部包裝以進行組件流動)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM