如何从RecycleView SelectableButton对象切换到动态创建的屏幕?

时间:2018-09-30 03:27:37

标签: python python-3.x kivy

我有一个应用程序,可以在其中从相同的textinput小部件动态创建屏幕小部件和recycleview按钮viewclass对象。动态创建的ProjectScreen小部件的名称与SelectableButton的字典中包含的值相同。

在单击具有相同名称的SelectableButton recycleview viewclass对象后,我很难切换到ProjectScreen小部件。下面的代码示例:

from kivy.app import App

from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty, BooleanProperty

'''Library imports for recycleview'''
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview import RecycleViewBehavior
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.behaviors import FocusBehavior


class HomeScreen(Screen):
    pass

class ProjectListScreen(Screen):
    rv = ObjectProperty(None)


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = []


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


class SelectableButton(RecycleDataViewBehavior, Button):
    """ Add selection support to the Label """
    index = None


class ProjectScreen(Screen):
    pass


class NewProjectScreen(Screen):
    project_name_text_input = ObjectProperty(None)
    project_address_text_input = ObjectProperty(None)
    project_scope_text_input = ObjectProperty(None)

    def add_project_list_item(self,project_name_text_input):
        name = project_name_text_input.text
        project_list_screen = self.manager.get_screen('project_list_screen')
        project_list_screen.rv.data.insert(0, {'value': name})

    def add_project_screen(self,project_name_text_input, project_address_text_input, project_scope_text_input):
        name = project_name_text_input.text
        self.manager.add_widget(ProjectScreen(name=name))
        project_name_text_input.text = ''


screen_manager = ScreenManager()
class ReportingApp(App):
    def build(self):
        screen_manager.add_widget(HomeScreen(name="home_screen"))
        screen_manager.add_widget(ProjectListScreen(name="project_list_screen"))
        screen_manager.add_widget(NewProjectScreen(name="new_project_screen"))
        return screen_manager

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

还有我的kv文件:

#:kivy 1.10.1

#:import RecycleView kivy.uix.recycleview.RecycleView
#:import RecycleViewBehavior kivy.uix.recycleview.RecycleView
#:import RecycleDataViewBehavior kivy.uix.recycleview.views.RecycleDataViewBehavior
#:import RecycleBoxLayout kivy.uix.recycleboxlayout.RecycleBoxLayout
#:import LayoutSelectionBehavior kivy.uix.recycleview.layout.LayoutSelectionBehavior
#:import FocusBehavior kivy.uix.behaviors.FocusBehavior


<HomeScreen>:
    BoxLayout:
        orientation: "vertical"
        padding: 100
        spacing: 25
        Label:
            size_hint_y: None
            height: 150
            text: "Site Visit Reporting App v1.1"

        Button:
            text: "New Project"
            on_press:
                root.manager.transition.direction = 'left'
                root.manager.current = 'new_project_screen'

        Button:
            text: "Project List"
            on_press:
                root.manager.transition.direction = 'left'
                root.manager.current = 'project_list_screen'

<NewProjectScreen>:

    project_name_text_input: project_name
    project_address_text_input: project_address
    project_scope_text_input: project_scope

    BoxLayout:
        orientation: "vertical"

        Label:
            text: 'Project Name:'
        TextInput:
            id: project_name

        Label:
            text: 'Project Address:'
        TextInput:
            id: project_address

        Label:
            text: 'Project Scope:'
        TextInput:
            id: project_scope

        BoxLayout:
            padding: 15
            spacing: 25
            Button:
                text: 'OK'
                on_press:
                    root.add_project_list_item(project_name)
                    root.add_project_screen(project_name, project_address,                     
                        project_scope)
            Button:
                text: 'Back'
                on_press:
                    root.manager.transition.direction = 'right'
                    root.manager.current = 'home_screen'


<SelectableButton>:
    canvas.before:
        Color:
            rgba: 0.5, 0.5, 0.5, 1
        Rectangle:
            size: self.size
            pos: self.pos
    value: ''
    text: root.value
    on_press:
        root.manager.current = root.value


<ProjectListScreen>:

    rv: rv

    BoxLayout:
        orientation: 'vertical'
        Label:
            text: 'Current list of projects'
        Button:
            text: 'Back'
            on_press:
                root.manager.transition.direction = 'right'
                root.manager.current = 'home_screen'

        RV:
            id: rv
            scroll_type: ['bars', 'content']
            scroll_wheel_distance: dp(114)
            bar_width: dp(10)
            viewclass: 'SelectableButton'
            SelectableRecycleBoxLayout:
                default_size: None, dp(56)
                default_size_hint: 1, None
                size_hint_y: None
                height: self.minimum_height
                orientation: 'vertical'
                spacing: dp(2)
                multiselect: False
                touch_multiselect: False

