如何访问Kivy中不属于root的不同widget类?

时间:2015-10-21 13:38:40

标签: python kivy

我正在尝试将屏幕添加到屏幕管理器,但该屏幕是独立的。这意味着它不是根元素的一部分,只是一个独立的类。我想在按下图标时将此屏幕添加到屏幕管理器,但我无法弄清楚如何在我的kv文件中引用屏幕。

我猜你一般如何引用kv lang中不属于根小部件的小部件(属于一个单独的类)?

usb_screen_manager.kv

#:import label kivy.uix.label
#:import sla kivy.adapters.simplelistadapter
#:import hvt hub_validation_test


<UsbScreenManager>:
    id: manager
    H2HScreen:
    HubValidationScreen:


<H2HScreen>:
    id: h2h
    name: 'h2h'
    BoxLayout:
        id:bl
        orientation: 'vertical'
        TestIcon:
            id: h2hicon
            source: 'h2h.png'


<HubValidationScreen>:
    id: hvs
    name: 'hvs'
    BoxLayout:
        id:bl
        orientation: 'vertical'

        TestIcon:
            id: hubvicon
            source: 'usb_button.png'
            on_touch_down: app.root.manager.switch_to(hvts) <--add screen when this icon is pressed
        Label:
            text: 'Hub Validation test' 
            size_hint: (1,.25)


<HubValidationTestScreen>:
    id: hvts
    name: 'hvts'
    BoxLayout:
        ListView:
            adapter:
                sla.SimpleListAdapter(
                data= hvt.requirements,
                cls= label.Label)

sam1.kv(包含根元素的kv文件)

<MainPanel>:
    id: mp
    manager: manager

    size_hint: 1,1
    tab_width: 65
    do_default_tab: False
    tab_pos: 'top_right'


    TabbedPanelItem:
        id: usb_tab
        text: 'Usb'
        BoxLayout:
            orientation: 'vertical'
            UsbScreenManager:
                id: manager
            NavLayout:
                id: nav

    TabbedPanelItem:
        id: remote_tab
        text: 'Remote'

    TabbedPanelItem:
        id: sd_tab
        text: 'SD'





<NavLayout>:
    id: nav
    spacing: 5,5
    rows: 1
    size_hint: 1, .2


    LeftButton:
        id: left_arrow_button
        on_release: app.root.manager.current = app.root.manager.previous()
        Image:
            source: 'left_arrow_iconb.png'
            center: left_arrow_button.center
            size: nav.width*.8, nav.height*.8

    BackButton:
        id: back_button

        Image:
            source: 'back_iconb.png'
            center: back_button.center
            size: nav.width*.8, nav.height*.8
    RightButton:
        id: right_arrow_button
        on_release: app.root.manager.current = app.root.manager.next()
        Image:
            source: 'right_arrow_iconb.png'
            center: right_arrow_button.center
            size: nav.width*.8, nav.height*.8

1 个答案:

答案 0 :(得分:2)

可能有更好的&#34;这样做的方式,但我们走了。

首先,我必须声明Kivy Properties,在这个例子中是ObjectProperty(),可能不像它们看起来那样。正如文档所述,ObjectProperty可能表示一个python对象,但让它知道它不会是实际的对象。当ObjectProperty必须通过isinstance测试时,这很重要,因为它会失败。

我提到这个是因为当我不得不从Kivy的另一个类引用我的ListViewLabel类时,我认为我已经解决了我的问题。 (我创建了一个ListViewLabel类来正确格式化我将在屏幕上显示的列表)。我使用ObjectProperty做到了这一点,它就像一个魅力。

in main.py
class HubValidationTestScreen(Screen):
    lvl = ObjectProperty(ListViewLabel)
    #manager = ObjectProperty(UsbScreenManager)
    pass

in kv file

<HubValidationTestScreen>:
    id: hvts
    name: 'hvts'
    BoxLayout:
        ListView:
            adapter:
                sla.SimpleListAdapter(
                data= hvt.requirements,
                cls= root.lvl) <---I'm a genius! (not really)

因此,当我尝试切换屏幕时尝试相同的操作时,我收到了一个错误,指出“屏幕管理器只接受屏幕&#39;”。嗯,这就是我想做的事情。问题在于http://kivy.org/docs/_modules/kivy/uix/screenmanager.html在添加屏幕时必须通过isinstance测试

 if not isinstance(screen, Screen):
            raise ScreenManagerException(
                'ScreenManager accepts only Screen widget.')

它失败了。

所以我发现了如何引用另一个类,但它不适用于此。 我希望我的所有课程都是独立的,包括屏幕,所以我只是在需要时给他们打电话。所以为了能够切换到我所做的屏幕,我的屏幕管理器下的屏幕就像其他两个一样,并且在屏幕管理器的初始化期间我移除了屏幕,希望id仍然留在屏幕管理器中。它确实如此。因此,当按下按钮时,我通过添加一个屏幕并移除另外两个屏幕来给出新屏幕的错觉。然后,我将实施一个&#39; back&#39;按钮可以反转此动作。

<UsbScreenManager>:
    id: manager
    hvts:hvts
    h2h: h2h
    H2HScreen:
        id:h2h
    HubValidationScreen:
        id:hvs
    HubValidationTestScreen:
        id: hvts

class UsbScreenManager(ScreenManager):
    hvts = ObjectProperty()
    h2h = ObjectProperty()
    def __init__(self, **kwargs):

        Clock.schedule_once(self.remove, .5)

        print(str(self.ids))
        super(UsbScreenManager, self).__init__(**kwargs)

    def remove(self, b):
        self.remove_widget(self.hvts)
    pass

<HubValidationScreen>:
    id: hvs
    name: 'hvs'


    BoxLayout:
        id:bl
        orientation: 'vertical'

        TestIcon:
            id: hubvicon

            source: 'usb_button.png'
            on_press: hvs.manager.switch_to(app.root.manager.hvts); app.root.manager.remove_widget(app.root.manager.h2h)