【问题标题】:Kivy- All dynamically created buttons (in for loop) return the same argumentKivy - 所有动态创建的按钮(在 for 循环中)返回相同的参数
【发布时间】:2020-03-18 13:34:48
【问题描述】:

我正在尝试制作密码锁应用程序。

我面临的问题是我想为每个用户名创建一个按钮,然后在单击按钮时执行一个函数,该函数根据单击的按钮采用不同的参数。 但无论单击哪个按钮,无论它自己的用户名如何,与之关联的函数总是采用最后创建的按钮的参数。我想知道为什么会发生这种情况。

我用于创建按钮和复制该用户名密码的代码:

class CopyCredentialWindow(Screen):
    def __init__(self, **kwargs):
        super(CopyCredentialWindow, self).__init__(**kwargs)
        self.scroll = ScrollView(size_hint=(1, 1), do_scroll_y=True, do_scroll_x=False, scroll_timeout=55, bar_width=10)
        self.grid = GridLayout(cols=1, size_hint_y=None)
        self.grid.bind(minimum_height=self.grid.setter('height'))
    def on_enter(self):
        button_list = []
        for i in self.manager.credentials:
            button_list.append(Button(text=i[8:], size_hint_y=None, height=40, on_release=lambda x: self.do_accordingly(i)))
            self.grid.add_widget(button_list[-1])
        self.scroll.add_widget(self.grid)
        self.ids.grid.add_widget(self.scroll)
    def delete_dropdown(self):
        self.grid.clear_widgets()
        self.scroll.clear_widgets()
        self.ids.grid.remove_widget(self.scroll)
    def do_accordingly(self, account_name):
        credentials = self.manager.credentials
        password = credentials[account_name]
        password = password.encode()
        password = self.manager.f.decrypt(password)
        password = password.decode()
        MyApp.displaypassword = password
        pyperclip.copy(password)
        ok = PopupContent()
        popup = Popup(title='Password Copied', content=ok,
              auto_dismiss=False, size_hint=(1,1))
        ok.closebutton.bind(on_release=popup.dismiss)
        popup.open()
        self.delete_dropdown()
        self.manager.current = "Options"

self.manager.credentials 是一个字典,用户名作为键,密码作为值。 比如,

self.manager.credentials = {"one":"1","two":"3","third_username":"thirdpassword"}

这里将创建名称为 one、two 和 third_username 的 3 个按钮。 (请注意,在我的代码中,Button 的文本是 i[8:],这是因为我为每个用户名都有一个自定义别名,长度为 7 个字符。)

但每当我点击第一个/第二个按钮(名为“one”/“two”的按钮)时,函数 do_accordingly 总是获取第三个按钮的参数,即“third_username”,它总是返回第三个按钮的密码,无论单击哪个按钮。

关于为什么会发生这种情况的任何想法? 谢谢。

我的 .kv 代码(以防万一):

<CopyCredentialWindow>:
    name: "CopyCredentials"
    GridLayout:
        id: grid
        cols: 1
        AnchorLayout:
            Button:
                text: "Click here to Go Back\nSelect account to copy:"
                font_size: 20
                color: .4, .4, .8, 1
                on_release:
                    root.manager.current = "Options"
                    root.delete_dropdown()

Edit- 请注意,按钮的文本正确显示,但功能无法按预期工作。

编辑 2: 感谢 - Lothric 这是开始工作的代码: 在 for 循环内:

            button_list.append(Button(text=i[8:], size_hint_y=None, height=40, on_release=lambda x, cred=i: self.do_accordingly(cred)))
            self.grid.add_widget(button_list[-1])

【问题讨论】:

  • 如果您使用partial(self.do_accordingly, i) 进行on_release 回调,会发生同样的事情吗?
  • 是的。我已经尝试了所有的东西。使用 partial 没有区别。

标签: python-3.x kivy


【解决方案1】:

这是常见的问题,解决方案是在列表或字典中创建小部件。您使用单独的按钮创建了列表并且您不使用它,试试这个:

        for i in self.manager.credentials:
            button_list.append(Button(text=i[8:], size_hint_y=None, height=40, on_release=lambda x, cred=i: self.do_accordingly(cred)))
            self.grid.add_widget(button_list[-1])

【讨论】:

  • @KrYmZiN 好的,我已经编辑了答案,再试一次
  • @KrYmZiN 不客气,顺便说一句,这不是 Kivy 问题,而是 Python 问题,所以当你在循环中使用 lambda 时,你可以在任何其他框架中使用它:)
  • 是的,我就是这么想的,但由于它是基于 kivy 的,所以我也标记了它。
猜你喜欢
  • 2018-08-17
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-12
  • 2017-10-12
  • 1970-01-01
相关资源
最近更新 更多