<ProjectScreen>:
    BoxLayout:
        Label:
            text: 'hook up project info here'
        Button:
            text: 'Back'

当我在recycleview中按下SelectableButton对象时,出现以下错误:

[INFO   ] [Logger      ] Record log in C:\Users\amars\.kivy\logs\kivy_18-09-29_32.txt
[INFO   ] [Kivy        ] v1.10.1
[INFO   ] [Python      ] v3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:06:47) [MSC v.1914 32 bit (Intel)]
[INFO   ] [Factory     ] 194 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)
[INFO   ] [Text        ] Provider: sdl2
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] GLEW initialization succeeded
[INFO   ] [GL          ] Backend used <glew>
[INFO   ] [GL          ] OpenGL version <b'4.3.0 - Build 20.19.15.4549'>
[INFO   ] [GL          ] OpenGL vendor <b'Intel'>
[INFO   ] [GL          ] OpenGL renderer <b'Intel(R) HD Graphics 4400'>
[INFO   ] [GL          ] OpenGL parsed version: 4, 3
[INFO   ] [GL          ] Shading version <b'4.30 - Build 20.19.15.4549'>
[INFO   ] [GL          ] Texture max size <16384>
[INFO   ] [GL          ] Texture max units <32>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [Base        ] Start application main loop
[INFO   ] [GL          ] NPOT texture support is available
[INFO   ] [Base        ] Leaving application in progress...
 Traceback (most recent call last):
   File "C:/Users/amars/PycharmProjects/ReportingApp/main.py", line 69, in <module>
     ReportingApp().run()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\app.py", line 826, in run
     runTouchApp()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\base.py", line 502, in runTouchApp
     EventLoop.window.mainloop()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\core\window\window_sdl2.py", line 727, in mainloop
     self._mainloop()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\core\window\window_sdl2.py", line 460, in _mainloop
     EventLoop.idle()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\base.py", line 340, in idle
     self.dispatch_input()
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\base.py", line 325, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\base.py", line 231, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\core\window\__init__.py", line 1364, in on_motion
     self.dispatch('on_touch_up', me)
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\core\window\__init__.py", line 1400, in on_touch_up
     if w.dispatch('on_touch_up', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\screenmanager.py", line 1201, in on_touch_up
     return super(ScreenManager, self).on_touch_up(touch)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 482, in on_touch_up
     if child.dispatch('on_touch_up', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\relativelayout.py", line 304, in on_touch_up
     ret = super(RelativeLayout, self).on_touch_up(touch)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 482, in on_touch_up
     if child.dispatch('on_touch_up', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 482, in on_touch_up
     if child.dispatch('on_touch_up', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\scrollview.py", line 848, in on_touch_up
     if self.dispatch('on_scroll_stop', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\scrollview.py", line 887, in on_scroll_stop
     self.simulate_touch_down(touch)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\scrollview.py", line 607, in simulate_touch_down
     ret = super(ScrollView, self).on_touch_down(touch)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 460, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\behaviors\focus.py", line 443, in on_touch_down
     return super(FocusBehavior, self).on_touch_down(touch)
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 460, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\behaviors\button.py", line 151, in on_touch_down
     self.dispatch('on_press')
   File "kivy\_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1098, in kivy._event.EventObservers._dispatch
   File "C:\Users\amars\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\lang\builder.py", line 64, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "C:\Users\amars\PycharmProjects\ReportingApp\reportingapp.kv", line 82, in <module>
     root.manager.current = root.value
   File "kivy\weakproxy.pyx", line 30, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'SelectableButton' object has no attribute 'manager'

以某种方式,我需要获取SelectableButton小部件以“知道”屏幕管理器,以便可以切换到所需的屏幕。

据我了解,对root.manager的调用将直接转到我的root小部件,后者是屏幕管理器小部件。 SelectableButton是否不是RV的子小部件,RV是ProjectListScreen的子小部件?因此,ScreenManager根窗口小部件下还是一个子窗口小部件?

感谢您的帮助。谢谢。

1 个答案:

答案 0 :(得分:0)

一种可能的解决方案是将data中的信息传递给RecycleView,因为它必须在SelectableButton中创建一个属性:

*。py

def add_project_list_item(self,project_name_text_input):
    name = project_name_text_input.text
    project_list_screen = self.manager.get_screen('project_list_screen')
    project_list_screen.rv.data.insert(0, {'value': name, 'manager': self.manager}) # <---

*。kv

<SelectableButton>:
    manager: None # <---
    canvas.before:
        Color:
            rgba: 0.5, 0.5, 0.5, 1
        Rectangle:
            size: self.size
            pos: self.pos
    value: ''
    text: root.value
    on_press:
        root.manager.current = root.value # <---