Python Kivy 如何将 Python 制作的小部件注入 kv 文件中的布局
Python Kivy How to inject widgets made with Python to layout in kv file
我写了一个 python kivy 应用程序来显示测量值。在 kivy 上搜索内容时,我偶然发现了 kivy-md(Material Design for kivy)项目。我发现 UI 非常好看。这就是为什么我想将我的应用程序注入 kivy-md 项目的屏幕。
我的项目在文件夹 kivy-playground
中,其中包含 kivymd
文件夹中的文件 kivymd
、main.py
(用于启动 kivy md 应用程序)、 main.kv
文件(用于 kivy md 应用程序的布局)和一个 playground.py
其中包含用于显示测量值的 kivy 应用程序。我正在使用 Python 3.7 和最新版本的 kivy。
Goal: I want to inject the Application view from playground.py
into the main application which is started by the main.py
such that
the view of the playground.py
is displayed on the screen page2
(see main.kv
) of the main application. I am totally lost how this
can be achieved and I would be happy if someone could show me on this
toy example how this can be achieved. It is not necessarily important that the playground.py
stays as it is. If the problem can be solved by small changes in the playground.py
file then this would be also a valid solution.
我试图编写一个最小的工作示例。这是文件
# 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"
这里是 playground.py
,我想将其注入主应用程序的屏幕 page2
。
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.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
。
- 如果有kv文件,playground.kv for playground.py then use
include <file>
在 main.kv
- 添加导入语句,
from playground import PlayGround
in main.py
Kivy Lang Directives » include <file>
include <file>
Syntax:
#:include [force] <file>
Includes an external kivy file. This allows you to split complex
widgets into their own files. If the include is forced, the file will
first be unloaded and then reloaded again.
片段
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 kivy 应用程序来显示测量值。在 kivy 上搜索内容时,我偶然发现了 kivy-md(Material Design for kivy)项目。我发现 UI 非常好看。这就是为什么我想将我的应用程序注入 kivy-md 项目的屏幕。
我的项目在文件夹 kivy-playground
中,其中包含 kivymd
文件夹中的文件 kivymd
、main.py
(用于启动 kivy md 应用程序)、 main.kv
文件(用于 kivy md 应用程序的布局)和一个 playground.py
其中包含用于显示测量值的 kivy 应用程序。我正在使用 Python 3.7 和最新版本的 kivy。
Goal: I want to inject the Application view from
playground.py
into the main application which is started by themain.py
such that the view of theplayground.py
is displayed on the screenpage2
(seemain.kv
) of the main application. I am totally lost how this can be achieved and I would be happy if someone could show me on this toy example how this can be achieved. It is not necessarily important that theplayground.py
stays as it is. If the problem can be solved by small changes in theplayground.py
file then this would be also a valid solution.
我试图编写一个最小的工作示例。这是文件
# 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"
这里是 playground.py
,我想将其注入主应用程序的屏幕 page2
。
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.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
。
- 如果有kv文件,playground.kv for playground.py then use
include <file>
在 main.kv - 添加导入语句,
from playground import PlayGround
in main.py
Kivy Lang Directives » include <file>
include <file>
Syntax:
#:include [force] <file>
Includes an external kivy file. This allows you to split complex widgets into their own files. If the include is forced, the file will first be unloaded and then reloaded again.
片段
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: