【问题标题】:Python - Can I use a lambda function to generate a repetitive GUI with tkinter? (labels/text/buttons)Python - 我可以使用 lambda 函数通过 tkinter 生成重复的 GUI 吗? (标签/文本/按钮)
【发布时间】:2019-03-04 12:53:11
【问题描述】:

我有一个非常重复的 GUI 来实现 - 想想数十个标签/文本/按钮字段,用于数据输入表单。每个重复部分的大小可以相同 - 事实上,除了标签中的文本和文本字段中的数据在完成时分配给的变量之外,所有内容都可以相同。

我曾与一位工程师合作,他使用 lambda 函数以非常复杂的方式生成子函数,我几乎遵循了这种方式,但不是 100%。我希望,因为这是一个类似的,主要是重复性的任务,有某种方法可以使用公式函数为我重复 GUI 创建工作,而不是必须输入每个 GUI 项目。

函数是否可以生成重复的 GUI 元素,如果可以,那是 lambda 函数吗?或者有没有不同(或更好)的方式来完成同样的“不重复自己”?

【问题讨论】:

  • 不清楚你的意思。真的没有“lambda 函数”这样的东西。 lambda 表达式 只是一个表达式,其值为function 对象,就像def 语句在执行时创建一个function 对象一样。
  • 有两种方法可以减少代码重复:函数和类。两者本质上都不比另一个更好。我们无法告诉您使用哪一个。这是您的决定。
  • @chepner 是的,一个 lambda 表达式。过失。
  • @Aran-Fey 我相信我没有足够详细地解释这个问题。如果我没有找到基于一些新搜索的答案,我将尝试添加示例代码...

标签: python user-interface tkinter lambda tk


【解决方案1】:

函数是否可以生成重复的 GUI 元素,如果可以,那是 lambda 函数吗?

是的,可以使用函数创建 gui 元素,不,它不是 lambda 函数。不仅可以,而且可以说是在函数中创建 gui 元素的最佳实践,尽管您也可以只使用简单的循环或常规函数。

在创建以某种方式捆绑在一起的小部件组时,最好创建一个自定义类,该类可以封装所有行为并为程序的其余部分提供一个简单的接口。

示例

在下面的示例中,我们要创建一系列带有标签、条目和提交按钮的小部件。它将被实现为一个类,因为我们实际上是在创建一个表示一个表单字段的对象。

注意:以下代码假设您使用 import tkinter as tk 导入 tkinter。

首先,让我们创建一个回调,在字典中设置一个值,并打印出该值以进行调试。回调将被赋予字段的名称,以及用户输入的值:

data = {}
def handle_submit(name, value):
    print("you submitted '%s' for %s" % (value, name))
    data[name] = value

接下来,创建 10 个项目的代码可能如下所示:

root = tk.Tk()
for i in range(1, 11):
    field_name = "field %s" % i
    row = CustomWidget(root, name=field_name, callback=handle_submit)

最后,我们需要创建我们的类。我们从 tk.Frame 继承,以便我们可以像使用任何其他 tkinter 小部件一样使用它。它需要为其父级、字段名称以及用户按下提交时要调用的函数获取参数:

class CustomWidget(tk.Frame):
    def __init__(self, parent, name, callback):
        tk.Frame.__init__(self, parent)

        self.name = name
        label_text = name.title() + ":"
        self.callback = callback
        self.label = tk.Label(self, text=label_text, anchor="e")
        self.entry = tk.Entry(self)
        self.button = tk.Button(self, text="Submit", command=self.submit)

        self.button.pack(side="right")
        self.label.pack(side="left")
        self.entry.pack(side="left", fill="x", expand=True)

    def submit(self):
        self.callback(self.name, self.entry.get())

【讨论】:

  • 我正在删除我原来的评论,因为我一定是在某种程度上隔开并错过了你一半的答案。现在我会重新阅读它,是的,我确实看到了循环。我觉得很害羞……
  • 极好的例子,虽然我必须在创建行后添加 .pack() 调用。但是,self.entry.pack() 中的 fill 没有正确发生。我更正了关于fill="x" 的语法错误,因为tk 希望填充引用tk 对象X。是否有理由专门让CustomWidgettk.Frame 继承,而不是只传递Frame,如果我@987654332 @?
  • 不要介意fill 不起作用。虽然fill 参数可以引用Tk 对象(例如fill=BOTHfill=X),但我使用的是嵌套框架,并且自定义框架的父框架没有设置为展开。
  • @user3.1415927:tk 变量 X 只是一个常量,其值为 "x"。您可以使用常量,也可以使用文字字符串。 Tkinter 不在乎。
  • @user3.1415927: _"Is there a reason to specifically have CustomWidget inherit from tk.Frame, instead of passing it just Frame"_ - yes, I imported tkinter "as tk", which is the preferred way to import tkinter. Since that's how I imported it, every tkinter class needs to be prefixed with tk.`.
猜你喜欢
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-27
  • 2020-10-14
  • 2012-04-10
相关资源
最近更新 更多