#python #for-loop #button #lambda #kivy
#python #for-цикл #кнопка #лямбда #kivy
Вопрос:
Я пишу средство обработки данных для своей школы, которое отображает информацию в реальном времени в форме приложения. Я пытаюсь создавать кнопки в цикле for, использовать lambda для привязки каждой кнопки к функции и значению для использования при вызове (в данном случае для печати их значения для тестирования), добавить каждую кнопку (а также пару других виджетов) в макет и добавить этот макет вэкран.
Однако по какой-то причине, хотя я должен сохранять значение «a» в функции lambda: btn.bind(on_press=lambda btn, a=a: self.getlink(a))
, lambda, похоже, не может «запомнить» больше, чем около 3 итераций назад (этот цикл длится около 20 циклов).). Последние три кнопки (самые последние сгенерированные) на экране возвращают правильные значения, но чем дальше вы поднимаетесь по экрану (макет kivy RecycleView), тем менее точным будет значение. Когда я нажимаю первые несколько кнопок на экране, буквально ничего не происходит. Когда я спускаюсь по экрану, нажимая кнопки, я иногда получаю случайное число, иногда значительно отличающееся число (например, выдает 2, когда оно должно быть 11).
При запуске не возникает ошибок, и все остальное работает просто отлично. Кажется, я просто не могу заставить эти кнопки привязываться к правильному значению. Я даже пытался использовать счетчик в цикле, который добавляет единицу для каждой итерации, и использовать его вместо a , но он сделал то же самое.
Любая помощь будет высоко оценена, спасибо!
Вот соответствующий код:
from kivy.app import App
from kivy.base import runTouchApp
from kivy.core.window import Window
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.recycleview import RecycleView
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget
from kivy.uix.image import AsyncImage
from kivy.uix.button import Button
from kivy.lang import Builder
class ScreenThree(RecycleView, Screen):
def __init__(self, **kwargs):
super(ScreenThree, self).__init__(**kwargs)
self.data = [{'padding': '7sp',
'size_hint': (6, None),
'allow_stretch': True,
'height': ((Window.height / 4) * (22))}]
def screenlength(self):
return Window.height * (20 / 4)
def screenSize(self, modifier=1):
window_s = Window.size
if window_s[1] >= window_s[0]:
return str((window_s[0] * 0.007) * modifier) 'sp'
else:
return str((window_s[1] * 0.007) * modifier) 'sp'
class ScreenFour(TabbedPanel, Screen):
def __init__(self, **kwargs):
super(ScreenFour, self).__init__(**kwargs)
self.default_tab_text = 'Events'
self.tab_width = Window.width / 2.7
self.tab_height = Window.height / 25
self.default_tab_content = ScreenThree()
self.background_color = (0, 0, 0, 1)
def screenSize(self, modifier=1):
window_s = Window.size
if window_s[1] >= window_s[0]:
return str((window_s[0] * 0.007) * modifier) 'sp'
else:
return str((window_s[1] * 0.007) * modifier) 'sp'
class AddWidget(GridLayout, Widget):
def __init__(self, **kwargs):
super(AddWidget, self).__init__(**kwargs)
for a in range(20):
asyncimage1 = AsyncImage(source='https://images-na.ssl-images-amazon.com/images/I/51zLZbEVSTL._AC_SX679_.jpg',
allow_stretch=True,
size_hint_y=None,
size_hint_x=5,
height=Window.height / 4)
self.add_widget(asyncimage1)
label = Label(text='title goes here',
bold=True,
text_size=self.size,
size_hint=(1, 1),
valign='top',
padding=(0, '11sp'),
font_size=self.screenSize(1.2))
label.bind(size=label.setter('text_size'))
layout2 = GridLayout(rows=3)
label2 = Label(text='date goes here',
text_size=self.size,
size_hint=(1, 1),
valign='top',
padding=(0, '1sp'),
font_size=self.screenSize(0.9))
label2.bind(size=label2.setter('text_size'))
layout2.add_widget(label)
layout2.add_widget(label2)
btn = Button(text='Visit Website',
font_size=self.screenSize(1.4),
size_hint=(1, 1),
id = str(a),
padding=("10sp", "10sp"))
btn.bind(on_press=lambda btn, a=a: self.getlink(a))
layout2.add_widget(btn)
self.add_widget(layout2)
def getlink(self, position):
print(position)
def screenSize(self, modifier=1):
window_s = Window.size
if window_s[1] >= window_s[0]:
return str((window_s[0] * 0.007) * modifier) 'sp'
else:
return str((window_s[1] * 0.007) * modifier) 'sp'
class ScreenManagement(ScreenManager):
pass
pres1 = runTouchApp(Builder.load_file('screenskv2.kv'))
class MyApp(App):
def build(self):
return ScreenManagement
MyApp().run()
И соответствующий код в файле kv:
#:import Window kivy.core.window.Window
ScreenManagement:
ScreenThree:
<AddWidget>:
orientation: 'horizontal'
cols:2
spacing: '10sp'
col_default_width: (Window.width/2)-50
<ScreenThree>:
name: 'screen_three'
rv_layout: 'layout'
viewclass: 'AddWidget'
RecycleBoxLayout:
id: 'layout'
pos_hint_x: 0
size_hint: (None, None)
height: self.minimum_height
orientation: 'vertical'
Комментарии:
1. Можете ли вы опубликовать минимальный выполнимый пример?
2. Полный проект содержит 4 файла py, 1 файл kv и 5 файлов JSON, я не уверен, что смогу загрузить все, хотя, вероятно, я мог бы загрузить достаточно, чтобы заставить работать только один раздел, если это сработает
3. Опубликуйте минимум, необходимый для выполнения только вашей проблемы.
4. Я только что отредактировал исходное сообщение, чтобы включить все необходимые компоненты для решения проблемы