Reputation: 191
I have written a python kivy application for displaying measurements. While searching stuff on kivy I stumbled on the the kivy-md (Material Design for kivy) project. I find the UI very good looking. That is why I want to inject my app into a screen of the kivy-md project.
My project is inside a folder kivy-playground
which contains the kivymd
files in a folder kivymd
, the main.py
(for starting the kivy md application), the main.kv
file (for the layout of the kivy md application) and a playground.py
which contains the kivy application for displaying measurements. I am using Python 3.7 with the latest version of 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.
I tried to cook up a minimal working example. Here are the files
# 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()
here is the 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"
and here is the playground.py
which I want to inject into the screen page2
of the main application.
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()
Upvotes: 1
Views: 2683
Reputation: 16011
include <file>
in main.kvfrom playground import PlayGround
in main.pyKivy 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.
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()
#:kivy 1.11.0
<PlayGround>:
text: "Hello World!"
# 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
#: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:
Upvotes: 1
Reputation: 38822
If you can change Playground.py
to something like this:
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()
Then, in your main.py
, you can add:
from playGround import getPlaygroundRoot
And then use add_widget(getPlaygroundRoot())
to add the Playground
root to some container in the MainApp
.
Or, if you want to use Playground
in your .kv
file, you can add
#:import playground playGround
to your .kv
file, and then add:
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)
to add it to your page2
.
Upvotes: 4