简体   繁体   English

Python Kivy遍历小部件树

[英]Python Kivy Traversing the Widget tree

I'm building a small project for school and I require an interface so I thought I would use Kivy and Python for it but I'm stuck in a part with the UI , mainly how can I access widgets across the tree. 我正在为学校建设一个小型项目,并且需要一个接口,所以我以为我会使用KivyPython ,但是我陷入UI的一部分,主要是如何在树上访问小部件。 I have searched around but the kivy docs are not very helpful and what questions and answer I found don't seem to be related. 我进行了搜索,但是kivy文档不是很有帮助,发现的问题和答案似乎无关。

What I want to do is to have a top bar with some buttons and below a screen manager that has separate predefined screens but I'm not sure how could I traverse the tree to get to do what I need. 我想要做的是在顶部的按钮栏和一个单独的预定义屏幕的屏幕管理器下方,但是我不确定如何遍历树以完成所需的操作。

So for example the first button would always bring up the screen called Dashboard. 因此,例如,第一个按钮将始终显示称为仪表板的屏幕。 I have tried something I found, but I'm getting "Name Dashboard not defined" 我已经尝试了一些发现的问题,但是却收到“未定义名称仪表盘”的信息

    #!/usr/bin/env python 
    from kivy.app import App 
    from kivy.uix.widget import Widget 
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.floatlayout import FloatLayout
    from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
    from kivy.properties import ObjectProperty


    class Container(FloatLayout):
        pass

    class UpperMenu(BoxLayout):
        def change_screen(self,argument):
            self.ids.screens.ids.manager.current = argument


    class Screens(ScreenManager):
        pass

    class Dashboard(Screen):
        pass

    class Player(Screen):
        pass

    class Weather(Screen):
        pass

    class Map(Screen):
        pass

    class Carousel(BoxLayout):
        pass

    class CarlApp(App):
        def build(self):
            return Container()

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

And here is my KV file: 这是我的KV文件:

    #:kivy 1.10.0

    <Container>:
        id: container
        UpperMenu:
            id: uppermenu
            pos: root.x, root.top - self.height
        Screens:
            id: screens

    <UpperMenu>:
        size_hint: 1,.15
        Button:
            text: ""
            id: ButtonCeasuri
            on_release: root.change_screen(dashboard)
            Image:
                source: 'dashboard.png'
                allow_stretch: False
                center_x: self.parent.center_x
                center_y: self.parent.center_y
        Button:
            text: ""
            id: ButtonCeasurii
            Image:
                source: 'play-button.png'
                allow_stretch: False
                center_x: self.parent.center_x
                center_y: self.parent.center_y
        Button:
            text: ""
            id: ButtonCeasuriii
            Image:
                source: 'distance.png'
                allow_stretch: False
                center_x: self.parent.center_x
                center_y: self.parent.center_y
        Button:
            text: ""
            id: ButtonCeasuriiii
            Image:
                source: 'temperature.png'
                allow_stretch: False
                center_x: self.parent.center_x
                center_y: self.parent.center_y

    <Screens>:
        size_hint: 1,.85
        Dashboard:
            name: 'Dashboard'
            label: "Dashboard Screen"
            id: dashboard
            Button:
                text: "Stuff"
                on_release: pass
        Player:
            name: 'Player'
            label: "Player Screen"
            id: Player
            Button:
                text: "Stuff2"
        Weather:
            name: 'Weather'
            label: "Weather Screen"
        Map:
            name: 'Map'
            label: "Map Screen"

I've been trying to understand how can I do this in the last 3-4 days, but I fail to understand. 我一直试图了解过去3-4天该怎么做,但是我不明白。

from your codes, it seems you are already on the dashboard screen, anyway to change your screen to another screen, this is a sample code to help you do that 从您的代码看来,您似乎已经在仪表板屏幕上了,无论如何将您的屏幕更改为另一个屏幕,这是一个示例代码,可以帮助您实现

<UpperMenu>:
size_hint: 1,.15
Button:
    text: ""
    id: ButtonCeasuri
    on_release: root.change_screen("Dashboard")

the name dashboard is undefined because the kv file cant make a reference to it,, and then in your code you can also do this instead,, 名称仪表板是未定义的,因为kv文件无法对其进行引用,然后在您的代码中也可以这样做,

class UpperMenu(BoxLayout):
    def change_screen(self,argument):
        self.parent.children[0].current = argument

you can call print(self.parent.children) to see what it prints out, i hope this helps 您可以致电print(self.parent.children)查看打印出来的内容,希望对您print(self.parent.children)帮助

