我正在 Tkinter 中重新制作一個 GUI 計算器應用程式,以了解類、方法、屬性,并縮短我的原始代碼。為了縮短代碼,我制作了一個框架類,可以生成框架、條目、標簽和下拉選單,因此我不必單獨創建它們。一切都很順利,直到我進入下拉選單部分。當用戶從過濾器 - 下拉選單(如 V、B 或 L 等)中選擇不同的選項時,第 1 幀 -> 條目 [1] 中的值不會更新。更新該條目中的值的方法稱為 add(self) ,它是計算器類的一部分。這是簡單的版本
import numpy as np
import tkinter as tk
window = tk.Tk()
window.geometry("920x500")
window.resizable(0,0)
window.title('Exposure Time Calculator')
class Calculator:
def __init__(self, window):
self.create_test_frame1()
self.create_test_frame2()
self.add(None)
def create_test_frame1(self):
labelvalues=['val 1','val 2']
entryvalues=['203','1333']
self.frame_1 = frame('Test Frame 1',labelvalues,entryvalues,6, 2, 0, 0, "no",0,0,0,0,0,30,40)
def create_test_frame2(self):
labelvalues = ['val 3','val 4']
entryvalues = ['10','24.5']
option_menu_values = ['B','V','R','I','Luminance','Hydrogen 3nm']
self.frame_2 = frame('Frame 2', labelvalues, entryvalues, 14, 2, 0, 2,
"option_menu1_yes", option_menu_values,'Filters',
0,0,0,
5,20)
def add(self, e):
qe = self.frame_1.entry[1]
bandOption = self.frame_2.clicked.get()
if bandOption == "B":
qe.delete(0,tk.END)
qe.insert(0,22)
elif bandOption == "V":
qe.delete(0,tk.END)
qe.insert(0,33)
class frame:
# Creates a frame class for automatic frame generation
# with entries, labels and/or option menus
# 1. name : frame name
# 2. label_default_values: name of labels
# 3. entry_default_values: default values in entries
# 4. entry_width: the entries dimensions
# 5. I: number of labels and entries
# 6. grid_row: frame grid row placement
# 7. grid_column: frame grid column placement
# 8. option_menu: true or false if user wants a option list or not
# 9. option_list_values: list for option menu
# 10. option_label: name for option menu label
# 11. ipax, ipady: padding
# 12. comand: comand for option list
def __init__(self, name, label_default_values, entry_default_values, entry_width, I, grid_row, grid_column,
option_menu1, option_list_values, option_label,
option_menu2, option2_list_values,option_label2,
ipad_x, ipad_y
):
self.name = name
self.label_default_values = label_default_values
self.entry_default_values = entry_default_values
self.I = I
self.grid_row = grid_row
self.grid_column = grid_column
self.dropMenu_options = option_list_values
self.label = option_label
self.entry_width = entry_width
self.dropMenu_options2 = option2_list_values
self.option_label2 = option_label2
self.ipad_x = ipad_x
self.ipad_y = ipad_y
frame = tk.LabelFrame(window, text = name, highlightbackground='grey', highlightthickness=1)
frame.grid(row=self.grid_row, column=self.grid_column, padx=5, pady=5, ipadx=ipad_x, ipady=ipad_y)
if option_menu1 == "option_menu1_yes":
self.clicked = tk.StringVar()
self.clicked.set(self.dropMenu_options[0])
self.drop = tk.OptionMenu(frame, self.clicked, *self.dropMenu_options, command = self.add)
self.drop.grid(row=5, column=1, sticky="ew")
label = tk.Label(frame, text = option_label, highlightbackground='grey', highlightthickness=1)
label.grid(row = 5, column = 0, sticky = "w")
if option_menu2 == "option_menu2_yes":
self.clicked2 = tk.StringVar()
self.clicked2.set(self.dropMenu_options2[0])
self.drop2 = tk.OptionMenu(frame, self.clicked2, *self.dropMenu_options2)
self.drop2.grid(row=6, column=1, sticky="ew")
label = tk.Label(frame, text = option_label2, highlightbackground='grey', highlightthickness=1)
label.grid(row = 6, column = 0, sticky = "w")
self.entry ={}
for i in range(0, self.I):
label = tk.Label(frame, text = self.label_default_values[i], justify = "left")
label.grid(row=i, column=0, sticky = "w")
self.entry[i] = tk.Entry(frame, textvariable = float(self.entry_default_values[i]), width=self.entry_width)
self.entry[i].grid(row=i, column=1, sticky = "e")
self.entry[i].delete(0, tk.END)
self.entry[i].insert(0, self.entry_default_values[i])
c=Calculator(window)
window.mainloop()
uj5u.com熱心網友回復:
該方法add在Calculator類中,因此self.add您需要呼叫add計算器而不是。由于框架不知道計算器是什么,所以在構建框架時需要將其傳入。
類似于以下內容,其中計算器實體作為第一個選項傳遞:
self.frame_1 = frame(self, 'Test Frame 1', ...)
接下來,你需要定義你的類接受并參照保存到計算器,然后在使用它command的OptionMenu:
class frame:
def __init__(self, calculator, name, ...):
self.calculator = calculator
...
self.drop = tk.OptionMenu(..., command = self.calculator.add)
另外,您可以add這樣定義:
def add(self, e):
我假設這意味著您認為第二個引數是一個事件物件。它不是。它是從選項選單中選擇的值。
可以說,定義它的更好方法是在提供時實際使用這個新值,如果未提供值則回退到呼叫get。此外,您可以將 if 陳述句的墻壁減少到單個字典查找中,以使代碼更短且更健壯。
def add(self, new_value=None):
qe = self.frame_1.entry[1]
bandOption = self.frame_2.clicked.get() if new_value is None else new_value
band = {"B": 22, "V": 33}
qe.delete(0, "end")
qe.insert(0, band[bandOption])
此解決方案的大小是原件的 2/3,并且更靈活且更易于維護。
uj5u.com熱心網友回復:
有2個問題:
- 第一個是您提到的并修復它:
重命名def add(self)為def add(self, e)和重命名add()為add(None). 然后lambda event: self.add改為self.add - 第二個是:
AttributeError: 'frame' object has no attribute 'frame_camera'但與問題無關
uj5u.com熱心網友回復:
如果我在類之外定義 add(event) ,它會起作用。
def add(event):
qe = c.frame_1.entry[1]
bandOption = c.frame_2.clicked.get()
if bandOption == "B":
qe.delete(0,tk.END)
qe.insert(0,22)
elif bandOption == "V":
qe.delete(0,tk.END)
qe.insert(0,33)
這在框架類中:
self.drop = tk.OptionMenu(frame, self.clicked, *self.dropMenu_options, command = lambda event:add(event))
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/407827.html
標籤:
