How to use MDNavigationRail + MDNavigationRailItem without KV language - python

How can I create MDNavigationRail without KV language? I tried this code but I get a lot of errors.
class MyApp(MDApp):
def build(self):
boxlayout1 = MDBoxLayout(orientation = "vertical")
toolbar = MDToolbar(title = "Hello")
boxlayout1.add_widget(toolbar)
boxlayout2 = MDBoxLayout()
boxlayout1.add_widget(boxlayout2)
from kivymd.uix.navigationrail import MDNavigationRail, MDNavigationRailItem
navigationrail = MDNavigationRail()
navigationrail.add_widget(MDNavigationRailItem(icon="access-point"))
boxlayout2.add_widget(navigationrail)
return boxlayout1
root = MyApp()
root.run()

You have to pass your object navigationrail as an argument of MDNavigationRailItem.
from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.toolbar import MDToolbar
from kivy.utils import get_color_from_hex
class MyApp(MDApp):
def build(self):
boxlayout1 = MDBoxLayout(orientation = "vertical")
toolbar = MDToolbar(title = "Hello")
boxlayout1.add_widget(toolbar)
boxlayout2 = MDBoxLayout()
boxlayout1.add_widget(boxlayout2)
from kivymd.uix.navigationrail import MDNavigationRail, MDNavigationRailItem
navigationrail = MDNavigationRail(
md_bg_color = get_color_from_hex("#344954"),
# color_normal = get_color_from_hex("#718089"), #crash the app when clicking on an item, don't understand why...
color_active = get_color_from_hex("#f3ab44"),
visible = "Persistent")
for i in range(3):
item = MDNavigationRailItem(navigation_rail = navigationrail, text="item%d" %(i+1))
navigationrail.add_widget(item)
boxlayout2.add_widget(navigationrail)
return boxlayout1
root = MyApp()
root.run()

Related

How to display all returned photos on a kivy app using python

I am making a project involving looking up images. I decided to use kivy, creating a system where you can input a name of a folder (located in a specific directory) into a search bar, and it will return all images inside said folder tagged '.jpg'. I am stuck with updating the window to display these images, and I can't find anything online which helps.
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.screenmanager import Screen
from kivymd.app import MDApp
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.core.window import Window
import glob
import os
os.chdir(r'directory/of/imagefolders')
class functions:
def lookup(name):
root = f'imagefolder'
for root, subdirs, files in os.walk(f'imagefolder'):
for d in subdirs:
if d == name:
print(d)
path = f'imagefolder/'+d
print(path)
return path
def load_images(f):
facefile = []
for images in glob.glob(f + '\*.jpg'):
facefile.append(images)
print(facefile)
return facefile
class MainApp(MDApp):
def build(self):
Window.clearcolor = (1,1,1,1)
layout = GridLayout(cols=2, row_force_default=True, row_default_height=40,
spacing=10, padding=20)
self.val = TextInput(text="Enter name")
submit = Button(text='Submit', on_press=self.submit)
layout.add_widget(self.val)
layout.add_widget(submit)
return layout
def submit(self,obj):
print(self.val.text)
layout2 = GridLayout(cols=2, row_force_default=True, row_default_height=40,
spacing=10, padding=20)
name = self.val.text
f = functions.lookup(name)
print(f)
facefile = functions.load_images(f)
x = len(facefile)
print(x)
for i in range(0, x):
print(facefile[i])
self.img = Image(source=facefile[i])
self.img.size_hint_x = 1
self.img.size_hint_y = 1
self.img.pos = (200,100)
self.img.opacity = 1
layout2.add_widget(self.img)
return layout2
MainApp().run()
This is what I tried, but the window doesn't update. All images are returned (demonstrated by print(facefile[i])), but nothing happens with them. Any help would be massively appreciated
Your submit() method is creating Image widgets and adding them to a newly created layout2, You are returning that new layout2 from that method, but that does not add it to your GUI. Try replacing:
layout2.add_widget(self.img)
with:
self.root.add_widget(self.img)

Python, If statement error with variables says not defined

