最初我在功能上撰寫了這個 tkinter 應用程式,但現在我將它轉換為 OOP,因為它變得如此臃腫,我遇到的主要問題是理解一種在大量類之間傳遞變數的簡化方法。
下面是我的代碼開始的最低測驗版本,其中定義了兩個變數Mainframe,我想首先傳遞給以FileSelect更新它們,然后傳遞給LoadFiles. 對我來說最大的困惑是為什么file_list在運行時似乎正確更新print_files,但import_state我想用來啟用按鈕的變數LoadFiles卻沒有。
import os
import tkinter as tk
from tkinter import filedialog
class MainFrame:
def __init__(self, master):
self.master = master
# Variables
self.file_list = [] # Files list
self.import_state = tk.DISABLED # Enable import on correct fp
# Class Frames
FileSelect(master, self.file_list, self.import_state)
LoadFiles(master, self.file_list, self.import_state)
class FileSelect:
def __init__(self, master, files, button_state):
self.files = files
self.button_state = button_state
# Frame
self.frame = tk.LabelFrame(master, text='File Selection')
self.frame.grid(row=0, column=0)
# Select directory button
tk.Button(self.frame, text='Open:', command=self.directory_path).grid(row=0, column=0)
# Tkinter Elements...
# Directory Selection
def directory_path(self):
# Select filepath
directory = filedialog.askdirectory(initialdir="/", title="Select a directory")
os.chdir(directory)
# Populate list of files
for tb in os.listdir(directory):
self.files.append(tb)
# Update GUI, activate button in different class if condition met
if len(os.listdir(directory)) == 0:
# Update GUI Labels...
self.button_state = tk.DISABLED
print(self.files, self.button_state)
elif len(self.files) == len(os.listdir(directory)):
# Update GUI Labels...
self.button_state = tk.NORMAL
print(self.files, self.button_state)
class LoadFiles:
def __init__(self, master, files, button_state):
self.files = files
self.button_state = button_state
# Frame
self.frame = tk.LabelFrame(master, text='File loading')
self.frame.grid(row=1, column=0)
# Load button
self.import_files_button = tk.Button(self.frame, text='Import TB', command=self.print_files)
self.import_files_button.grid(row=0, column=0, sticky="EW")
# Tkinter Elements...
def print_files(self):
print(self.files, self.button_state)
if __name__ == "__main__":
root = tk.Tk()
MainFrame(root)
root.mainloop()
除了類之間的變數傳遞問題,一般來說有沒有更簡化的方法呢?我看到 OOP 提倡的主要原因之一是它在多大程度上提高了可讀性、組織和隔離 tkinter 元素,但變數處理似乎是從函式轉換時的主要關鍵。
uj5u.com熱心網友回復:
不要傳遞單個變數,而是傳遞擁有變數的類的實體。這減少了您必須來回傳遞的東西的數量,并且它使代碼更具自我記錄性,因為很明顯這self.main.files.append(...)是附加到由主程式管理的串列而不是本地管理的串列。
class MainFrame:
def __init__(self, master):
...
FileSelect(master, main=self)
LoadFiles(master, main=self)
class FileSelect:
def __init__(self, master, main):
self.main = main
...
# Directory Selection
def directory_path(self):
# Select filepath
directory = filedialog.askdirectory(initialdir="/", title="Select a directory")
os.chdir(directory)
# Populate list of files
for tb in os.listdir(directory):
self.main.files.append(tb)
# Update GUI, activate button in different class if condition met
if len(os.listdir(directory)) == 0:
# Update GUI Labels...
self.main.button_state = tk.DISABLED
print(self.main.files, self.main.button_state)
elif len(self.files) == len(os.listdir(directory)):
# Update GUI Labels...
self.main.button_state = tk.NORMAL
print(self.main.files, self.main.button_state)
uj5u.com熱心網友回復:
只是為了跟進,Bryan 和 Martineau 的回答幫助解決了我的問題,但為了其他可能在處理 tkinter 小部件更新時遇到問題的人,我在下面包含了我的更新代碼,因為它self.main.file_load.import_files_button是一種明確解決變化的方法類之間的按鈕狀態,而我理解這一點的主要問題之一是缺乏明確的最小化示例:
import os
import tkinter as tk
from tkinter import filedialog
class MainFrame:
def __init__(self, master):
self.file_selection = FileSelect(master, main=self)
self.file_load = LoadFiles(master, main=self)
class FileSelect:
def __init__(self, master, main):
self.main = main
self.files = []
# Frame
self.frame = tk.LabelFrame(master, text='File Selection')
self.frame.grid(row=0, column=0)
# Select directory button
tk.Button(self.frame, text='Open:', command=self.directory_path).grid(row=0, column=0)
# Directory Selection
def directory_path(self):
# Select filepath
directory = filedialog.askdirectory(initialdir="/", title="Select a directory")
os.chdir(directory)
# Populate list of files
for tb in os.listdir(directory):
self.files.append(tb)
# Update GUI, activate button in different class if condition met
if len(os.listdir(directory)) == 0:
self.main.file_load.import_files_button['state'] = tk.DISABLED
else:
self.main.file_load.import_files_button['state'] = tk.NORMAL
class LoadFiles:
def __init__(self, master, main):
self.main = main
# Frame
self.frame = tk.LabelFrame(master, text='File loading')
self.frame.grid(row=1, column=0)
# Load button
self.import_files_button = tk.Button(self.frame, text='Import TB', command=self.print_files,
state=tk.DISABLED)
self.import_files_button.grid(row=0, column=0, sticky="EW")
# Tkinter Elements...
def print_files(self):
print(self.main.file_selection.files)
if __name__ == "__main__":
root = tk.Tk()
MainFrame(root)
root.mainloop()
希望有人覺得這很有用!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/405999.html
標籤:
上一篇:使用tkinter頂級父/子視窗時如何避免破壞資料?
下一篇:自定義Tkinter影像
