如何在 Kivy 应用程序中为不同的 ListView 实例设置不同的属性?
How do I set different properties for different instances of ListView in a Kivy App?
我希望我的 Kivy 应用有多个 ListView 实例。在分配不同的属性,尤其是回调时,我被卡住了。以下代码说明了我的问题:
from kivy.app import App
from kivy.uix.listview import ListItemButton
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
Builder.load_string('''
#: import ListAdapter kivy.adapters.listadapter.ListAdapter
#: import ListItemButton kivy.uix.listview.ListItemButton
<smRoot>:
Screen1:
Screen2:
<ListItemButton>:
on_press: app.callback1(self)
height: dp(25)
size_hint: (1,.1)
<Screen1>:
name:'screen1'
BoxLayout:
orientation: 'vertical'
Label:
text: 'Screen1'
size_hint_y: .1
ListView:
id:lstScreen1
adapter:
ListAdapter(data=[{'text':'item1'},{'text':'item2'},{'text':'item3'}],
args_converter=lambda row_index, rec: {'text': rec['text']},
cls=ListItemButton,
selection_mode='single',
allow_empty_selection=False)
Button:
text: 'Switch Screen'
size_hint_y: .1
on_press: root.manager.current = 'screen2'
<ListItemButton>:
on_press: app.callback2(self)
height: dp(25)
size_hint: (1,.1)
<Screen2>:
name:'screen2'
BoxLayout:
orientation: 'vertical'
Label:
text: 'Screen2'
size_hint_y: .1
ListView:
id:lstScreen2
adapter:
ListAdapter(data=[{'text':'item1'},{'text':'item2'},{'text':'item3'}],
args_converter=lambda row_index, rec: {'text': rec['text']},
cls=ListItemButton,
selection_mode='single',
allow_empty_selection=False)
Button:
text: 'Switch Screen'
size_hint_y: .1
on_press: root.manager.current = 'screen1'
''')
class smRoot(ScreenManager):
pass
class Screen1(Screen):
MyButt = ListItemButton
pass
class Screen2(Screen):
pass
class myApp(App):
def build(self):
smroot = smRoot()
return smroot
def callback1(self, btn_instance):
index = btn_instance.index
print 'From Screen 1: ' + str(index)
def callback2(self, btn_instance):
index = btn_instance.index
print 'From Screen 2: ' + str(index)
myApp().run()
在这里,我希望屏幕 1 和屏幕 2 上的每个 ListView 实例都有单独的回调。但是当我点击任一屏幕时,输出是相同的,如下所示:
From Screen 2: 0
From Screen 1: 0
理想情况下,我希望实现类似 Dynamic Class 的东西。但是当我尝试这样的事情时:
<MyButt@ListItemButton>:
#on_press: app.callback1(self)
height: dp(25)
size_hint: (1,.1)
<Screen1>:
name:'screen1'
MyButt:
on_press: app.callback1(self)
BoxLayout:
orientation: 'vertical'
Label:
text: 'Screen1'
size_hint_y: .1
ListView:
id:lstScreen1
adapter:
ListAdapter(data=[{'text':'item1'},{'text':'item2'},{'text':'item3'}],
args_converter=lambda row_index, rec: {'text': rec['text']},
cls=MyButt,
selection_mode='single',
allow_empty_selection=False)
我收到 NameError: name 'MyButt' is not defined
错误。据我所知,我在上面链接的文档示例中遵循了相同的语法,所以我很困惑。
我没有尝试在 Python 中创建自定义 class,但我宁愿在 .kv 代码中将 UI 元素分开(如果我没记错的话,这不就是kv背后的基本思想吗?)。
任何 help/pointers/suggestions 在这方面的人将不胜感激。
您不能在不导入的情况下在 kv 中使用 python 端(在“:”之后)的小部件 class,但由于 MyButt
未在任何模块中定义,作为动态 class(以纯 kv 定义),您可以使用 Factory
来使用它。
首先,在您的 kv 文件的顶部导入 Factory。
#:import Factory kivy.factory.Factory
然后改变
ListView:
id:lstScreen1
adapter:
ListAdapter(data=[{'text':'item1'},{'text':'item2'},{'text':'item3'}],
args_converter=lambda row_index, rec: {'text': rec['text']},
cls=MyButt,
到
ListView:
id:lstScreen1
adapter:
ListAdapter(data=[{'text':'item1'},{'text':'item2'},{'text':'item3'}],
args_converter=lambda row_index, rec: {'text': rec['text']},
cls=Factory.MyButt,
我希望我的 Kivy 应用有多个 ListView 实例。在分配不同的属性,尤其是回调时,我被卡住了。以下代码说明了我的问题:
from kivy.app import App
from kivy.uix.listview import ListItemButton
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
Builder.load_string('''
#: import ListAdapter kivy.adapters.listadapter.ListAdapter
#: import ListItemButton kivy.uix.listview.ListItemButton
<smRoot>:
Screen1:
Screen2:
<ListItemButton>:
on_press: app.callback1(self)
height: dp(25)
size_hint: (1,.1)
<Screen1>:
name:'screen1'
BoxLayout:
orientation: 'vertical'
Label:
text: 'Screen1'
size_hint_y: .1
ListView:
id:lstScreen1
adapter:
ListAdapter(data=[{'text':'item1'},{'text':'item2'},{'text':'item3'}],
args_converter=lambda row_index, rec: {'text': rec['text']},
cls=ListItemButton,
selection_mode='single',
allow_empty_selection=False)
Button:
text: 'Switch Screen'
size_hint_y: .1
on_press: root.manager.current = 'screen2'
<ListItemButton>:
on_press: app.callback2(self)
height: dp(25)
size_hint: (1,.1)
<Screen2>:
name:'screen2'
BoxLayout:
orientation: 'vertical'
Label:
text: 'Screen2'
size_hint_y: .1
ListView:
id:lstScreen2
adapter:
ListAdapter(data=[{'text':'item1'},{'text':'item2'},{'text':'item3'}],
args_converter=lambda row_index, rec: {'text': rec['text']},
cls=ListItemButton,
selection_mode='single',
allow_empty_selection=False)
Button:
text: 'Switch Screen'
size_hint_y: .1
on_press: root.manager.current = 'screen1'
''')
class smRoot(ScreenManager):
pass
class Screen1(Screen):
MyButt = ListItemButton
pass
class Screen2(Screen):
pass
class myApp(App):
def build(self):
smroot = smRoot()
return smroot
def callback1(self, btn_instance):
index = btn_instance.index
print 'From Screen 1: ' + str(index)
def callback2(self, btn_instance):
index = btn_instance.index
print 'From Screen 2: ' + str(index)
myApp().run()
在这里,我希望屏幕 1 和屏幕 2 上的每个 ListView 实例都有单独的回调。但是当我点击任一屏幕时,输出是相同的,如下所示:
From Screen 2: 0
From Screen 1: 0
理想情况下,我希望实现类似 Dynamic Class 的东西。但是当我尝试这样的事情时:
<MyButt@ListItemButton>:
#on_press: app.callback1(self)
height: dp(25)
size_hint: (1,.1)
<Screen1>:
name:'screen1'
MyButt:
on_press: app.callback1(self)
BoxLayout:
orientation: 'vertical'
Label:
text: 'Screen1'
size_hint_y: .1
ListView:
id:lstScreen1
adapter:
ListAdapter(data=[{'text':'item1'},{'text':'item2'},{'text':'item3'}],
args_converter=lambda row_index, rec: {'text': rec['text']},
cls=MyButt,
selection_mode='single',
allow_empty_selection=False)
我收到 NameError: name 'MyButt' is not defined
错误。据我所知,我在上面链接的文档示例中遵循了相同的语法,所以我很困惑。
我没有尝试在 Python 中创建自定义 class,但我宁愿在 .kv 代码中将 UI 元素分开(如果我没记错的话,这不就是kv背后的基本思想吗?)。
任何 help/pointers/suggestions 在这方面的人将不胜感激。
您不能在不导入的情况下在 kv 中使用 python 端(在“:”之后)的小部件 class,但由于 MyButt
未在任何模块中定义,作为动态 class(以纯 kv 定义),您可以使用 Factory
来使用它。
首先,在您的 kv 文件的顶部导入 Factory。
#:import Factory kivy.factory.Factory
然后改变
ListView:
id:lstScreen1
adapter:
ListAdapter(data=[{'text':'item1'},{'text':'item2'},{'text':'item3'}],
args_converter=lambda row_index, rec: {'text': rec['text']},
cls=MyButt,
到
ListView:
id:lstScreen1
adapter:
ListAdapter(data=[{'text':'item1'},{'text':'item2'},{'text':'item3'}],
args_converter=lambda row_index, rec: {'text': rec['text']},
cls=Factory.MyButt,