KivyMD without using kv file - python

I'm trying to make an expense tracker app using KivyMD. I have built it already using kivy but it's design is awful, then i found out KivyMD and now i want to tweak the app using KivyMD but i want to do it without using a kv file because my app has a lot of nested if statements which are too complex to write in the kv file. Anyway, i'm trying to test KivyMD but running into this nasty ValueError
ValueError: KivyMD: App object must be initialized before loading root widget. See https://github.com/kivymd/KivyMD/wiki/Modules-Material-App#exceptions and idk how to fix it without using a kv file. This question is asked plenty times but every answer uses a kv file. Can someone please help me understand this error and tackle it without kv. Thank you... Here is some code
from kivymd.app import MDApp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.app import App
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.stacklayout import MDStackLayout
from kivymd.uix.button import MDRaisedButton, MDRectangleFlatButton
from kivy.metrics import dp,sp
from kivymd.uix.screen import MDScreen
from kivy.uix.textinput import TextInput
from kivymd.uix.textfield import MDTextField
from kivy.uix.screenmanager import ScreenManager
import re
#ALL SCREENS
class MainScreen(MDScreen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
box = MDBoxLayout(orientation="vertical")
b = MDRaisedButton(text="Content",size_hint = (1,0.5))
box.add_widget(b)
t = MDTextField(size_hint=(1,0.5))
box.add_widget(t)
self.add_widget(box)
#ScreenManager
sm = ScreenManager()
sm.add_widget(MainScreen(name="main_screen"))
class MyApp(MDApp):
def build(self):
self.theme_cls.primary_palette = "DeepOrange"
self.theme_cls.accent_palette = "Lime"
return MainScreen()
if __name__ == "__main__":
MyApp().run()
works perfectly fine when i remove the screenmanager and just return the MainScreen.
Any help or guidance is highly appreciated.

Related

Kivy not loading video

I'm using the following code using kivy, trying to load a video. I created a new file that didn't have all the extra things I was doing, as to eliminate all the possible complications. I'm new to stack overflow, so if I've done something wrong don't judge...The video is in the same file, and I've tried everything I found online about these kind of errors, I've also installed pillow and ffpyplayer. The error I receive is [ERROR ] [Image ] Error loading <ironman.mp4>
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.video import Video
from kivy.uix.videoplayer import VideoPlayer
class MyApp(App):
def build(self):
video = Video(source='ironman.mp4')
video.state = "play"
video.options = {'eos': 'loop'}
video.allow_stretch = True
video.loaded = True
return video
if __name__ == "__main__":
MyApp().run()
I had the same problem but with Image. Install pillow 8.4.0.

Image not showing when created from a thread kivy/kivymd

I'm working on an app, and I need the images to display independently at a specific timing. I have set up a thread using python's stock threading module, it runs and works normally instead of the image it displays a black square. Does anyone know how to fix it?
Here is my code to reproduce the issue:
import threading
from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
class TestApp(App):
def build(self):
self.fl = FloatLayout()
self.fl.add_widget(Button(text="show image", on_press=self.start_thread))
return self.fl
def insertfunc(self):
self.fl.add_widget(Image(source="HeartIcon.png"))
def start_thread(self, instance):
threading.Thread(target=self.insertfunc).start()
TestApp().run()
Any help will be appreciated!
The add_widget() must be done on the main thread. I assume that you are using threading because you have additional things to do on the Thread aside from just the add_widget(). Based on that assumption, here is a modified version of your code that does what I think you want:
import threading
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
class TestApp(App):
def build(self):
self.fl = FloatLayout()
self.fl.add_widget(Button(text="show image", on_press=self.start_thread))
return self.fl
def insert_image(self, dt):
self.fl.add_widget(Image(source="HeartIcon.png"))
def insertfunc(self):
# do some calculations here
Clock.schedule_once(self.insert_image)
def start_thread(self, instance):
threading.Thread(target=self.insertfunc).start()
TestApp().run()
If you are not doing anything else in the new thread, then you don't actually need another thread. The start_thread() method can just do the:
self.fl.add_widget(Image(source="HeartIcon.png"))

kivy unable to load image

Kivy is not loading an image for me, its showing '[image][error] error reading file x.png'
My python code (in short) is:
from kivy.core.window import Window
from kivy.properties import NumericProperty
from kivy.properties import ObjectProperty
from kivy.properties import StringProperty
from kivy.uix.floatlayout import FloatLayout
from kivymd.app import MDApp
from kivymd.theming import ThemeManager
from kivymd.uix.snackbar import Snackbar
import requests
class Home(FloatLayout):
pass
class MainApp(MDApp):
def __init__(self,**kwargs):
super().__init__(**kwargs)
self.theme_cls = ThemeManager()
self.theme_cls.theme_style = "Light"
self.theme_cls.primary_palette = ('LightBlue')
Window.size = (400,600)
Kivy file (again part that matters) is:
MDBottomNavigation:
MDBottomNavigationItem:
text:'Home'
name: 'Home'
Home:
Image:
source:'khatam.png'
Image:
source: 'togeather.png'
I have pip installed Kivy with all its dependencies(including GStreamer) and have OpenCV. Also, I am using Pycharm. The rest of the code is working just fine only this part is bugged.
I am relatively new. Thanks in advance.

Unable to use ColorWheel without loading kv (AttributeError)

Can't understand why I get
AttributeError: 'ColorWheel' object has no attribute 'sv_s'
When I run
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.colorpicker import ColorWheel
from kivy.uix.boxlayout import BoxLayout
class MainApp(App):
def build(self):
box = BoxLayout()
box.add_widget(ColorWheel())
self.root = box
MainApp().run()
and I haven't any errors when use kv, for example:
from kivy.app import App
from kivy.lang import Builder
KV = '''
BoxLayout
ColorWheel
'''
class MainApp(App):
def build(self):
self.root = Builder.load_string(KV)
MainApp().run()
What did I miss?
You missed the warning in the ColorPicker documentation. That is a bug in the ColorWheel code. You should report it as a bug at Kivy Issues.

Issues with accessing information declared in different modules in kivy

I've got a python file(root.py) and another python file(button.py). When I define a button with an attribute (such as size_hint:0.1,1) in button.py using the kv language, root.py doesnt seem to be able to access that information.
When I define the same information using python in button.py, root.py seems to be able to access it.
ROOT.PY
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang.builder import Builder
from buttons import *
Builder.load_string("""
<Root>:
ButtonBar:
""")
class BtnBar(ButtonBar):
print(self.size_hint) # prints [1,1] instead of [0.1,1]
class Root(FloatLayout):
pass
class AppDev(App):
def build(self):
return Root()
BUTTON.PY
from kivy.uix.floatlayout import FloatLayout
from kivy.lang.builder import Builder
Builder.load_string("""
<ButtonBar>:
size_hint: 0.1,1
""")
class ButtonBar(FloatLayout):
pass
Root.py should be able to access any information I declare in button.py's Builder.load_string
After the object is instantiated, the right data will be accessable. You can use clock to make sure you get it after instantiation.
Also in your kv string, you probably want BtnBar instead of ButtonBar
Here is your root.py rewritten to do this.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang.builder import Builder
from kivy.clock import Clock
from buttons import *
Builder.load_string("""
<Root>:
BtnBar: # corrected to BtnBar
""")
class BtnBar(ButtonBar):
def __init__(self, **kwargs):
super(BtnBar, self).__init__(**kwargs)
Clock.schedule_once(self.get_data)
def get_data(self, dt):
print(self.size_hint) # prints on second frame
class Root(FloatLayout):
pass
class AppDev(App):
def build(self):
return Root()
AppDev().run()

Categories