No project description provided
Project description
KivyMD-utils
description
KivyMD-utils brings some flutter widgets to KivyMD.
CoroutineBuilder
This widget allows to render the result of a Coroutine. It will rerender when the coroutine finishes its work.
example:
class TestApp(MDApp):
async def generate_number(self):
await asyncio.sleep(2)
return "5"
def build(self):
self.coroutine = self.generate_number()
return CoroutineBuilder(
builder=self.generate_text,
coroutine=self.coroutine
)
def generate_text(self, snapshot: CoroutineSnapshot):
if snapshot.has_data:
return MDLabel(text = snapshot.data)
else:
return MDLabel(text = "calculating")
RedrawAble
A widget that allows all content to be redrawn when a value changes. This widget differs from properties in that it allows any class to inherit the NotifyListeners
class and be used in any RedrawAble
. A new value also does not mean an automatic redraw but can be controled using either the notify_listeners()
method or by calling redraw()
example:
class Person(NotifyListener):
def __init__(self, name:str, age: int):
super().__init__()
self.name = name
self.age = age
def age_up(self):
self.age += 1
self.notify_listeners()
class App(MDApp):
def build(self):
self.person = Person("Joe", 25)
self.redraw_able= RedrawAble(
provider=self.person,
builder=lambda: MDBoxLayout(
MDLabel(text= f"{self.person.name} is {self.person.age} years old"),
MDTextButton(
text= "age",
on_release= lambda x:self.person.age_up()
),
MDTextButton(
text="force redraw",
on_release= lambda x: self.redraw_able.redraw()
)
)
)
return self.redraw_able
Router
A basic implementation of GoRouter is provided under the router directory. The Router widget provides a ScreenManager implementation that allows vertical and horizontal movement.
To achieve horizontal navigation the router allows swapping pages utilizing the router.go(<url>)
method. The Route of the most specific path
will be chosen and displayed
basic example:
from kivymd_utils.router import Router, RouterWidget, Route
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDTextButton
from kivymd.app import MDApp
ROUTER = Router(
initial_route="/",
routes= [
Route(
path="/",
builder=lambda state, *args, **kwargs: MDBoxLayout(
MDLabel(text= "home screen"),
MDTextButton(
text= "to next screen",
on_release= lambda x: kwargs["router"].go("/greet")
)
)
),
Route(
path="/greet",
builder=lambda state, *args, **kwargs: MDLabel(text= "hello user")
)
]
)
class App(MDApp):
def build(self):
return RouterWidget(
router = ROUTER
)
if __name__=="__main__":
App().run()
Nested Routes can be achieved by nesting routes inside the Router widget.
example:
from kivymd_utils.router import Router, RouterWidget, Route
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDTextButton
from kivymd.app import MDApp
ROUTER = Router(
initial_route="/",
routes= [
Route(
path="/",
builder=lambda state, *args, **kwargs: MDBoxLayout(
MDLabel(text= "home screen"),
MDTextButton(
text= "to next screen",
on_release= lambda x: kwargs["router"].go("/greet")
)
)
),
Route(
path="/greet",
builder=lambda state, *args, **kwargs: MDBoxLayout(
MDLabel(text= "hello user"),
MDTextButton(
text= "go deeper",
on_release= lambda x: kwargs["router"].go("/greet/again")
)
),
routes=[
Route(
path="/again",
builder=lambda state, *args, **kwargs: MDLabel(text= "hello again")
)
]
)
]
)
class App(MDApp):
def build(self):
return RouterWidget(
router = ROUTER
)
if __name__=="__main__":
App().run()
If you need a topbar for all elements of a specific path you can utilize a ShellRoute. The shellroute draws its own content around the child object.
ROUTER = Router(
initial_route="/",
routes= [
ShellRoute(
builder=lambda state, child, *args, **kwargs: MDBoxLayout(
MDLabel(text="Title block"),
child,
orientation="vertical"
),
routes=[
Route(
path="/",
builder=lambda state, *args, **kwargs: MDBoxLayout(
MDLabel(text="home"),
MDTextButton(
text="next_page",
on_release= lambda x: kwargs["router"].go("/greet")
)
)
),
Route(
path="/greet",
builder=lambda state, *args, **kwargs: MDLabel(text= "hello user")
)
]
)
]
)
When routing sometimes you need to pass an object to the widget to display it. To notify a route passes an object you need to start it with a ':'
example:
ROUTER = Router(
initial_route="/",
routes= [
Route(
path="/",
builder=lambda state, *args, **kwargs: MDBoxLayout(
MDLabel(text="home"),
MDTextButton(
text="go greet",
#for simple string objects, we can pass it as a url itself
on_release= lambda x: kwargs["router"].go("/greet/Joe")
),
MDTextButton(
text="go greet",
#you can also pass data with the goData method and a dictionary containing data
#the key is equivalent to the name in the url '/greet/:name'
#all items are optional in the dictionary and will fall back to the item in the url
on_release= lambda x: kwargs["router"].goData("/greet/_", {"name": "Joe"})
)
)
),
Route(
path="/greet/:name",
#you can access the data via the state.parameters dictionary
builder=lambda state, *args, **kwargs: MDLabel(text= state.parameters["name"])
)
]
)
When a page gets moved to a new route you can modify the old route to be a redirect, this allows all the old router.go()
methods to point to the new page with minimal configuration.
example:
ROUTER = Router(
initial_route="/",
routes= [
Route(
path="/",
builder=lambda state, *args, **kwargs: MDBoxLayout(
MDLabel(text="home"),
MDTextButton(
text="go greet",
on_release= lambda x: kwargs["router"].go("/old")
),
)
),
Route(
path="/old",
redirect="/new"
),
Route(
path="/new",
builder=lambda state, *args, **kwargs: MDLabel(text= "a new page")
)
]
)
To allow for vertical movement the provided methods of push(<url>)
and pop()
are provided. An equivalent pushData(<url>, <data>)
is also provided.
Everytime a .go()
method is called the current page stack gets cleared. Pushing a page adds it to the current page stack allowing for a back button to call pop()
example:
ROUTER = Router(
initial_route="/",
routes= [
Route(
path="/",
builder=lambda state, *args, **kwargs: MDBoxLayout(
MDLabel(text="home"),
MDTextButton(
text="show popup",
on_release= lambda x: kwargs["router"].push("/popup")
),
)
),
Route(
path="/popup",
builder=lambda state, *args, **kwargs: MDBoxLayout(
MDLabel(text="popup"),
MDTextButton(
text="go back",
on_release= lambda x: kwargs["router"].pop()
)
)
)
]
)
Instead of a builder method you can also pass a prebuilt widget to the Route. Due to a limitation with kivy itself, this is not possible when declaring the router as a global variable.
example:
class App(MDApp):
def build(self):
router = Router(
initial_route="/",
routes= [
Route(
path="/",
builder=lambda state, *args, **kwargs: MDBoxLayout(
MDLabel(text="home"),
MDTextButton(
text="show prebuilt",
on_release= lambda x: kwargs["router"].push("/prebuilt")
),
)
),
Route(
path="/prebuilt",
#you can access the data via the state.parameters dictionary
widget=MDLabel(text="prebuilt"),
)
]
)
return RouterWidget(
router = router
)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for kivymd_utils-0.15.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7e298911841cddeea002c9bd6b44d75c50dc6c80a824ef02f27c7a30f240568a |
|
MD5 | 452cb114271966b7bc5c1626882a1468 |
|
BLAKE2b-256 | 994bee06d17b967a2bded9e8fd0f150738270e30f5c9ae8ef2dde45c1e15b702 |