我有一个类:例如 MyClassName,有两个函数:一个用于计算数字,一个用于验证一组组合框(tkinter)是否都具有选择。 我还使用 tkinter 作为按钮来使用 lambda 调用计算函数,因为我希望用户进行组合框选择,然后按计算按钮,因此需要 lambda。
这是按钮代码:
# Calculate Button
self.calculate_button = ttk.Button(button_frame,
command = lambda: calculate(self), # Use a lambda to send params to the function for command.
width = 12,
text = "CALCULATE",
bootstyle = 'primary',
state = 'enabled')
# In the calculate function, I call another function:
def calculate(self):
# Call the Class function from within another Class function.
self.validate_Comboboxes() ...
在 validate_Comboboxes 函数中我使用类似这样的东西:
# Function to validate if all the Comboboxes were selected.
def validate_Comboboxes(self):
for widget in self.base_frame.winfo_children():
if isinstance(widget, ttk.Combobox) and widget.get() == "":
messagebox.showerror("error", "All Comboboxes for the base frame must be selected for calculations!")
break
...
我在这个应用程序之外独立测试了 validate_Comboboxes 函数,所以我知道它是有效的。 但是,我收到此错误:AttributeError:'MyClassName'对象没有属性'validate_Comboboxes'。这似乎是我没有正确声明它? 我知道如果它只是一个类属性,您可以使用: myAttribute(self) 来声明它,但是 validate_Comboboxes(self) 对我来说没有意义,因为我使用 def 语句声明它,除非我遗漏了一些东西?
针对我的用例进行编码的正确方法是什么,主要是为了验证用户在点击计算按钮之前是否已选择所有组合框?
我想如果一个类中有两个函数,比如 functionA(self) 和 functionB(self),你可以使用 self.function() 从 functionB 调用 functionA。 那么使用带有 lamdda 的按钮的机制是这里的问题吗?
使用您的 之前的问题 代码作为上下文,您会遇到这些错误,原因是您定义
validateComboboxes
、calculate
和 clear
函数的范围。
考虑以下是您的代码的摘要版本...
class ComboBoxTestGroup:
def __init__(self, master):
...
...
def calculate(self):
...
def clear(self):
...
def validateComboboxes(self):
...
由于前面提到的三个函数是在
__init__
方法体内定义的,因此这些函数不会绑定到 ComboBoxTestGroup
实例,并且只能由在 __init__
方法范围内执行的代码访问。 再加上您使用的 lambda 将在运行时评估,这意味着当您尝试调用 calculate(self)
时,函数定义将不再存在。
有一个非常简单的解决方案。 在类的主体/范围中定义您的方法,而不是
__init__
方法。 这将确保函数将绑定到类实例,并且在实例对象的生命周期内保持可调用状态。
示例:
import tkinter
from tkinter import *
from tkinter import messagebox
from tkinter.ttk import Combobox
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
window = ttk.Window(themename = 'superhero')
window.title('Combobox Test Group')
window.geometry('1200x275')
class ComboBoxTestGroup:
def __init__(self, master):
# Create the main frame.
self.main_frame = ttk.Frame(master, relief=SUNKEN, borderwidth=1)
self.main_frame.grid(row=0, column=0)
# Dropdowns
self.base_frame = tkinter.LabelFrame(self.main_frame, text='BASE', relief=SUNKEN, borderwidth=1)
self.base_frame.grid(row=4, column=0, sticky="news", padx=10, pady=15)
self.base_label_ti = ttk.Label(self.base_frame, text='Technical Interface (TI)', font=('Helvetica', 10))
self.base_label_ti.grid(row=0, column=0)
self.ti_values = [("High", "H", "1.0"), ("Medium", "M", "0.5"), ("Low", "L", "0.1"), ("None", "N", "0.0")]
self.ti_combobox = ttk.Combobox(self.base_frame, bootstyle='primary', values=self.ti_values, state = 'readonly')
self.ti_combobox.grid(row=1, column=0)
self.base_label_ap = ttk.Label(self.base_frame, text='Application Project (AP)', font=('Helvetica', 10))
self.base_label_ap.grid(row=0, column=1)
self.ap_values = [("High", "H", "1.0"), ("Medium", "M", "0.5"), ("Low", "L", "0.1"), ("None", "N", "0.0")]
self.ap_combobox = ttk.Combobox(self.base_frame, bootstyle='primary', values=self.ap_values, state = 'readonly')
self.ap_combobox.grid(row=1, column=1)
self.base_label_al = ttk.Label(self.base_frame, text='Application Logs (AL)', font=('Helvetica', 10))
self.base_label_al.grid(row=0, column=2)
self.al_values = [("High", "H", "1.0"), ("Medium", "M", "0.5"), ("Low", "L", "0.1"), ("None", "N", "0.0")]
self.al_combobox = ttk.Combobox(self.base_frame, bootstyle='primary', values=self.al_values, state = 'readonly')
self.al_combobox.grid(row=1, column=2)
self.base_label_ic = ttk.Label(self.base_frame, text='Internal Composition (IC)', font=('Helvetica', 10))
self.base_label_ic.grid(row=0, column=3)
self.ic_values = [("High", "H", "1.0"), ("Medium", "M", "0.5"), ("Low", "L", "0.1"), ("None", "N", "0.0")]
self.ic_combobox = ttk.Combobox(self.base_frame, bootstyle='primary', values=self.ic_values, state = 'readonly')
self.ic_combobox.grid(row=1, column=3)
self.base_label_fc = ttk.Label(self.base_frame, text='Fixed Controls (FC)', font=('Helvetica', 10))
self.base_label_fc.grid(row=0, column=4)
self.fc_values = [("High", "H", "1.0"), ("Medium", "M", "0.5"), ("Low", "L", "0.1"), ("None", "N", "0.0")]
self.fc_combobox = ttk.Combobox(self.base_frame, bootstyle='primary', values=self.fc_values, state = 'readonly')
self.fc_combobox.grid(row=1, column=4)
# For loop to space widgets within the base_frame
for widget in self.base_frame.winfo_children():
widget.grid_configure(padx=20, pady=10)
# Create a frame for the buttons.
button_frame = ttk.Frame(self.main_frame, relief=SUNKEN, borderwidth=1)
button_frame.grid(row=5, column=0)
# Validate Button
self.calculate_button = ttk.Button(button_frame,
command = self.calculate, # no need for lambda
width = 12,
text = "VALIDATE",
bootstyle = 'primary',
state = 'enabled')
self.calculate_button.grid(row=10, column=0, padx=75, pady=10)
# Clear Button
self.clear_button = ttk.Button(button_frame,
command=self.clear, # no need for lambda
width = 12,
text = "CLEAR",
bootstyle = 'primary',
state = 'enabled')
self.clear_button.grid(row=10, column=1, padx=75, pady=10)
def calculate(self):
self.validateComboboxes()
# Function to clear the ttk widgets.
def clear(self):
# This clears the Comboboxes by the enclosing frame.
for widget in self.base_frame.winfo_children():
if isinstance(widget, ttk.Combobox):
widget.set("")
# Function to validate if all the Comboboxes were selected.
def validateComboboxes(self):
for widget in self.base_frame.winfo_children():
if isinstance(widget, ttk.Combobox) and widget.get() == "":
messagebox.showerror("error", "All Comboboxes must be selected in order to do calculations!")
widget_class = ComboBoxTestGroup(window)
# Run the GUI
window.mainloop()