在 Tkinter 的 for 循环中处理多个小部件

Address multiple widgets in a for loop in Tkinter

我需要一种方法来解决 TKinter 中的多个小部件,例如 for 循环中的标签、条目或比例,然后再编辑它们。它是更大 GUI 的一部分,如果没有解决方案,代码将会太长且令人困惑。下面的例子应该能说明问题。

import tkinter as tk
import tkinter.ttk as ttk

class NewprojectApp:
    def __init__(self, master=None):
        # build the GUI
        self.frame1 = ttk.Frame(master)
        self.scale1 = tk.Scale(self.frame1)
        self.scale1.configure(label="scale2", orient="horizontal")
        self.scale1.grid(column="0", row="1")
        self.scale2 = tk.Scale(self.frame1)
        self.scale2.configure(label="scale3", orient="horizontal")
        self.scale2.grid(column="0", row="2")
        self.scale3 = tk.Scale(self.frame1)
        self.scale3.configure(label="scale4", orient="horizontal")
        self.scale3.grid(column="0", row="3")
        self.button1 = ttk.Button(self.frame1)
        self.button1.configure(text="set default value")
        self.button1.grid(column="0", pady="5", row="4")
        self.button1.configure(command=self.set_value)
        self.frame1.configure(height="200", width="200")
        self.frame1.grid(column="0", row="0")

        # Main widget
        self.mainwindow = self.frame1

    def run(self):
        self.mainwindow.mainloop()

    def set_value(self):
        # set the value of multiples scales to a new value 
        self.scale1.set(20)
        self.scale2.set(20)
        self.scale3.set(20)
        
        """
        I want to change functions like the one above into for loops;
        The following is something I tried out but that didn't work
        
        for i in range(1,3):
            current_scale = 'self.scale' + str(i)
            current_scale.set(20)
        """
            
if __name__ == "__main__":
    root = tk.Tk()
    app = NewprojectApp(root)
    app.run()

非常感谢您!

对于您要实现的目标,有不同的选择。

要保持​​ for 循环,您可以这样做:

def set_value(self):
    for i in range(1, 4):
        getattr(self, f'scale{i}').set(20)

这样,您就正确地使用了 i 作为变量来寻址小部件。显然,您应该注意寻址正确的小部件(例如,为 getattr 设置 default,或使用 try,或确保 hasattr(self, scale{i})

另一种方法可能是在适当的时候迭代 self、运行 set 的元素:

def set_value(self):
    for widget_name in dir(self):
        widget = getattr(self, widget_name)
        if isinstance(widget, tk.Scale):  # ensure widget is of Scale class
            widget.set(20)

最后,您可以简单地定义一个要迭代的小部件列表:

class NewprojectApp:
    def __init__(self, master=None):
        # build the GUI
        self.frame1 = ttk.Frame(master)
        self.button1 = ttk.Button(self.frame1)
        self.button1.configure(text="set default value")
        self.button1.grid(column="0", pady="5", row="4")
        self.button1.configure(command=self.set_value)
        self.frame1.configure(height="200", width="200")
        self.frame1.grid(column="0", row="0")

        # Define your scales
        self.scales = []
        for i in range(1, 4):
            self.scales.append(tk.Scale(self.frame1))
            self.scales[-1].configure(label=f"scale{i}", orient="horizontal")
            self.scales[-1].grid(column=0, row=i)

        # You could also initiate your scales indipendently and then do:
        # self.scales = [scale1, scale2, scale3]

        # Main widget
        self.mainwindow = self.frame1

    def run(self):
        self.mainwindow.mainloop()

    def set_value(self):
        for scale in self.scales:
            scale.set(20)

在这种情况下,当你要解决单个规模时,你必须注意。您也可以同时保留 self.scale{i}self.scales.

可能还有很多其他方法可以达到这个结果,但您可以从这里开始,找到最适合您的方法:)