I am having a problem when I am trying to use the if statement in python.
I cannot see if a variable is true or false because it says the variable is not defined but I defined it in a method.
I am using kivy and kivyMD as well, just in case people were wondering why some of the code was there.
from kivymd.app import MDApp
from kivymd.uix.screen import Screen
from kivymd.uix.button import MDRectangleFlatButton, MDRoundFlatButton
from kivymd.uix.textfield import MDTextField
from kivy.lang import Builder
from kivymd.uix.menu import MDDropdownMenu
class DemoApp(MDApp):
def show_data(self):
inputFahrenheit = self.root.ids.fahrenheit.text
if fahrenheit1 is True:
Celsius_Half = float(inputFahrenheit) - 32
Celsius_Before_Round = Celsius_Half * 5/9
Celsius = round(Celsius_Before_Round , 1)
def convert1F(self):
fahrenheit1 = True
celsius1 = False
def convert1C(self):
fahrenheit1 = False
celsius1 = True
def convert2F(self):
fahrenheit2 = True
celsius2 = False
def convert2C(self):
fahrenheit2 = False
celsius2 = True
def on_start(self):
self.theme_cls.primary_palette = "Green"
self.theme_cls.primary_hue = "A700"
self.theme_cls.theme_style = "Light"
def build(self):
kv = Builder.load_file("test.kv")
screen = Screen()
return kv
DemoApp().run()
The if statement is the problem there is a copy of the problem:
"fahrenheit1" is not defined
In order for fahrenheit1 to be defined, you need to declare it as a class attribute.
Either define in in the class __init__ or as a static attribute at the top of the class, outside of any method) as fahrenheit1: bool = <your_defualt_value>
Because there is no defined variable called fahrenheit1.
Fix that first

Can buildozer made android apps use glob and os modules?

So at the moment in try to figure out why is my small player i wrote in kivy crashes on start. It says build successful and all modules seem to work separately in other tests (except for glob) but this one is pure python as far as i know.
here's my code
import glob
import kivy
from kivy.core.audio import SoundLoader
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.graphics import Rectangle
from kivy.graphics import Color
from kivy.uix.widget import Widget
import random
import os
from android.permissions import request_permissions, Permission
request_permissions([Permission.READ_EXTERNAL_STORAGE])
class PageI(GridLayout):
def __init__(self,**kwargs):
super().__init__( **kwargs)
self.cols = 3
self.state = False
self.music = glob.glob('/Phone/reMusic/*.mp3')#glob.glob('music\\*.mp3')
self.currname = self.music[0]
self.lasttime = 0
self.currsound = SoundLoader.load(self.currname)
fillclr = (round(random.random(),4), round(random.random(),4), round(random.random(),4), 1)
SR = Button(text='forward')
SR.bind(on_press=self.switchoR)
self.add_widget(SR)
placeholder = Label()
self.add_widget(placeholder)
SL = Button(text='backward')
SL.bind(on_press=self.switchoL)
self.add_widget(SL)
placeholder = Label()
self.add_widget(placeholder)
self.PP = Button(on_press = self.switchostate)
self.add_widget(self.PP)
placeholder = Label()
self.add_widget(placeholder)
placeholder = Label()
self.add_widget(placeholder)
self.showcase = Label(text=self.currname)
self.add_widget(self.showcase)
def PPcontrol(self):
if not self.currsound.state == 'play':
self.currsound.play()
self.currsound.seek(self.lasttime)
else:
self.lasttime = int(self.currsound.get_pos())
self.currsound.stop()
def switchostate(self,instance):
self.PPcontrol()
def showsitch(self):
self.showcase.text = self.currname
def switchoR(self,instance):
instance.background_color = (round(random.random(),4), round(random.random(),4), round(random.random(),4), 1)
ind = self.music.index(self.currname)
if ind+1 > len(self.music)-1:
self.currname = self.music[ind - len(self.music) + 1]
else:
self.currname = self.music[ind + 1]
self.lasttime = 0
self.currsound.stop()
self.currsound = SoundLoader.load(self.currname)
self.currsound.play()
self.showsitch()
def switchoL(self,instance):
instance.background_color = (round(random.random(),4), round(random.random(),4), round(random.random(),4), 1)
ind = self.music.index(self.currname)
if ind - 1 < 0:
self.currname = self.music[len(self.music) - 2]
else:
self.currname = self.music[ind - 1]
self.lasttime = 0
self.currsound.stop()
self.currsound = SoundLoader.load(self.currname)
self.currsound.play()
self.showsitch()
class Applet(App):
def build(self):
self.dircheck()
self.p = PageI()
return self.p
def dircheck(self):
try:
if not os.path.exists(os.path.join(os.getcwd(),'\\music')):
os.mkdir(os.path.join(os.getcwd(),'\\music'))
except: None
if __name__ == '__main__':
apper = Applet()
apper.run()
ik its quite messy but as you can see i tried both creating directories and accessing premade one.
and well, im not sure why it dies, i made sure it had all perms in spec file as well.

