Почему мои кнопки киви действуют нажатыми в момент их создания на питоне?Динамически создаваемые кнопки киви запускаются on_press и on_release немедленно
Итак, позвольте мне сказать, я знаю, что там, кажется, есть ответ на этот вопрос здесь:
on_press in Kivy keeps running at start up instead
... впрочем, нет рабочего примера. Я попытался скопировать пример, чтобы понять ответ, но не хватает опыта, чтобы заполнить то, что отсутствует в этом примере.
Таким образом, это, вероятно, будет легким ответом для тех, кто смотрит на другой ответ, может применить его здесь и объяснить более простым английским языком для noob.
Вот небольшой рабочий пример проблемы:
import kivy
kivy.require('1.7.2') # replace with your current kivy version !
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
i = ['some', 'words']
class HomeScreen(Screen):
grid_l = ObjectProperty(None)
top_lbl = ObjectProperty(None)
def search_btn_pressed(self):
grid = self.grid_l
grid.bind(minimum_height=grid.setter('height'),
minimum_width=grid.setter('width'))
for result in i:
btn1 = Button(size_hint=(1, None))
btn1.text = '%r' % result
btn1.bind(on_release=self.btn1_pressed(result))
btn2 = Button(size_hint=(1, None))
btn2.text = 'Remove result buttons'
btn2.bind(on_release=self.btn2_pressed)
grid.add_widget(btn1)
grid.add_widget(btn2)
def btn1_pressed(self, result, *args):
new_text = result
self.top_lbl.text = new_text
def btn2_pressed(self, *args):
self.grid_l.clear_widgets()
#pass
class buttons_pressedApp(App):
def build(self):
return HomeScreen()
if __name__ == '__main__':
buttons_pressedApp().run()
И файл Kv:
#:kivy 1.7.2
<HomeScreen>:
scroll_view: scrollviewID
top_lbl: lblID
grid_l: gridlayoutID
AnchorLayout:
size_hint: 1, .1
pos_hint: {'x': 0, 'y': .9}
anchor_x: 'center'
anchor_y: 'center'
Label:
id: lblID
text: 'Button Tester'
Button:
size_hint: 1, .1
pos_hint: {'x': 0, 'y': .8}
text: 'Add theoretical search results'
on_release: root.search_btn_pressed()
ScrollView:
id: scrollviewID
orientation: 'vertical'
pos_hint: {'x': 0, 'y': 0}
size_hint: 1, .8
bar_width: '8dp'
GridLayout:
id: gridlayoutID
cols: 1
size_hint: 1, None
row_default_height: 40
row_force_default: False
Как вы можете видеть, когда вы запускаете его, первая кнопка создана в kivy работает супер , Однако вы также заметите, что верхний ярлык сразу изменился, что указывает на то, что первая динамически созданная кнопка уже выполнила функцию on_release.
Вы не можете сказать, что вторая динамически созданная кнопка «Удалить результирующие кнопки» уже выполнена, потому что она удалила все кнопки, когда их еще не было. Тем не менее, очевидно, что кнопка «Удалить кнопки результатов» выполняется сразу, когда вы снова нажимаете кнопку «Добавить теоретические результаты поиска». Он должен добавить еще две кнопки, но кажется, что ничего не происходит. Это происходит потому, что кнопка «Удалить кнопки результатов» удаляет предыдущие две кнопки, а затем они сразу же заменяются.
Тогда, конечно, ни одна из кнопок, похоже, ничего не делает.
Должно быть легко для кого-то исправить пример с учетом аналогичного вопроса!
Заранее спасибо.
EDIT:
Я изменил btn2, чтобы отразить ответ ненастную в. Работает отлично. Однако, как он отметил, когда я делаю то же самое с btn1, в этот метод передаются некоторые аргументы по умолчанию, и он дает ошибку. Итак, я оставил btn1, как и раньше, с круглой скобкой и «результатом» внутри них в качестве аргумента. Конечно, это запускается немедленно и не возвращает ничего связанного (как объяснено в деталях). Я хочу иметь возможность передать «результат», как уже определено в примере, но, естественно, не запускать его немедленно. Мои извинения .. Я должен был написать это так в первый раз.
EDIT 2, ответ:
Чтобы отразить inclements последний комментарий, я просто хотел, чтобы выложили весь рабочий пример снова ответ включен.
import kivy
kivy.require('1.7.2') # replace with your current kivy version !
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from functools import partial
i = ['some', 'words']
class HomeScreen(Screen):
grid_l = ObjectProperty(None)
top_lbl = ObjectProperty(None)
def search_btn_pressed(self):
grid = self.grid_l
grid.bind(minimum_height=grid.setter('height'),
minimum_width=grid.setter('width'))
for result in i:
btn1 = Button(size_hint=(1, None))
btn1.text = '%r' % result
btn1.bind(on_release=partial(self.btn1_pressed, result))
btn2 = Button(size_hint=(1, None))
btn2.text = 'Remove result buttons'
btn2.bind(on_release=self.btn2_pressed)
grid.add_widget(btn1)
grid.add_widget(btn2)
def btn1_pressed(self, result, *args):
new_text = result
self.top_lbl.text = new_text
def btn2_pressed(self, *args):
self.grid_l.clear_widgets()
#pass
class buttons_pressedApp(App):
def build(self):
return HomeScreen()
if __name__ == '__main__':
buttons_pressedApp().run()
Это работает!
Ваш ответ был идеален для моего примера (и ясно), и я хочу дать вам ответ. Тем не менее, я только что отредактировал свой вопрос, чтобы отразить, что я хочу иметь возможность передавать аргументы. Теперь btn1 должен передать каждый «результат» в списке до btn1_pressed. – bosky
Затем вам нужно создать функцию, включающую эти аргументы. Обманом является использование 'partial' из модуля' functools', и в этом случае вы можете выполнить 'bind (on_release = partial (self.btn1_pressed, result))'. 'partial' - это функция, которая принимает функцию и некоторые аргументы, а * возвращает * новую функцию, которая сначала будет передана этим аргументам. – inclement
Это билет! Благодаря! – bosky