【问题标题】:Python Kivy How to inject widgets made with Python to layout in kv filePython Kivy 如何将用 Python 制作的小部件注入到 kv 文件中的布局中
【发布时间】:2019-02-15 00:26:22
【问题描述】:

我编写了一个 python kivy 应用程序来显示测量值。在 kivy 上搜索东西时,我偶然发现了 kivy-md(kivy 的材料设计)项目。我觉得 UI 非常好看。这就是为什么我想将我的应用程序注入到 kivy-md 项目的屏幕中。

我的项目位于文件夹 kivy-playground 中,其中包含文件夹 kivymd 中的 kivymd 文件、main.py(用于启动 kivy md 应用程序)、main.kv 文件(用于布局kivy md 应用程序)和一个playground.py,其中包含用于显示测量值的 kivy 应用程序。我正在使用 Python 3.7 和最新版本的 kivy。

目标:我想将来自playground.py 的应用程序视图注入到由main.py 启动的主应用程序中,这样 playground.py 的视图显示在屏幕上page2 (见main.kv)的主应用程序。我完全迷失了这是怎么回事 可以实现,如果有人能告诉我这个我会很高兴 玩具示例如何实现这一点。 playground.py 保持原样并不一定很重要。如果问题可以通过对playground.py 文件的微小更改来解决,那么这也是一个有效的解决方案。

我尝试编写一个最小的工作示例。这是文件

# main.py
# -*- coding: utf-8 -*-

import os

from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivymd.theming import ThemeManager


class MainApp(App):

    theme_cls = ThemeManager()

    def __init__(self, **kwargs):
        super(MainApp, self).__init__(**kwargs)
        Window.bind(on_close=self.on_stop)

    def build(self):
        main_widget = Builder.load_file(
            os.path.join(os.path.dirname(__file__), "./main.kv")
        )
        self.theme_cls.theme_style = 'Dark'
        return main_widget

    def close_app(self, *largs):
        super(MainApp, self).stop(*largs)

    def on_pause(self):
        return True


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

这里是main.kv

# main.kv
#:kivy 1.10.1
#:import Toolbar kivymd.toolbar.Toolbar
#:import MDNavigationDrawer kivymd.navigationdrawer.MDNavigationDrawer
#:import NavigationLayout kivymd.navigationdrawer.NavigationLayout
#:import NavigationDrawerToolbar kivymd.navigationdrawer.NavigationDrawerToolbar

NavigationLayout:
    id: nav_layout
    MDNavigationDrawer:
        id: nav_drawer
        NavigationDrawerToolbar:
        NavigationDrawerIconButton:
            icon: 'checkbox-blank-circle'
            text: "Page1"
            on_release: app.root.ids.scr_mngr.current = 'page1'
        NavigationDrawerIconButton:
            icon: 'checkbox-blank-circle'
            text: "Page2"
            on_release: app.root.ids.scr_mngr.current = 'page2'
    BoxLayout:
        orientation: 'vertical'
        halign: "center"
        Toolbar:
            id: toolbar
            md_bg_color: app.theme_cls.primary_color
            background_palette: 'Primary'
            background_hue: '500'
            right_action_items: [['dots-vertical', lambda x: app.root.toggle_nav_drawer()]]
        ScreenManager:
            id: scr_mngr
            Screen:
                name: 'page1'
                Label:
                    text: "page1"
            Screen:
                name: 'page2'
                Label:
                    text: "Page 2"

这是我想要注入到主应用程序屏幕page2playground.py

from kivy.app import App
from kivy.uix.label import Label


class Playground(App):

    def build(self):
        hello_world_label = Label(text="Hello World!")
        return hello_world_label


if __name__ == "__main__":
    Playground().run()

【问题讨论】:

  • 我怀疑尝试在同一个窗口中运行两个应用程序会导致很多问题。将Playground 应用程序中的根小部件插入原始应用程序会容易得多。
  • 它不必与第二个应用程序一起使用,但我不知道如何更改 playground.py 以便可以将其注入到 page2main.kv 中。跨度>

标签: python python-3.x layout kivy programmatically-created


【解决方案1】:

如果您可以将Playground.py 更改为这样的:

from kivy.app import App
from kivy.uix.label import Label

def getPlaygroundRoot():
    hello_world_label = Label(text="Hello World!")
    return hello_world_label


class PlayGround(FloatLayout):
    def __init__(self, **kwargs):
        super(PlayGround, self).__init__(**kwargs)
        self.add_widget(getPlaygroundRoot())

class Playground(App):

    def build(self):
        return getPlaygroundRoot()


if __name__ == "__main__":
    Playground().run()

然后,在您的main.py 中,您可以添加:

from playGround import getPlaygroundRoot

然后使用add_widget(getPlaygroundRoot())Playground 根添加到MainApp 中的某个容器中。

或者,如果您想在您的 .kv 文件中使用 Playground,您可以添加 #:import playground playGround 到你的.kv 文件,然后添加:

        Screen:
            name: 'page2'
            Label:
                text: "Page 2"
                pos_hint: {'center_x': 0.5, 'y': 0.8}
                size_hint: (1.0, 0.2)
            PlayGround:
                pos_hint: {'center_x': 0.5, 'y': 0.1}
                size_hint: (1.0, 0.2)

将其添加到您的page2

【讨论】:

  • 感谢您的回答!如果成功,我会尝试并接受答案。
  • 谢谢!它就像一个魅力!我花了一些时间来弄清楚如何重构应用程序,但您的示例是理解如何实现它的关键。
【解决方案2】:
  • 如果有 kv 文件,playground.kv for playground.py 然后在 main.kv 中使用 include <file>
  • main.py 中添加导入语句 from playground import PlayGround

Kivy Lang Directives » include <file>

include <file>

语法:

#:include [force] <file>

包括一个外部 kivy 文件。这允许您拆分复杂的 小部件到他们自己的文件中。如果强制包含,文件将 先卸载再重新加载。

片段

playground.py

​​>
from kivy.app import App
from kivy.uix.label import Label


class PlayGround(Label):
    pass


class Playground(App):

    def build(self):
        return PlayGround()


if __name__ == "__main__":
    Playground().run()

playground.kv

#:kivy 1.11.0

<PlayGround>:
    text: "Hello World!"

min.py

​​>
# main.py
# -*- coding: utf-8 -*-

import os

from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivymd.theming import ThemeManager
from playground import PlayGround


class MainApp(App):

main.kv

# main.kv
#:kivy 1.10.1
#:import Toolbar kivymd.toolbar.Toolbar
#:import MDNavigationDrawer kivymd.navigationdrawer.MDNavigationDrawer
#:import NavigationLayout kivymd.navigationdrawer.NavigationLayout
#:import NavigationDrawerToolbar kivymd.navigationdrawer.NavigationDrawerToolbar

#:include playground.kv

NavigationLayout:
    ...
        ScreenManager:
            id: scr_mngr
            Screen:
                name: 'page1'
                Label:
                    text: "page1"
            Screen:
                name: 'page2'
                Label:
                    text: "Page 2"
                PlayGround:

【讨论】:

  • 感谢您的回答。问题是,我的整个代码都在 python 中。我没有为 playground.py 使用任何 kv 文件。
猜你喜欢
  • 2018-03-06
  • 2017-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多