To change the screen, there are two ways to do it. 要更改屏幕,有两种方法可以完成。 The first method is all done in kv file. 第一种方法都是在kv文件中完成的。 The second method is done in Python file. 第二种方法在Python文件中完成。 In the example demonstrates both methods. 在示例中演示了这两种方法。

Method 1 - kv file 方法1-KV文件

You could put the code for changing screen in the kv file by replacing: 您可以通过以下方式将用于更改屏幕的代码放在kv文件中:

root.change_screen(dashboard)

with

app.root.ids.screen.current = 'Dashboard'    # 'Dashboard' name of screen

Method 2 - Python & kv files 方法2-Python和KV文件

  1. In kv file, pass the name of the screen to change_screen() function eg root.change_screen('Dashboard') . kv文件中,将屏幕名称传递给change_screen()函数,例如root.change_screen('Dashboard')
  2. In Python file, replace self.ids.screens.ids.manager.current with self.parent.ids.screen.current in change_screen() method. Python文件,更换self.ids.screens.ids.manager.currentself.parent.ids.screen.currentchange_screen()方法。

Note 注意

AttributeError AttributeError

     self.ids.screens.ids.manager.current = argument
 AttributeError: 'super' object has no attribute '__getattr__'

Explanation 说明

self - The keyword self references the “current widget instance” ie class UpperMenu() self-关键字self引用“当前小部件实例”,即类UpperMenu()

ids - The keyword ids references the lookup object and it is a dictionary type property. ids-关键字id引用查找对象,它是字典类型的属性。 In this case, all the Button widgets tagged with id's under the class rule <UpperMenu>: in the kv file. 在这种情况下,所有kv文件中在类规则<UpperMenu>:下标记有id的Button小部件。

screens - The keyword screens reference the id's for screens but it does not exist under self.ids . 屏幕 -关键字屏幕参考ID对 屏幕 ,但它并没有下self.ids存在。 Due to this, Kivy threw AttributeError. 因此,Kivy抛出了AttributeError。 Add print(self.ids) to display all the ids found in self.ids . 添加print(self.ids)以显示在self.ids中找到的所有ID

Example

test.kv 测试文件

#:kivy 1.10.0

<Container>:
    id: container
    UpperMenu:
        id: uppermenu
        pos: root.x, root.top - self.height
    Screens:
        id: screens

<UpperMenu>:
    size_hint: 1,.15
    Button:
        text: ""
        id: ButtonCeasuri
        on_release:
            root.change_screen('Dashboard')    # Method 2

        Image:
            source: 'dashboard.png'
            allow_stretch: False
            center_x: self.parent.center_x
            center_y: self.parent.center_y
    Button:
        text: ""
        id: ButtonCeasurii
        on_release:
            app.root.ids.screens.current = 'Player'    # Method 1

        Image:
            source: 'play-button.png'
            allow_stretch: False
            center_x: self.parent.center_x
            center_y: self.parent.center_y
    Button:
        text: ""
        id: ButtonCeasuriii
        Image:
            source: 'distance.png'
            allow_stretch: False
            center_x: self.parent.center_x
            center_y: self.parent.center_y
    Button:
        text: ""
        id: ButtonCeasuriiii
        Image:
            source: 'temperature.png'
            allow_stretch: False
            center_x: self.parent.center_x
            center_y: self.parent.center_y

<Screens>:
    size_hint: 1,.85
    Dashboard:
        id: dashboard
        name: 'Dashboard'
        label: "Dashboard Screen"
        Button:
            text: "Stuff"
            on_release: pass
    Player:
        name: 'Player'
        label: "Player Screen"
        id: Player
        Button:
            text: "Stuff2"
    Weather:
        name: 'Weather'
        label: "Weather Screen"
    Map:
        name: 'Map'
        label: "Map Screen"

main.py main.py

#!/usr/bin/env python
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.properties import ObjectProperty


class Container(FloatLayout):
    pass


class UpperMenu(BoxLayout):
    def change_screen(self, argument):
        self.parent.ids.screens.current = argument


class Screens(ScreenManager):
    pass


class Dashboard(Screen):
    pass


class Player(Screen):
    pass


class Weather(Screen):
    pass


class Map(Screen):
    pass


class Carousel(BoxLayout):
    pass


class TestApp(App):
    def build(self):
        return Container()


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

Output 输出量

Clicked Second Button 单击第二个按钮

Img01-单击第二个按钮后显示的第二个屏幕

Clicked First Button 单击第一个按钮

Img02-单击第一个按钮后显示的第一个屏幕

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM