如何从Python3x中使用带有lamda的按钮调用的类中的函数调用函数?

问题描述 投票:0回答:1

我有一个类:例如 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 的按钮的机制是这里的问题吗?

python-3.x tkinter lambda combobox
1个回答
0
投票

使用您的 之前的问题 代码作为上下文,您会遇到这些错误,原因是您定义

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()
© www.soinside.com 2019 - 2024. All rights reserved.