python/kivy: need function clock() but crash because of recursion

I'm new to python and kivy and try to learn from code snippets and trial and error. But now I'm stuck.
To displays weather and garbage information on an raspberry I used kivy.
To grab these information I use the function URLRequest. This function needs the clock-function
while not req.is_finished:
Clock.tick()
return req.result
So the program works, displays the infos but crashed regularly after some 20 minutes or so wit hthe error "RuntimeError: maximum recursion depth exceeded
But I don't understand how I can get rid of the recursion by still getting things working :(
Here's mor of the code in context. Can anyone help?
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.network.urlrequest import UrlRequest
from time import gmtime, strftime, localtime, sleep
class garbage:
def garbage_text(garbage):
req = UrlRequest('http://192.168.1.1:8083/fhem?cmd={ReadingsVal(%22ABFALL%22,%22next_text%22,0)}&XHR=1&fwcsrf=password')
while not req.is_finished:
Clock.tick()
return req.result
class weather:
def weather_db1(weather):
req = UrlRequest('http://192.168.1.1:8083/fhem?cmd={ReadingsVal(%22netatmo_M01_00_00_3f_1d_1a%22,%22temperature%22,0)}&XHR=1&fwcsrf=password')
while not req.is_finished:
Clock.tick()
return req.result
class MyBox(BoxLayout):
def update(self, *args):
uweather = weather()
aktw = uweather.weather_db1()
ggarbage = garbage()
garbagetext = ggarbage.garbage_text()
self.ids.temp_ist.text = str(aktw)
self.ids.uhrzeit_top.text = strftime("%H:%M", localtime())
self.ids.datum_top.text = strftime("%d.%m.%Y", localtime())
self.ids.garbage_std.text = garbagetext+" rausstellen "
class ControlApp(App):
def build(self):
actclock = MyBox()
Clock.schedule_interval(actclock.update, 1)
return actclock
if __name__ == "__main__":
ControlApp().run()
Here is a modified version of your code that uses callbacks instead of looping or waiting:
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock, mainthread
from kivy.uix.boxlayout import BoxLayout
from kivy.network.urlrequest import UrlRequest
from time import strftime, localtime
class garbage:
def garbage_text(self, *args):
req = UrlRequest('http://192.168.1.1:8083/fhem?cmd={ReadingsVal(%22netatmo_M01_00_00_3f_1d_1a%22,%22temperature%22,0)}&XHR=1&fwcsrf=password',
on_success=self.update, on_failure=self.failure)
#mainthread
def update(self, req, result):
# update the GUI
garbage_std = App.get_running_app().root.ids.garbage_std
garbage_std.text = str(result)+" rausstellen "
# schedule the next update
Clock.schedule_once(self.garbage_text, 1)
def failure(self):
print('garbage failed')
class weather:
def weather_db1(self, *args):
req = UrlRequest('http://192.168.1.1:8083/fhem?cmd={ReadingsVal(%22netatmo_M01_00_00_3f_1d_1a%22,%22temperature%22,0)}&XHR=1&fwcsrf=password',
on_success=self.update, on_failure=self.failure)
#mainthread
def update(self, req, result):
# update the GUI
temp_ist = App.get_running_app().root.ids.temp_ist
temp_ist.text = str(result)
# schedule the next update
Clock.schedule_once(self.weather_db1, 1)
def failure(self):
print('weather failed')
class MyBox(BoxLayout):
def update(self, *args):
self.ids.uhrzeit_top.text = strftime("%H:%M", localtime())
self.ids.datum_top.text = strftime("%d.%m.%Y", localtime())
class ControlApp(App):
def build(self):
actclock = MyBox()
self.weather = weather()
self.garbage = garbage()
# start the time updates
Clock.schedule_interval(actclock.update, 1)
# start the other updates
Clock.schedule_once(self.weather_update)
Clock.schedule_once(self.garbage_update)
return actclock
def weather_update(self, dt):
self.weather.weather_db1()
def garbage_update(self, dt):
self.garbage.garbage_text()
Builder.load_string('''
<MyBox>:
orientation: 'vertical'
Label:
id: temp_ist
Label:
id: uhrzeit_top
Label:
id: datum_top
Label:
id: garbage_std
''')
if __name__ == "__main__":
ControlApp().run()

