Using builder in Kivy - kivy

I want to create a simple app that has GUI with a button that allows me to vibrate an android phone. Im using a .kv file for the layout and the Builder in my .yp file
.py file:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.lang import Builder
from plyer import vibrator
class AndroidApp(GridLayout):
def vibrate(self):
vibrator.vibrate()
kv = Builder.load_file("android_app.kv")
class MainApp(App):
def build(self):
return kv
if __name__ == "__main__":
MainApp().run()
.kv file:
#:import utils kivy.utils
<AndroidApp>:
FloatLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
GridLayout:
rows: 1
cols: 2
Label:
text:"Android Vibrate"
Button:
text:"Android Vibrate"
on_press:
root.vibrate()
When I try to run the app, I get the following error:
enter image description here
This should be straightforward app but somehow I find a way to make it crash. The android_app.py & .kv files are in the same folder. Any ideas why the window wont be created? I aprreciate any help.
Thanks,
Alex

You have to return the main class, not the result from building. Here I'm using Builder.load_string() for convenience, and not importing player, but otherwise the only substantive change is that I changed return kv to return AndroidApp()
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.lang import Builder
KV = '''
#:import utils kivy.utils
<AndroidApp>:
FloatLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
GridLayout:
rows: 1
cols: 2
Label:
text:"Android Vibrate"
Button:
text:"Android Vibrate"
on_press:
root.vibrate()
'''
class AndroidApp(GridLayout):
def vibrate(self):
vibrator.vibrate()
Builder.load_string(KV)
class MainApp(App):
def build(self):
return AndroidApp()
if __name__ == "__main__":
MainApp().run()

Related

KivyMD, MDFloatingActionButton: correct placement

I've been trying to use floating action buttons alongside FileChooser:
import kivy
kivy.require("2.1.0")
from kivy.utils import platform
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivymd.app import MDApp
from kivymd.uix.tab import MDTabsBase
from kivymd.icon_definitions import md_icons
import os
USERPATH = os.path.expanduser("~")
if platform == "android":
from android.storage import primary_external_storage_path
from android.storage import secondary_external_storage_path
from android.permissions import request_permissions, Permission
USERPATH = primary_external_storage_path()
request_permissions(
[Permission.WRITE_EXTERNAL_STORAGE, Permission.READ_EXTERNAL_STORAGE]
)
KV = '''
#:kivy 2.1.0
#:set dark_gray (.5, .5, .5, 1)
MDBoxLayout:
orientation: "vertical"
MDTabs:
id: ps_tabs
TabList:
id: ps_tab_list
icon: "folder"
FileChooserListView:
id: ps_filechooser
canvas.before:
Color:
rgba: dark_gray
Rectangle:
size: self.size
pos: self.pos
MDFloatingActionButton:
id: fc_playdir
icon: "folder"
pos_hint: {"center_x": .4, "center_y": .5}
MDFloatingActionButton:
id: fc_playfile
icon: "file"
pos_hint: {"center_x": .6, "center_y": .5}
TabDetails:
id: ps_tab_details
icon: "book"
MDScrollView:
'''
class TabList(FloatLayout, MDTabsBase):
"""The engaged power supplies tab."""
class TabDetails(FloatLayout, MDTabsBase):
"""The engaged power supply details tab."""
class Ron(MDApp):
def build(self):
return Builder.load_string(KV)
def on_start(self):
self.theme_cls.primary_palette = "Gray"
self.theme_cls.material_style = "M3"
if platform != "android":
self.root.ids.ps_tabs.lock_swiping = True
self.root.ids.ps_filechooser.rootpath = USERPATH
if __name__ == "__main__":
Ron().run()
Mouse clicks, as well as taps, shoot right through the buttons and into the FileChooser, no matter what I do. I tried placing the buttons into their own box layout, tried moving them up and down the widget tree. Nothing helps, while the buttons remain visible. Besides, on visiting the second tab, one can see two thick black button footprints. Something's very wrong and I can't think of anything else to try.

Recreating kivy app with scrollview to be used as screen with screenmanager

