Kivy - 如何从ListView调用函数?

时间:2017-12-14 20:24:37

标签: android python python-3.x kivy kivy-language

因此,当我按下ListView项时,我无法找到通过过程传递值的方法。以下示例是我想要发生的更简单的版本以及我的主要代码的设置方式。 目标是在KV文件中的哈希标记 on_release:上看到 ChangeScreen(self.index)。但问题是我不知道如何成功调用ChangeScreen。谢谢!

Kivy:

#: import main main
#: import ListAdapter kivy.adapters.listadapter.ListAdapter 

AppScreenManager:
    DemoScreen1:
        id: screen1
    DemoScreen2:
        id: screen2

<DemoScreen1>:
    name: "demoscreen1"
    BoxLayout:
        orientation: "vertical"
        ListView:
            adapter:
                ListAdapter(data=["Screen 1","Screen 2"], cls=main.ListButton)

<DemoScreen2>:
    name: "demoscreen2"
    orientation: "vertical"
    BoxLayout:
        orientation: "vertical"
        Label:
            id: labText
            text: "Hello World"

<ListButton>:
    height: self.texture_size[1]
    on_release: ### HOW DO I CALL THE ChangeScreen FUNCTION HERE

的Python:

import kivy
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import StringProperty, ObjectProperty, ListProperty
from kivy.uix.listview import ListItemButton


class DemoScreen1(Screen):
    def ChangeScreen(self, option):
        if option == 0:
            print("Screen1")
            self.parent.ids.screen2.labelUpdater("Screen 1 was pressed")
        else:
            print("Screen2")
            self.parent.ids.screen2.labelUpdater("Screen 2 was pressed")
        self.parent.current = "demoscreen2"

class DemoScreen2(Screen):
    labText = StringProperty()
    def labelUpdater(self,newText):
        self.ids.labText.text = newText

class ListButton(ListItemButton):
    data = ListProperty()

class AppScreenManager(ScreenManager):
    pass
class Tester(App): 
    pass
if __name__ == '__main__':
    Tester().run() 

3 个答案:

答案 0 :(得分:1)

另一种解决方案:

...
<ListButton>:
    height: self.texture_size[1]
    on_release: self.parent.parent.parent.parent.parent.ChangeScreen(self.index)

...

但是只针对on_presson_release这样的事件执行此操作,因为on_parent永远不会为self.parent.parent.parent执行此事件,因为他们在调用最后一个事件时没有父母

要获得解释,您必须知道的是ListView是您的SUGAR.util = function () { var additionalDetailsCache; var additionalDetailsCalls; var additionalDetailsRpcCall; return{getAndRemove: function (el) { if (YAHOO && YAHOO.util && YAHOO.util.Dom) el = YAHOO.util.Dom.get(el); else if (typeof (el) == "string") el = document.getElementById(el); if (el && el.parentNode) el.parentNode.removeChild(el); return el; }, paramsToUrl: function (params) { var parts = []; for (var i in params) { if (params.hasOwnProperty(i)) { parts.push(encodeURIComponent(i) + '=' + encodeURIComponent(params[i])); } } return parts.join("&") + "&"; }, globalEval: function (data) { var rnotwhite = /\S/; if (data && rnotwhite.test(data)) { (window.execScript || function (data) { window["eval"].call(window, data); //<====== THIS IS THE LINE MENTIONED IN THE WEB BROWSER'S CONSOLE })(data); }

我希望这会有所帮助

答案 1 :(得分:1)

我认为你应该这样做:

  • ChangeScreen方法应移至ScreenManager:它是a 管理屏幕更改的屏幕管理员。

  • 更改选择的反应应放在ListAdapter内: list adapter - 是一个控制器,用于管理选择中发生的事情 on_selection_change事件。 您可以使用与您相同的方式继承ListAdapter ListItemButton

  • 放置在kvfile中调用的回调是(恕我直言)坏主意:kvfile是一种视图,将回调留给cotrollers,例如ListAdapter。再次,它可以继承ListAdapter

  • 由于ListAdapter使用ScreenManager&#39; ChangeScreen方法,因此适配器应该与屏幕一起使用(替代它可以像EL3PHANTEN建议的那样放置{{1}进入App,但它变成了一种全局变量。)

此处的重构代码包含上述所有建议:

<强> tester.kv

ScreenManager

<强> main.py

#: import main main

AppScreenManager:
    DemoScreen1:
        id: screen1
    DemoScreen2:
        id: screen2

<DemoScreen1>:
    name: "demoscreen1"
    BoxLayout:
        orientation: "vertical"
        ListView:
            adapter:
                main.MyListAdapter(
                data=["Screen 1","Screen 2"], 
                cls=main.MyListButton, 
                scr=root.parent
                )

<DemoScreen2>:
    name: "demoscreen2"
    orientation: "vertical"
    BoxLayout:
        orientation: "vertical"
        Label:
            id: labText
            text: "Hello World"

<MyListButton>:
    height: self.texture_size[1]

答案 2 :(得分:0)

请尝试将changeScreen方法放在ListButton课程中 然后将ScreenManager作为App类中的属性。你可以在kv中以app.sm的形式访问它 然后,您可以将app.sm传递给ChangeScreen方法,以获取屏幕 以下是您修改过的示例:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.listview import ListItemButton
from kivy.lang import Builder


class DemoScreen2(Screen):

    def labelUpdater(self,newText):
        self.ids.labText.text = newText


class ListButton(ListItemButton):
    data = ListProperty()

    def ChangeScreen(self, option, sm):
        if option == 0:
            print("Screen1")
            sm.ids.screen2.labelUpdater("Screen 1 was pressed")
        else:
            print("Screen2")
            sm.ids.screen2.labelUpdater("Screen 2 was pressed")
        sm.current = "demoscreen2"


class AppScreenManager(ScreenManager):
    pass


KV = """

#: import ListAdapter kivy.adapters.listadapter.ListAdapter
#: import Factory kivy.factory.Factory

<AppScreenManager>:
    DemoScreen1:
        id: screen1
    DemoScreen2:
        id: screen2

<DemoScreen1@Screen>:
    name: "demoscreen1"
    BoxLayout:
        orientation: "vertical"
        ListView:
            adapter:
                ListAdapter(data=["Screen 1","Screen 2"], cls=Factory.ListButton)

<DemoScreen2>:
    name: "demoscreen2"
    orientation: "vertical"
    BoxLayout:
        orientation: "vertical"
        Button:
            id: labText
            text: "Hello World"
            on_release:
                app.sm.current = "demoscreen1"

<ListButton>:
    height: self.texture_size[1]
    on_release: root.ChangeScreen(self.index,app.sm)

"""


class Tester(App):

    def build(self):
        Builder.load_string(KV)
        self.sm = AppScreenManager()
        return self.sm

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