Обратные вызовы Kivy для экземпляров кнопок/виджетов?

#python #kivy

#питон #киви

Вопрос:

Я пытаюсь создать несколько экземпляров кнопок, которые будут запускать функцию «on_toggle_button_state», как показано в приведенном ниже фрагменте кода. Я уверен, что это что-то простое, что я упустил из виду, но это ставило меня в тупик дольше, чем я хотел бы признать.

Ошибка атрибута: объект «Кнопки переключения» не имеет атрибута «состояние»

 class ToggleButtons(StackLayout):    def __init__(self, *args, **kwargs):  super().__init__(**kwargs)    conn = sqlite3.connect('players_db.db')   c = conn.cursor()  c.execute("DELETE FROM players WHERE (name IS NULL OR name = '')") ##Remove empty entries  c.execute("SELECT * FROM players")  records = c.fetchall()  records = list(filter(None, records))    for i in range(0, len(records)):  name = str(records[i])[2:-3]   b = ToggleButton(size_hint = (0.2, 0.2), text = name, on_state = self.on_toggle_button_state())   self.add_widget(b)    def on_toggle_button_state(self, widget):  print("toggle state: "   widget.state)  if widget.state == "normal":  widget.text = "OFF"  self.count_enabled = False  else:  widget.text = "ON"  self.count_enabled = True  

Что-то, что работает для кнопок без экземпляров:

 StackLayout:  ToggleButton:  text: "Charlie"  on_state: root.on_toggle_button_state(self)  size_hint: 0.2, 0.2  

Ответ №1:

В вашем файле kv используется lt;ToggleButtongt;: для назначения on_state метода с. self.parent.on_toggle_button_state(self)

self является динамически создаваемой кнопкой, а родительский ToggleButtons элемент-это StackLayout, в котором вы определили on_toggle_button_state метод.

Я немного изменил ваш код, чтобы я мог запускать его без SQL-кода. Так что игнорируйте эти изменения.

Разница между ToggleButton и lt;ToggleButtongt; заключается в том, что первый помещает экземпляр в StackLayout — не то, что вам здесь нужно. И обозначение в скобках определяет методы и стили для каждого из ваших экземпляров.

Пожалуйста, найдите фрагмент ниже с упомянутым изменением:

 from kivy.app import App from kivy.uix.stacklayout import StackLayout from kivy.uix.button import Button from kivy.lang import Builder  kv = ''' StackLayout:  lt;ToggleButtongt;:  text: "Charlie"  on_state:   self.parent.on_toggle_button_state(self)  size_hint: 0.2, 0.2 '''  Builder.load_string(kv)  class ToggleButton(Button):  pass  class ToggleButtons(StackLayout):   def __init__(self, *args, **kwargs):  super().__init__(**kwargs)    # conn = sqlite3.connect('players_db.db')   # c = conn.cursor()  # c.execute("DELETE FROM players WHERE (name IS NULL OR name = '')") ##Remove empty entries  # c.execute("SELECT * FROM players")  # records = c.fetchall()  # records = list(filter(None, records))  records = ["test1", "test2"]  for i in range(0, len(records)):  # name = str(records[i])[2:-3]   name = records[i] # just for testing  print(name)   b = ToggleButton(size_hint = (0.2, 0.2), text = name, on_state = self.on_toggle_button_state)   self.add_widget(b)    def on_toggle_button_state(self, widget):  print("toggle state: "   widget.state)  if widget.state == "normal":  widget.text = "OFF"  widget.count_enabled = False  else:  widget.text = "ON"  widget.count_enabled = True   class MyApp(App):  def build(self):  return ToggleButtons()  if __name__ == '__main__':  MyApp().run()