I've been trying to use scrollview in a screen, that will be used as part of an app and I managed to find the following code that creates an app with scrollview. But I'm not able to change it into screen class.
Here is the python code:
from kivy.app import App
from kivy.uix.button import Button
class ScrollButton(Button):
pass
class TestApp(App):
def build(self):
super(TestApp, self).build()
container = self.root.ids.container
for i in range(30):
container.add_widget(ScrollButton(text=str(i)))
return self.root
if __name__ == '__main__':
TestApp().run()
.kv file
ScreenManager:
Screen:
ScrollView:
size_hint: None, None
size: 600, 320
pos_hint: {'center_x': .5, 'center_y': .5}
GridLayout:
cols: 1
padding: 10
spacing: 10
height: self.minimum_height
size_hint: None, None
do_scroll_x: False
id: container
<ScrollButton>
size_hint: None, None
size: 600, 40
I would appreciate if anybody could show how to do it/give me some directions on how to change this to fit my purpose. Any alternative way of doing this is also welcome.
Many people recommend making the ScreenManager in the build method in the python file instead, here's how to do that:
Python
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang.builder import Builder
Builder.load_file("styling.kv")
class ScrollButton(Button):
pass
class MainScreen(Screen):
def on_kv_post(self, instance):
container = self.ids['container']
for i in range(30):
container.add_widget(ScrollButton(text=str(i)))
class TestApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MainScreen())
return sm
if __name__ == '__main__':
TestApp().run()
Kivy
<ScrollButton>:
size_hint: None, None
size: 600, 40
<MainScreen>:
name: 'MainScreen'
ScrollView:
size_hint: None, None
size: 600, 320
pos_hint: {'center_x': .5, 'center_y': .5}
GridLayout:
cols: 1
padding: 10
spacing: 10
height: self.minimum_height
size_hint: None, None
do_scroll_x: False
id: container
Changes made
ScreenManager made in .py instead of .kv
Created Screen class in .py, so we can use python methods from the Screen
Widget adding moved to the Screen's class, using on_kv_post (this method is fired only one time when the Screen is ready)
Made the screen a template class instead of an object in .kv which the Screen in the python file uses to make the final Screen
PS: This is how it's usually done

Center Title in actionbar - kivy

Is there any chance to center title or some text in general in actionbar in kivy?
I am new in kivy so i will be happy for any help.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
kv=Builder.load_string("""
GridLayout:
cols:1
size: root.width, root.height
ActionBar:
ActionView:
minimum_width: root.width
use_separator: True
ActionPrevious:
app_icon:""
title:"Hey"
with_previous: False
ActionOverflow:
ActionLabel:
text: "centered text"
minimum_width:300
ActionLabel:
text: "time"
""")
class ButtonsApp(App):
def build(self):
return kv
if __name__ == "__main__":
ButtonsApp().run()

kvlang : Builder.load_string issue

I was just trying to make a small hello world program as given below. Why nothing gets displayed.
# File: main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.base import runTouchApp
KV = '''
# File: clock.kv
<aClock#BoxLayout>:
orientation: 'vertical'
Label:
color: 1,0,1,1
text: '00:00:00'
<myClock> :
aClock:
'''
class myClock(App):
pass
if __name__ == '__main__':
Builder.load_string(KV)
myClock().run()
from kivy.app import App
from kivy.lang import Builder
KV = '''
<AClock#BoxLayout>:
orientation: 'vertical'
Label:
color: 1,0,1,1
text: '00:00:00'
AClock: # This is going to be the return value of Builder.load_string()
'''
class MyClock(App):
def build(self):
return Builder.load_string(KV)
if __name__ == '__main__':
MyClock().run()
App is not a widget, so you can't do this:
<myClock> :
aClock:
And in Kivy, PEP8 is constraint rather than style. All widgtes' class name must starts with upper case. So aClock must be AClock.
And you should implement build() and make it return a widget. (There is a case that build() doesn't have to return a widget, though.)
separating into two files
# myclock.kv
<AClock#BoxLayout>:
orientation: 'vertical'
Label:
color: 1,0,1,1
text: '00:00:00'
AClock:
# main.py
from kivy.app import App
class MyClock(App):
pass
if __name__ == '__main__':
MyClock().run()

How to create simple Kivy app (form with field name)

How to create simple Kivy app?
If user type text into field "Name" using keyboard like on android
phone, this name is display
I need this to learn
Here's as simple an example as i can figure out.
Here's the KVLANG code.
<LblTxt#BoxLayout>:
orientation: 'horizontal'
lblTxtIn: 'default'
theTxt: iAmTxt
Label:
text: root.lblTxtIn
TextInput:
id: iAmTxt
text: 'txt'
<MyLayout#BoxLayout>:
orientation: 'vertical'
LblTxt:
id: lt0
lblTxtIn: 'LblTxtInput0'
LblTxt:
id: lt1
lblTxtIn: 'LblTxtInput1'
LblTxt:
id: lt2
lblTxtIn: 'LblTxtInput2'
Button:
text: 'print LblTxtInput [0, 1, 2]'
on_release: print lt0.theTxt.text, lt1.theTxt.text, lt2.theTxt.text
MyLayout
Here's the Python code.
import kivy
kivy.require('1.8.0') # replace with your current kivy version !
from kivy.app import App
from kivy.lang import Builder
from kivy.config import Config
from kivy.core.window import Window
Window.size = (400,130)
from kivy.uix.boxlayout import BoxLayout
class LblTxt(BoxLayout):
from kivy.properties import ObjectProperty
theTxt = ObjectProperty(None)
class MyApp(App):
def build(self):
self.root = Builder.load_file('simpleForm.kv')
return self.root
if __name__ == '__main__':
MyApp().run()
Here's a run screenshot. It will print a b c to the command line when the 'print LblTxtInput [0, 1, 2]' button is released.
I hope this helps you out.

Resources