【问题标题】:Using the ScreenManager with RecycleView in Kivy在 Kivy 中使用 ScreenManager 和 RecycleView
【发布时间】:2017-10-10 09:37:34
【问题描述】:

我有一个响应触摸输入的 RecycleView 小部件。我需要 RecycleView 上的每一行将用户带到特定的屏幕。现在我只有两个屏幕设置。

这里是 Python 代码:

class Navigator(NavigationDrawer):
    image_source = StringProperty('images/1canaa.jpg')
    title = StringProperty('Navigation')

# This is the screen that is initiated when the app runs 
class MainScreen(Screen):
    pass

# This is the screen that is suppose to initiate when the first row is 
# touched
class MapScreen(Screen):
    pass


class Manager(ScreenManager):
    main_screen_obj = ObjectProperty(None)
    map_screen_obj = ObjectProperty(None)


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                             RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''


class SelectableLabel(RecycleDataViewBehavior, Label):
    ''' Add selection support to the Label '''
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        return super(SelectableLabel, self).refresh_view_attrs(
        rv, index, data)

    def on_touch_down(self, touch):
        ''' Add selection on touch down '''
        if super(SelectableLabel, self).on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos) and self.selectable:
            return self.parent.select_with_touch(self.index, touch)

    def apply_selection(self, rv, index, is_selected):
        ''' Respond to the selection of items in the view. '''
        self.selected = is_selected
        if is_selected:
            print("selection changed to {0}".format(rv.data[index]))
            if rv.data[index] == {'text': 'FIRST ROW'}:
                Manager.current = 'mapScreen'
                print('The evaluation was executed')


        else:
            print("selection removed for {0}".format(rv.data[index]))


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)

        Unidades = ['FIRST ROW', 'SECOND ROW', 'THIRD ROW', 'FORTH ROW']

        self.data = [{'text': x} for x in Unidades]


class Main(App):
    theme_cls = ThemeManager()
    nav_drawer = ObjectProperty()

    def build(self):
        self.nav_drawer = Navigator()
        return Manager()


if __name__ == '__main__':
    Main().run()

如果您查看 SelectableLabel 类中的 apply_selection 方法,您会发现我试图通过检查来解决这个问题:

if the rv.data[index] == {'text': 'FIRST ROW'}:
    Manager.current = 'mapScreen'
    print('The evaluation was executed')

这不起作用。请注意,我打印了一条消息以检查评估是否发生,并且确实发生了。当我运行应用程序时,我收到消息:“评估已执行”。但用户并未被带到 MapScreen。

这里是kv代码:

#:import MapSource mapview.MapSource
#:import Toolbar kivymd.toolbar.Toolbar
#:import hex kivy.utils.get_color_from_hex


<SelectableLabel>:
# Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: hex('#867979') if self.selected else hex('#808080')
        Rectangle:
            pos: self.pos
            size: self.size


<RV>:
    viewclass: 'SelectableLabel'

    SelectableRecycleBoxLayout:

        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
        multiselect: False
        touch_multiselect: True


<MainScreen>:
    BoxLayout:
        orientation: 'vertical'

        Label:
            size_hint: None, None
            height: 45
            width: 100
            pos_hint: {'center_y': 0.5, 'center_x': 0.5}
            text: '[size=40]Unidades de Assistência[/size]'
            color: hex('#676767')
            markup: True
            font_name: 'alex-brush.regular.ttf'

        RV: 

<MapScreen>:
    BoxLayout:
        Label:
            text: 'MapScreen'



<Manager>:
    id: screen_manager
    main_screen_obj: main_screen
    map_screen_obj: map_screen

    MainScreen:
        id: main_screen
        name: 'mainScreen'
        manager: screen_manager


    MapScreen:
        id: map_screen
        name: 'mapScreen'
        manager: screen_manager

所以,我在这里想要完成的事情非常简单,或者至少应该如此。这一切都归结为:如果触摸第一行,则将用户带到 MapScreen... 如果触摸第二行,则将用户带到其他屏幕...等等。

我希望这不是很混乱。感谢您的帮助。

【问题讨论】:

    标签: python kivy


    【解决方案1】:

    有两种方法可以做到这一点,我想不到。 一种是使用kivy garden中的router模块:

    https://github.com/kivy-garden/garden.router

    另一种方法是将屏幕管理器的引用传递给回收视图中的小部件,这样您就可以说self.manager.current = self.text,但这意味着您必须先将所有屏幕添加到管理器。

    我会为此使用工厂:

    from kivy.factory import Factory
    
    class MyScreenManager(ScreenManager):
        def create_and_switch_screen(self, name):
            # This creates an instance of the class name you passed
            new_screen = getattr(Factory, name)()
            self.switch_to(my_screen)
    

    通过这种方式,您可以以编程方式创建每个屏幕并将它们定义为单独的类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 2015-05-01
      • 1970-01-01
      相关资源
      最近更新 更多