How to output text and delete text with buttons

I'm trying to output text from button presses and add it to a textbox each time it's pressed as well as delete the text when the delete button is pressed - in normal python.
I've been trying to use kivy.uix.textinput, but I'm not sure on how to output the value from the buttons as well as delete it.
This is what I've done so far.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class CodeScreen(Screen):
def __init__(self):
super(CodeScreen, self).__init__(name='code_screen')
main_grid_lay = GridLayout(cols=2,cols_minimum={0:640, 1:175})
self.add_widget(main_grid_lay)
#Code ouput display
display_code = TextInput(text='Code!', readonly = True, id=output)
main_grid_lay.add_widget(display_code)
#Options Buttons
box_lay = BoxLayout(orientation='vertical')
main_grid_lay.add_widget(box_lay)
delete_button = Button(
text='Delete',
size_hint_x= None,
width=160,
id='' #unsure on how to delete
)
box_lay.add_widget(delete_button)
base_left = Button(
text='Base Left',
#on_release= b_left(),
#id='left',
)
base_right = Button(
text='Base Right',
on_release=self.degree_popup,
#on_release= b_right(),
)
#b_left = self.ids.output.text='left'
#b_left = self.ids.output.text='right'
box_lay.add_widget(base_left)
box_lay.add_widget(base_right)
# The app class
class MyMain(App):
def build(self):
return CodeScreen()
# Runs the App
if __name__ == '__main__':
MyMain().run()
It currently sends an error and is probably because of the ids. Not fully sure how ids work without using kv language. Any help is appreciated.
The id only makes sense in .kv, in python they are useless. In this case the solution is to access the objects in the methods connected to on_release but for this they must be class attributes.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class CodeScreen(Screen):
def __init__(self):
super(CodeScreen, self).__init__(name="code_screen")
self.display_code = TextInput(text="Code!", readonly=True)
self.delete_button = Button(
text="Delete", size_hint_x=None, width=160, on_release=self.delete_clicked
)
self.base_left = Button(text="Base Left", on_release=self.left_clicked)
self.base_right = Button(text="Base Right", on_release=self.right_clicked)
main_grid_lay = GridLayout(cols=2, cols_minimum={0: 640, 1: 175})
main_grid_lay.add_widget(self.display_code)
self.add_widget(main_grid_lay)
box_lay = BoxLayout(orientation="vertical")
box_lay.add_widget(self.delete_button)
main_grid_lay.add_widget(box_lay)
box_lay.add_widget(self.base_left)
box_lay.add_widget(self.base_right)
def delete_clicked(self, instance):
self.display_code.text = ""
def left_clicked(self, instance):
self.display_code.text += "left"
def right_clicked(self, instance):
self.display_code.text += "right"
# The app class
class MyMain(App):
def build(self):
return CodeScreen()
# Runs the App
if __name__ == "__main__":
MyMain().run()

Categories

Resources