我注意到我的应用程序中的小部件创建速度很慢,因此我创建了这个简单的测试应用程序来检查它。它包含两个屏幕,每个屏幕都包含简单的小部件列表。
应用:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty, StringProperty
from kivy.clock import Clock
from time import time
class ListScreen(Screen):
items_box = ObjectProperty(None)
def on_enter(self):
start = time()
for i in range(0,50):
self.items_box.add_widget(ListItem('Item '+str(i)))
self.items_box.bind(minimum_height=self.items_box.setter('height'))
print time()-start
def on_leave(self):
self.items_box.clear_widgets()
class ListItem(BoxLayout):
title = StringProperty('')
def __init__(self, title, **kwargs):
super(ListItem, self).__init__(**kwargs)
self.title = title
class ListApp(App):
sm = ScreenManager()
screens = {}
def build(self):
self.__create_screens()
ListApp.sm.add_widget(ListApp.screens['list1'])
Clock.schedule_interval(self._switch, 1)
return ListApp.sm
def _switch(self, *args):
ListApp.sm.switch_to(ListApp.screens['list1' if ListApp.sm.current != 'list1' else 'list2'])
def __create_screens(self):
ListApp.screens['list1'] = ListScreen(name='list1')
ListApp.screens['list2'] = ListScreen(name='list2')
if __name__ == '__main__':
ListApp().run()
list.kv文件:
<ListScreen>:
items_box: items_box
BoxLayout:
orientation: "vertical"
AnchorLayout:
size_hint_y: 0.1
padding: self.width*0.1, self.height*0.05
Label:
font_size: root.height*0.05
text: "Some list"
ScrollView:
size_hint_y: 0.9
size: self.size
BoxLayout:
id: items_box
orientation: "vertical"
padding: self.width*0.1, 0
size_hint_y: None
<ListItem>:
orientation: "horizontal"
size_hint_y: None
height: app.sm.height*0.1
Label:
font_size: app.sm.height*0.025
text: root.title
size_hint_x: 0.9
text_size: self.size
valign: "middle"
CheckBox
size_hint_x: 0.1
登录我的设备(Moto G):
11-28 11:44:09.525 1848 2044 I python : 0.5793800354
11-28 11:44:10.853 1848 2044 I python : 0.453143119812
11-28 11:44:12.544 1848 2044 I python : 0.633069992065
11-28 11:44:13.697 1848 2044 I python : 0.369570970535
11-28 11:44:14.988 1848 2044 I python : 0.594089031219
11-28 11:44:16.017 1848 2044 I python : 0.339677095413
11-28 11:44:17.315 1848 2044 I python : 0.58710193634
11-28 11:44:18.403 1848 2044 I python : 0.359042882919
11-28 11:44:19.741 1848 2044 I python : 0.613200187683
11-28 11:44:20.820 1848 2044 I python : 0.359098911285
11-28 11:44:22.139 1848 2044 I python : 0.60958814621
11-28 11:44:23.199 1848 2044 I python : 0.354372024536
11-28 11:44:24.538 1848 2044 I python : 0.643312931061
11-28 11:44:25.606 1848 2044 I python : 0.360656023026
11-28 11:44:26.995 1848 2044 I python : 0.682018995285
11-28 11:44:28.140 1848 2044 I python : 0.393831014633
11-28 11:44:29.470 1848 2044 I python : 0.591700077057
11-28 11:44:30.525 1848 2044 I python : 0.346837043762
11-28 11:44:31.818 1848 2044 I python : 0.607005834579
11-28 11:44:32.877 1848 2044 I python : 0.36404299736
11-28 11:44:34.149 1848 2044 I python : 0.586351156235
11-28 11:44:35.195 1848 2044 I python : 0.349910974503
11-28 11:44:36.484 1848 2044 I python : 0.588956832886
11-28 11:44:37.547 1848 2044 I python : 0.367785930634
11-28 11:44:38.886 1848 2044 I python : 0.639610052109
11-28 11:44:40.007 1848 2044 I python : 0.394254922867
11-28 11:44:41.464 1848 2044 I python : 0.732916116714
来吧,真的吗?带标签和复选框的50行简单列表平均需要创建0.5秒?或者我做错了什么?
答案 0 :(得分:1)
感谢Alexander Taylor(Kivy的开发人员之一)找到了解决方案。这是他的回答:
小部件创建相对较慢,尤其取决于什么 小部件包含。
如果在你的例子中制作大名单,你通常会变得更好 使用RecycleView。这样可以优化重用较少数量的东西 滚动期间的小部件。
所以我试过了。
应用:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.clock import Clock
from time import time
class ListScreen(Screen):
recycle_view = ObjectProperty(None)
items_box = ObjectProperty(None)
def on_enter(self):
start = time()
for i in range(0,50):
self.recycle_view.data.append({'title': 'item'+str(i)})
print time()-start
def on_leave(self):
self.recycle_view.data = []
class ListApp(App):
sm = ScreenManager()
screens = {}
def build(self):
self.__create_screens()
ListApp.sm.add_widget(ListApp.screens['list1'])
Clock.schedule_interval(self._switch, 1)
return ListApp.sm
def _switch(self, *args):
ListApp.sm.switch_to(ListApp.screens['list1' if ListApp.sm.current != 'list1' else 'list2'])
def __create_screens(self):
ListApp.screens['list1'] = ListScreen(name='list1')
ListApp.screens['list2'] = ListScreen(name='list2')
if __name__ == '__main__':
ListApp().run()
list.kv文件:
<ListScreen>:
recycle_view: recycle_view
items_box: items_box
BoxLayout:
orientation: "vertical"
AnchorLayout:
size_hint_y: 0.1
padding: self.width*0.1, self.height*0.05
Label:
font_size: root.height*0.05
text: "Some list"
RecycleView:
id: recycle_view
size_hint: 1, 0.9
viewclass: "ListItem"
RecycleBoxLayout:
id: items_box
orientation: "vertical"
padding: self.width*0.1, 0
default_size_hint: 1, None
size_hint: 1, None
height: self.minimum_height
<ListItem@BoxLayout>:
orientation: "horizontal"
size_hint: 1, None
height: app.sm.height*0.1
title: ''
Label:
font_size: app.sm.height*0.025
text: root.title
size_hint_x: 0.9
text_size: self.size
valign: "middle"
CheckBox
size_hint_x: 0.1
登录同一设备(Moto G):
11-29 13:11:58.196 13121 13203 I python : 0.00388479232788
11-29 13:11:59.192 13121 13203 I python : 0.00648307800293
11-29 13:12:00.189 13121 13203 I python : 0.00288391113281
11-29 13:12:01.189 13121 13203 I python : 0.00324606895447
11-29 13:12:02.194 13121 13203 I python : 0.00873804092407
11-29 13:12:03.188 13121 13203 I python : 0.00265002250671
11-29 13:12:04.209 13121 13203 I python : 0.00614500045776
快了100多倍!太棒了。