i don't understand what did i do wrong, as for what i know, isn't it supposed to send a widget to the next box when inside BoxLayout? Plus i have been wrecking my brain trying to figure out on how to make this scrollable properly. It just stacks and i can see only half of it when not scrolling.
Here's my watered down code
main.py
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.checkbox import CheckBox
from kivymd.uix.boxlayout import MDBoxLayout
from configparser import ConfigParser
from kivymd.uix.label import MDLabel
cfg = ConfigParser()
cfg.read("app/data/cfg.ini")
class CfgScreen(Screen):
def __init__(self, **kwargs):
super(CfgScreen, self).__init__(**kwargs)
def on_enter(self, *args):
self.init_cfg_rm()
def init_cfg_rm(self):
roles = list(cfg.items("role_permission"))
for i in roles:
if i[0] != "dev":
boxlayout = MDBoxLayout(
orientation="horizontal",
)
label = MDLabel(
text=i[0].capitalize(),
halign="left",
pos_hint={'x': 0.5, 'center_y': 0.5},
)
boxlayout.add_widget(label)
pos_radio_btn = CheckBox(
pos_hint={'x': 0.5, 'center_y': 0.5},
)
db_radio_btn = CheckBox(
pos_hint={'x': 0.5, 'center_y': 0.5},
)
ua_radio_btn = CheckBox(
pos_hint={'x': 0.5, 'center_y': 0.5},
)
rm_radio_btn = CheckBox(
pos_hint={'x': 0.5, 'center_y': 0.5},
)
boxlayout.add_widget(pos_radio_btn)
boxlayout.add_widget(db_radio_btn)
boxlayout.add_widget(ua_radio_btn)
boxlayout.add_widget(rm_radio_btn)
self.ids.cfg_rm.add_widget(boxlayout)
class testApp(MDApp):
def build(self):
sm = ScreenManager()
sm.add_widget(CfgScreen(name="cfg"))
return sm
if __name__ == "__main__":
testApp().run()
main.kv
CfgScreen:
<CfgScreen>:
name: "cfg"
cfg_rm: cfg_rm
canvas.before:
Color:
rgba: 242/255, 242/255, 242/255, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: "vertical"
MDBoxLayout:
orientation: "horizontal"
MDNavigationRail:
anchor: "center"
type: "unselected"
MDNavigationRailItem:
icon: "account-details-outline"
MDNavigationRailItem:
icon: "account-card-outline"
MDNavigationRailItem:
icon: "account-tie-hat-outline"
MDNavigationRailItem:
icon: "database-settings-outline"
ScreenManager:
id: sm_cfg
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
Screen:
name: "cfg_rm"
FloatLayout:
MDLabel:
text: "Role Management"
halign: "left"
pos_hint:{'x': 0.05, 'center_y': 0.9}
font_style: "H5"
MDScrollView:
size_hint: 0.9, 0.6
pos_hint:{'x': 0.05, 'center_y': 0.55}
MDBoxLayout:
orientation: "vertical"
size_hint_y: None
height: self.minimum_height
MDBoxLayout:
orientation: "horizontal"
size_hint: 1, 0.1
MDLabel:
text: "Roles"
halign: "left"
MDLabel:
text: "P.O.S"
halign: "center"
MDLabel:
text: "Database"
halign: "center"
MDBoxLayout:
orientation: "vertical"
MDLabel:
text: "Settings"
halign: "center"
pos_hint:{'center_y': 0.85}
MDBoxLayout:
orientation: "horizontal"
MDLabel:
text: "ser"
halign: "center"
pos_hint:{'center_y': 0.15}
MDLabel:
text: "Role"
halign: "center"
pos_hint:{'center_y': 0.15}
MDBoxLayout:
id: cfg_rm
orientation: "vertical"
size_hint: 1, 0.9
and my cfg.ini
[role_permission]
cashier = ["cfg_my_account", "pos"]
cashier1 = ["cfg_my_account", "pos"]
cashier2 = ["cfg_my_account", "pos"]
cashier3 = ["cfg_my_account", "pos"]
cashier4 = ["cfg_my_account", "pos"]
cashier5 = ["cfg_my_account", "pos"]
cashier6 = ["cfg_my_account", "pos"]
cashier7 = ["cfg_my_account", "pos"]
cashier8 = ["cfg_my_account", "pos"]
cashier9 = ["cfg_my_account", "pos"]
cashier10 = ["cfg_my_account", "pos"]
Screenshot:
So please, if you can help me fix this.
Related
I created an app with a NavigationDrawer and everything work correctely, but the problem is to return to the first screen. I want to go back to the first screen (the Screen with name: 'Screen_*principal') when I click in the arrow-left in the MDTopAppBar in Login_*screen but nothing that I did worked.
KV file:
#: import RiseInTransition kivy.uix.screenmanager.RiseInTransition
#: import SlideTransition kivy.uix.screenmanager.SlideTransition
<CustomizeScreen#MDBoxLayout>
orientation: 'vertical'
text: ''
padding: 100
MDLabel:
text: root.text
halign: 'center'
pos_hint: {'center_x': .5}
MDFillRoundFlatButton:
text: 'Regresar'
pos_hint: {'center_x': .5}
on_release:
app.root.current = 'screen_principal'
app.root.transition = SlideTransition(direction= 'left' )
<DrawerClickableItem#MDNavigationDrawerItem>
focus_color: "#e7e4c0"
text_color: "#4a4939"
icon_color: "#4a4939"
ripple_color: "#c5bdd2"
selected_color: "#0c6c4d"
<DrawerLabelItem#MDNavigationDrawerItem>
text_color: "#4a4939"
icon_color: "#4a4939"
focus_behavior: False
selected_color: "#4a4939"
_no_ripple_effect: True
<Screen_principal>:
MDNavigationLayout:
MDScreen:
MDTopAppBar:
title: "Navigation Drawer"
elevation: 4
pos_hint: {"top": 1}
md_bg_color: "#e7e4c0"
specific_text_color: "#4a4939"
left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
MDNavigationDrawer:
id: nav_drawer
radius: (0, 16, 16, 0)
MDNavigationDrawerMenu:
MDNavigationDrawerHeader:
title: "LOCATE YOU"
source: "icono.png"
spacing: "4dp"
padding: "12dp", 0, 0, "56dp"
DrawerClickableItem:
icon: "login"
text_right_color: "#4a4939"
text: "Iniciar Sesion"
on_press:
root.manager.current = "Login_screen"
DrawerClickableItem:
icon: "new-box"
text: "Registrarse"
text_right_color: "#4a4939"
on_press:
root.current = "screen_register"
DrawerClickableItem:
icon: "information-outline"
text: "Informacion"
text_right_color: "#4a4939"
on_press:
root.current = "scr1"
DrawerClickableItem:
icon: "microsoft-teams"
text: "Equipo"
text_right_color: "#4a4939"
on_press:
root.current = "scr1"
<Login_screen>:
MDBoxLayout:
orientation: 'vertical'
MDTopAppBar:
title: "Login"
md_bg_color: "#e7e4c0"
left_action_items: [["arrow-left", lambda *args : setattr(screen_manager, "current", "Screen_principal")]]
MDBoxLayout:
orientation: 'vertical'
size_hint_y: 0.3
Image:
source: 'usuario.png'
pos_hint: {'center_x': 0.5}
MDLabel:
text: 'Iniciar Sesion'
halign: 'center'
color: '#FF5A1E'
font_size: '35dp'
bold: True
pos_hint: {'center_y': .5}
MDBoxLayout:
orientation: 'vertical'
size_hint_y: 0.3
spacing: '12dp'
MDTextField:
id: user
hint_text: "Nombre de usuario"
icon_right: "account"
font_size: '25dp'
icon_right_color: '#FF5A1E'
pos_hint: {'center_x': 0.5}
MDTextField:
id: password
password:True
icon_right: "key-variant"
font_size: '25dp'
icon_right_color: '#FF5A1E'
hint_text: "Contrasena"
pos_hint: {'center_x': 0.5}
MDLabel:
id: signal_login
text: ''
halign: 'center'
color: '#FF5A1E'
font_size: '15dp'
MDBoxLayout:
orientation: 'vertical'
size_hint_y:0.4
spacing: '25dp'
MDFillRoundFlatButton:
id: bt_ingresar
text: 'Ingresar'
pos_hint: {'center_x':0.5}
on_release:
x = app.login_data()
root.current = 'open_screen' if x == True else None
MDFillRoundFlatButton:
md_bg_color: 1,1,1,1
Python file:
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
from kivy.core.window import Window
import requests
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.properties import BooleanProperty, ObjectProperty
Builder.load_file('diseno.kv')
class Screen_principal(Screen):
pass
class Login_screen(Screen):
pass
class TestApp(MDApp):
def build(self):
# Create the screen manager
sm = ScreenManager()
sm.add_widget(Screen_principal(name='Screen_principal'))
sm.add_widget(Login_screen(name='Login_screen'))
return sm
if __name__ == '__main__':
TestApp().run()
I tried a lot of things but nothing work, if someone could fix it I would be very grateful
In your kv, change:
left_action_items: [["arrow-left", lambda *args : setattr(screen_manager, "current", "Screen_principal")]]
to:
left_action_items: [["arrow-left", lambda *args : setattr(root.manager, "current", "Screen_principal")]]
This change accesses the ScreenManager by referencing root.manager, and the root in that context is the Login_screen.
I created this widget in a .kv file that inherits from MDCard:
<ElementCard#MDCard>:
radius: '10dp'
spacing: '10dp'
padding: '10dp'
image: ''
text: ''
sub_text: ''
orientation: 'vertical'
md_bg_color: 0.87, 0, 0.49
ripple_behavior: True # effect
on_release:
app.root.transition = RiseInTransition()
Image:
source: root.image
halign: 'center'
MDBoxLayout:
orientation: 'vertical'
md_bg_color: 'green'
MDLabel:
text: root.text
color: 'white'
halign: 'center'
MDLabel:
text: root.sub_text
halign: 'center'
and I use it:
<ui>:
...
ElementCard:
text: 'IA'
sub_text: 'Inteligencia artificial'
image: 'images/image1.jpg'
on_release:
root.current = 'screen1'
...
The problem is that the ElementCard widget doesn't show the content:
ElementCard is the purple block and it covers all its content.
When I set the transparency in 0.5 the program looks like this:
50% transparency
The versions are these:
Kivy==2.1.0
kivymd==1.1.1
I've tried rebooting the machine, restarting the virtual environment, reinstalling kivy and kivymd but nothing works.
I think the problem is the inheritance because when I use directly the MDCard like in this code:
MDCard:
radius: '10dp'
spacing: '10dp'
padding: '10dp'
orientation: 'vertical'
md_bg_color: 0.87, 0, 0.49,0.6
ripple_behavior: True # effect
on_release:
app.root.transition = RiseInTransition()
Image:
source: 'images/image1.jpg'
halign: 'center'
MDBoxLayout:
orientation: 'vertical'
md_bg_color: 'green'
MDLabel:
text: 'IA'.
color: 'white'
halign: 'center'
MDLabel:
text: 'Inteligencia artificial'
halign: 'center'
With the last code the program works fine:
MDCard works normally.
main.py full code:
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
from kivymd.app import MDApp
class Ui(ScreenManager):
pass
class MainApp(MDApp):
def build(self):
self.theme_cls.theme_style ='Dark'
self.theme_cls.primary_palette ='Teal'
Builder.load_file("design.kv")
return Ui()
def change_style(self, checked, value):
if value:
self.theme_cls.theme_style ='Dark'
pass
else:
self.theme_cls.theme_style ='Light'
pass
if __name__ == "__main__":
MainApp().run()
design.kv full code:
#:kivy 2.1.0
#:import RiseInTransition kivy.uix.screenmanager.RiseInTransition
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
<CustomizeScreen#MDBoxLayout>:
orientation: 'vertical'
text: ''
padding: 100
MDLabel:
text: root.text
halign: 'center'
pos_hint:{'center_x': 0.5}
MDFillRoundFlatButton:
text: 'REGRESAR'
pos_hint: {'center_x': 0.5}
on_release:
app.root.current = 'screen_principal'
app.root.transition = SlideTransition(direction = 'left')
<ElementCard#MDCard>:
radius: '10dp'
spacing: '10dp'
padding: '10dp'
image: ''
text: ''
sub_text: ''
orientation: 'vertical'
md_bg_color: 0.87, 0, 0.49
ripple_behavior: True # effect
on_release:
app.root.transition = RiseInTransition()
Image:
source: root.image
halign: 'center'
MDBoxLayout:
orientation: 'vertical'
md_bg_color: 'green'
MDLabel:
text: root.text
color: 'white'
halign: 'center'
MDLabel:
text: root.sub_text
halign: 'center'
<ui>:
MDScreen:
name: 'screen_principal'
md_bg_color: "black"
MDBoxLayout:
orientation: "vertical"
MDBoxLayout:
size_hint: 1, 0.2 # x=1 ocupa todo, y=0.2 ocupa 20%
orientation: "horizontal"
padding: '10dp'
MDCard:
radius: '10dp'
padding: '10dp'
line_color: 1,0,1,1
MDLabel:
text: 'APLICACIÓN DE TECNOLOGÍA'
halign: 'center'
pos_hint: {'center_y': 0.5}
MDSwitch:
pos_hint: {'center_y': 0.5}
on_active:
app.change_style(*args)
MDGridLayout:
cols: 3
size_hint: 0.8, 0.8 # x=1 ocupa todo, y=0.8 ocupa 80%
pos_hint: {'center_x': 0.5}
padding: ['10dp','10dp','10dp','10dp']
spacing: '10dp'
ElementCard:
text: 'IA'
sub_text: 'Inteligencia artificial'
image: 'images/image1.jpg'
on_release:
root.current = 'screen1'
I commented this problem in the github kivyMD project, they marked as a bug and give me a couple of options to implement, link to github
Edit:
Thanks for pointing out my mistake with my link.
This is the first option:
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.card import MDCard
KV = """
<ElementCard>
MDLabel:
text: "HELLO WORLD"
MDScreen:
ElementCard:
size_hint: 0.5, 0.8
pos_hint: {"center_x": .5, "center_y": .5}
md_bg_color: 0.87, 0, 0.49, 1
"""
class ElementCard(MDCard):
pass
class MainApp(MDApp):
def build(self):
return Builder.load_string(KV)
MainApp().run()
and the 2nd:
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.card import MDCard
KV = """
<ElementCard#MDCard>
MDLabel:
text: "HELLO WORLD"
MDScreen:
ElementCard:
size_hint: 0.5, 0.8
pos_hint: {"center_x": .5, "center_y": .5}
md_bg_color: 0.87, 0, 0.49, 1
"""
class MainApp(MDApp):
def build(self):
return Builder.load_string(KV)
MainApp().run()
I guess that the kivymd developers will repair this bug in the future.
Iam trying to learn coding with Python and iam making an application that tracks session times from users using KivyMD. At the moment iam trying to display the total amount of time by fetching json data trough an api call from my database. I wrote a function to fetch and process the json data to calculate the total time. The function must fire automatically to show the data (variable:total_minutes) in the MDLabel time_label when the Mijn sessie Tab loads. This is where iam getting very confused.
I found the on_pre_enter function in Kivy which fires the function when the screen loads but it only works in the Screen Class and not in the Tabs Class. I have no idea how i can use the python variable in the Tabs class if i do the python logic in the Screen class. I have tried many things with Objectproperty and Stringproperty but none where succesfull. I think iam missing something bigger here.
I will post the code to make things more clearly when you will see the application for yourself. For safety reasons i replaced the api request function with a small function which produces the same outcome (float).
Many thanks in advance!
main.py file
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.tab import MDTabsBase
from kivymd.font_definitions import fonts
from kivymd.icon_definitions import md_icons
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.widget import Widget
from kivymd.uix.label import MDLabel
import requests
import json
from datetime import datetime
Window.size = (300, 500) # voor develop doeleinden mobielscherm
class Screen1(Screen):
pass
def on_pre_enter(self, *args):
def func(a, b):
total_minutes = a - b
return total_minutes
print(func(3000,1500))
class Screen2(Screen):
pass
class Screen3(Screen):
pass
class Screen4(Screen):
pass
class Tab_mijn_sessie(FloatLayout, MDTabsBase):
pass
class Tab_alarm(FloatLayout, MDTabsBase):
pass
class Tab_actieve_drinkers(FloatLayout, MDTabsBase):
pass
class Tab_score(FloatLayout, MDTabsBase):
pass
class Tab_achievments(FloatLayout, MDTabsBase):
pass
class Tab_historie(FloatLayout, MDTabsBase):
pass
class DemoApp(MDApp):
def build(self):
self.theme_cls.primary_palette = 'Red'
self.theme_cls.theme_style = 'Dark'
screen = Builder.load_file('demo_file.kv')
return screen
DemoApp().run()
demo_file.kv file
Screen:
NavigationLayout:
ScreenManager:
id:screen_manager
Screen1:
name: 'home_screen'
BoxLayout:
name: 'home_layout'
orientation: 'vertical'
MDToolbar:
title: 'Huidige sessie'
left_action_items: [['menu', lambda x: nav_drawer.set_state("open")]]
specific_text_color: 1,1,1,1
MDTabs:
id:home_tabs
tab_bar_height: '35dp'
text_color_active: 1,1,0,1
text_color_normal: 0,0,0,1
color_indicator: 0.95, 0.95, 0.1, 1
tab_indicator_anim: True
anim_duration: 0.2
tab_indicator_height: '3dp'
Tab_mijn_sessie:
text: 'Mijn sessie'
Tab_alarm:
text: 'Alarm'
Tab_actieve_drinkers:
text: 'Actieve drinkers'
MDToolbar:
id: bottom_toolbar_scr1
name: 'bottom_toolbar'
specific_text_color: 1,1,1,1
title: ' Sessie inactief..'
Screen2:
name: 'statistieken_screen'
BoxLayout:
name: 'statistieken_layout'
orientation: 'vertical'
MDToolbar:
title: 'Statistieken'
left_action_items: [['menu', lambda x: nav_drawer.set_state("open")]]
specific_text_color: 1,1,1,1
MDTabs:
id:home_tabs
tab_bar_height: '35dp'
text_color_active: 1,1,0,1
text_color_normal: 0,0,0,1
color_indicator: 0.95, 0.95, 0.1, 1
tab_indicator_anim: True
anim_duration: 0.2
tab_indicator_height: '3dp'
Tab_score:
text: 'Scorebord'
Tab_achievments:
text: 'Achievements'
Tab_historie:
text: 'Historie'
MDToolbar:
id: bottom_toolbar_scr2
name: 'bottom_toolbar'
specific_text_color: 1,1,1,1
title: ' Sessie inactief..'
Screen3:
name: 'logout_screen'
BoxLayout:
name: 'logout_layout'
orientation: 'vertical'
MDToolbar:
title: 'Uitloggen'
left_action_items: [['menu', lambda x: nav_drawer.set_state("open")]]
specific_text_color: 1,1,1,1
Widget:
Screen4:
name: 'profile_screen'
BoxLayout:
name: 'profile_layout'
orientation: 'vertical'
MDToolbar:
title: 'Profiel'
left_action_items: [['menu', lambda x: nav_drawer.set_state("open")]]
specific_text_color: 1,1,1,1
Widget:
MDToolbar:
id: bottom_toolbar_scr4
name: 'bottom_toolbar'
specific_text_color: 1,1,1,1
title: ' Sessie inactief..'
MDNavigationDrawer:
id:nav_drawer
BoxLayout:
orientation: 'vertical'
spacing: '8dp'
padding: '8dp'
Image:
source: 'avatar.jpg'
MDLabel:
text: ' Name'
front_style: 'Subtitle1'
size_hint_y: None
height: self.texture_size[1]
MDLabel:
text: ' email#hotmail.com'
front_style: 'Caption'
size_hint_y: None
height: self.texture_size[1]
ScrollView:
MDList:
OneLineIconListItem:
theme_text_color: 'Custom'
text_color: 244/255, 67/255, 54/255, 1
text: 'Huidige sessie'
on_press:
screen_manager.current = 'home_screen'
nav_drawer.set_state("close")
IconLeftWidget:
theme_text_color: 'Custom'
text_color: 0.95, 0.95, 0.1, 1
icon: 'beer'
on_press:
screen_manager.current = 'home_screen'
nav_drawer.set_state("close")
OneLineIconListItem:
theme_text_color: 'Custom'
text_color: 244/255, 67/255, 54/255, 1
text: 'Statistieken'
on_press:
screen_manager.current = 'statistieken_screen'
nav_drawer.set_state("close")
IconLeftWidget:
icon: 'history'
theme_text_color: 'Custom'
text_color: 0.95, 0.95, 0.1, 1
on_press:
screen_manager.current = 'historie_screen'
nav_drawer.set_state("close")
OneLineIconListItem:
theme_text_color: 'Custom'
text_color: 244/255, 67/255, 54/255, 1
text: 'Profiel'
on_press:
screen_manager.current = 'profile_screen'
nav_drawer.set_state("close")
IconLeftWidget:
icon: 'face-profile'
theme_text_color: 'Custom'
text_color: 0.95, 0.95, 0.1, 1
on_press:
screen_manager.current = 'profile_screen'
nav_drawer.set_state("close")
OneLineIconListItem:
theme_text_color: 'Custom'
text_color: 244/255, 67/255, 54/255, 1
text: 'Uitloggen'
on_press:
screen_manager.current = 'logout_screen'
nav_drawer.set_state("close")
IconLeftWidget:
icon: 'logout'
theme_text_color: 'Custom'
text_color: 0.95, 0.95, 0.1, 1
on_press:
screen_manager.current = 'logout_screen'
nav_drawer.set_state("close")
<Tab_mijn_sessie>:
MDLabel:
text: 'Total time'
font_style: 'H6'
halign: 'center'
pos_hint: {"center_x": .5, "center_y": .4}
MDLabel:
id : time_label
text: '(this has to display the total amount of time)'
font_style: 'Body2'
halign: 'center'
pos_hint: {"center_x": .5, "center_y": .3}
MDFlatButton:
theme_text_color: 'Custom'
text_color: 1,1,1,1
halign: 'center'
text:'Activate session'
user_font_size: "48sp"
pos_hint: {"center_x": .5, "center_y": .7}
on_press:
app.root.ids.bottom_toolbar_scr1.title = ' Sessie actief!'
app.root.ids.bottom_toolbar_scr1.specific_text_color = 0,1,0,1
app.root.ids.bottom_toolbar_scr2.title = ' Sessie actief!'
app.root.ids.bottom_toolbar_scr2.specific_text_color = 0,1,0,1
app.root.ids.bottom_toolbar_scr4.title = ' Sessie actief!'
app.root.ids.bottom_toolbar_scr4.specific_text_color = 0,1,0,1
<Tab_alarm>:
MDLabel:
halign: 'center'
text:'Alarm'
user_font_size: "48sp"
pos_hint: {"center_x": .5, "center_y": .5}
<Tab_actieve_drinkers>:
MDLabel:
halign: 'center'
text:'Actieve drinkers'
user_font_size: "48sp"
pos_hint: {"center_x": .5, "center_y": .5}
<Tab_score>:
MDLabel:
halign: 'center'
text:'Scorebord'
user_font_size: "48sp"
pos_hint: {"center_x": .5, "center_y": .5}
<Tab_achievments>:
MDLabel:
halign: 'center'
text:'Achievments'
user_font_size: "48sp"
pos_hint: {"center_x": .5, "center_y": .5}
<Tab_historie>:
FloatLayout:
MDLabel:
halign: 'center'
text:'Historie'
user_font_size: "48sp"
pos_hint: {"center_x": .5, "center_y": .5}
MDFlatButton:
id: flat
text: 'druk hier'
pos_hint: {"center_x": .5, "center_y": 0.4}
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
KV = '''
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "Example Tabs"
MDTabs:
id: tabs
on_tab_switch: app.on_tab_switch(*args)
<Tab>:
MDIconButton:
id: icon
icon: app.icons[0]
user_font_size: "48sp"
pos_hint: {"center_x": .5, "center_y": .5}
'''
class Tab(FloatLayout, MDTabsBase):
'''Class implementing content for a tab.'''
class Example(MDApp):
icons = list(md_icons.keys())[15:30]
def build(self):
return Builder.load_string(KV)
def on_start(self):
for name_tab in self.icons:
self.root.ids.tabs.add_widget(Tab(text=name_tab))
def on_tab_switch(
self, instance_tabs, instance_tab, instance_tab_label, tab_text
):
'''Called when switching tabs.
:type instance_tabs: <kivymd.uix.tab.MDTabs object>;
:param instance_tab: <__main__.Tab object>;
:param instance_tab_label: <kivymd.uix.tab.MDTabsLabel object>;
:param tab_text: text or name icon of tab;
'''
count_icon = [k for k, v in md_icons.items() if v == tab_text]
instance_tab.ids.icon.icon = count_icon[0]
Example().run()
https://kivymd.readthedocs.io/en/latest/components/tabs/index.html#kivymd.uix.tab.MDTabs.on_tab_switch
good day
is it possible to have multiple instances of a screen each using unique data? for example, i have a 'homescreen' with various buttons for various categories that takes you to a batch list screen unique to that category where you can add batches to be listed. each buttons batch list screen would have unique data to that category but the template for all batch list screens are the same.
ive made a simple example for one category but in order to expand it to the others would i need to repeat the code and create appropriately named .kv files and add each screen to the screen manager.
.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.uix.behaviors.touchripple import TouchRippleButtonBehavior
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.uix.textinput import TextInput
class CapitalInput(TextInput):
def insert_text(self, substring, from_undo=False):
s = substring.upper()
return super(CapitalInput, self).insert_text(s, from_undo=from_undo)
class RippleButton(TouchRippleButtonBehavior, Button):
def on_touch_down(self, touch):
collide_point = self.collide_point(touch.x, touch.y)
if collide_point:
touch.grab(self)
self.transparency = self.background_color[3]
self.background_color[3] = 0.5 # set transparency to half (0.5)
self.ripple_show(touch)
self.dispatch('on_press')
return True
return False
def on_touch_up(self, touch):
if touch.grab_current is self:
touch.ungrab(self)
self.ripple_fade()
def defer_release(dt):
self.background_color[3] = self.transparency
self.dispatch('on_release')
Clock.schedule_once(defer_release, self.ripple_duration_out)
return True
return False
class AddBatchScreen(Screen):
pass
class BatchScreen(Screen):
pass
class HomeScreen(Screen):
pass
gui = Builder.load_file('BatchTracker.kv')
class BatchTrackerApp(App):
def build(self):
return gui
def insert(self, value):
bs = self.root.get_screen('batch_screen')
bs.ids.rv.data.insert(0, {'value': value or 'default value'})
if __name__ == '__main__':
BatchTrackerApp().run()
BatchTraker.kv
#:kivy 1.11.1
#:include batchscreen.kv
#:include add_batch_screen.kv
#:include homescreen.kv
#:import hex kivy.utils.get_color_from_hex
#:import TouchRippleButtonBehavior kivy.uix.behaviors.touchripple
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
ScreenManager:
id: screen_manager
HomeScreen:
name: 'home_screen'
id: home_screen
BatchScreen:
name: 'batch_screen'
id: batch_screen
AddBatchScreen:
name: 'add_batch_screen'
id: add_batch_screen
<RoundButton#RippleButton>:
background_color: (0,0,0,0)
background_normal: ''
back_color: (1,0,1,1)
border_radius: [20]
canvas.before:
Color:
rgba: self.back_color
RoundedRectangle:
size: self.size
pos: self.pos
radius: self.border_radius
homescreen.kv
<HomeScreen>:
BoxLayout:
orientation: 'vertical'
canvas:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
Label:
canvas.before:
Color:
rgba: 1, 0.7, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
size_hint_y: None
pos_hint: {'top': .1}
text: 'Home Screen'
font_size: 40
GridLayout:
rows: 4
AnchorLayout:
canvas:
Color:
rgba: 0.1, 0.1, 1, 0.9
Rectangle:
pos: self.pos
size: self.size
Button:
pos_hint: {'center_x': 0.5}
size_hint: 0.5, 0.7
halign: 'center'
valign: 'middle'
text: 'Isolations'
font_size: 40
size: self.texture_size
text_size: self.width, None
on_press: print('isolations')
on_release: root.manager.current = 'batch_screen'
AnchorLayout:
canvas:
Color:
rgba: 0.1, 0.1, 1, 0.9
Rectangle:
pos: self.pos
size: self.size
Button:
pos_hint: {'center_x': 0.5}
size_hint: 0.5, 0.7
halign: 'center'
valign: 'middle'
text: 'QPCR'
font_size: 40
size: self.texture_size
text_size: self.width, None
on_release: root.manager.current = 'batch_screen'
AnchorLayout:
canvas:
Color:
rgba: 0.1, 0.1, 1, 0.9
Rectangle:
pos: self.pos
size: self.size
Button:
pos_hint: {'center_x': 0.5}
size_hint: 0.5, 0.7
halign: 'center'
valign: 'middle'
text: 'PCR'
font_size: 40
size: self.texture_size
text_size: self.width, None
AnchorLayout:
canvas:
Color:
rgba: 0.1, 0.1, 1, 0.9
Rectangle:
pos: self.pos
size: self.size
Button:
pos_hint: {'center_x': 0.5}
size_hint: 0.5, 0.7
halign: 'center'
valign: 'middle'
text: 'Electrophoresis'
font_size: 40
size: self.texture_size
text_size: self.width, None
batchscreen.kv
<Row#BoxLayout>:
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
value: ''
Button:
text: root.value
font_size: sp(80)
on_press: print(f'pressed button {root.value}')
<BatchScreen>:
rv: rv #to expose the widget
FloatLayout:
canvas:
Color:
rgba: hex('c6e2ff')
Rectangle:
pos: self.pos
size: self.size
FloatLayout:
canvas.before:
Color:
rgba: hex('b3b3ff')
RoundedRectangle:
radius: 0,0,25,25
pos: self.pos
size: self.size
pos_hint: {'top':1}
size_hint: 1, .1
Label:
id: lb
text: 'User'
font_size: 60
pos_hint: {'top': 1, 'x': .15}
size_hint: .2, .8
RoundButton:
text: 'Sign Out'
font_size: 40
on_release: print('Sign Out pressed')
pos_hint: {'top': .95, 'x': .55}
size_hint: .4, .8
BoxLayout:
canvas.before:
Color:
rgba: hex('eaec3c')
Rectangle:
pos: self.pos
size: self.size
pos_hint: {'center_x':.5,'center_y':.5}
size_hint: 0.9,0.8
RecycleView:
id: rv
viewclass: 'Row'
scroll_type: ['bars', 'content']
scroll_wheel_distance: dp(114)
bar_width: dp(10)
RecycleBoxLayout:
default_size: None,100
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
GridLayout:
cols:3
canvas.before:
Color:
rgba: hex('969c9c')
Rectangle:
pos: self.pos
size: self.size
pos_hint: {'y': 0}
size_hint: 1, .1
RoundButton:
id: add_batch
text: 'Add Batch'
font_size: 30
on_press: root.manager.transition = SlideTransition(direction="left")
on_release: root.manager.current = 'add_batch_screen'
pos_hint: {'center_y': .5, 'x': .05}
size_hint: .4, .8
back_color: hex('62fd00')
RoundButton:
text: 'Remove Batch'
font_size: 30
halign: 'center'
valign: 'middle'
size: self.texture_size
text_size: self.width, None
on_release: print('Remove pressed')
on_release: print(root.manager.ids.batch_screen.rv.data)
pos_hint: {'center_y': .5, 'x': .55}
size_hint: .4, .8
back_color: hex('fd0000')
RoundButton:
text: 'Back'
font_size: 30
halign: 'center'
valign: 'middle'
size: self.texture_size
text_size: self.width, None
on_press: print('Back pressed')
on_release: root.manager.current = 'home_screen'
pos_hint: {'center_y': .5, 'x': .55}
size_hint: .4, .8
back_color: hex('0000ff')
add_batch_screen.kv
<AddBatchScreen>:
canvas:
Color:
rgba: 0,0,1,1
Rectangle:
pos: self.pos
size: self.size
CapitalInput:
id: capital_input
size_hint: .9, .15
pos_hint: {'center_x': .5, 'y': .6}
font_size: 40
padding: [0, (self.height-self.line_height)/2]
hint_text: 'Batch No.'
multiline: False
halign: 'center'
Button:
id: addbtn
text: 'Add'
size_hint: .4, .08
pos_hint: {'center_x': .5, 'y': .2}
on_press: app.insert(capital_input.text) if capital_input.text != '' else None
on_release: capital_input.text = ''
Button:
text: 'Batch List'
size_hint: .4, .08
pos_hint: {'center_x': .5, 'y': .1}
on_press: root.manager.transition = SlideTransition(direction="right")
on_release: root.manager.current = 'batch_screen'
on_release: print(root.manager.ids.batch_screen.rv.data)
As this is a lot of code you will have a hard time finding someone to give you a specific answer. Without looking through all of your code, yes it is possible to have multiple instances of a screen with unique data. This is exactly the use case of class instances. You simply need to pass a variable, list or object into the instance. I will give you a short example, then you should be able to figure it out yourself for your code.
class MyReusableScreen(Screen):
def __init__(self, data, **kwargs):
super(MyReusableScreen, self).__init__(**kwargs)
self.data = data
mylabel = Label(text=self.data['mylabel_text'])
We added the attribute data to the class. Now we have to pass the data when we initialize the class instance
data1 = {'mylabel_text': 'first label'}
data2 = {'mylabel_text': 'second label'}
screen1 = MyReusableScreen(data=data1)
screen2 = MyReusableScreen(data=data2)
Like this we added unique label texts to the class instances labels. I guess you should now be able to build it up on your own. In case you defined a label in kv language, give it an id like for exanple id: mylabel and then assign the data value like this within you screen mylabel.text = self.data['mylabel_text']. I hope this helps you and if you struggle with something just give me a sign.
I am new to python/Kivy.
I have two files test.py and test.ky.
Now I am using two static row with serial number 1 and 2.
Can anyone tell me?
How to add row dynamic when click on '+add more' button.Now 2 row shows which are static row with serial number increment. I want add row dynamic 1 to 10 with serial number increment.
test.py
import kivy
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.size = (450, 525)
class display(Screen):
def add_more(self):
print('test')
class test(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
test().run()
test.kv
display:
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
Button:
size_hint_x: .2
text: "+Add More"
valign: 'bottom'
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
Label:
size_hint_x: .2
text: "SN"
valign: 'bottom'
Label:
size_hint_x: .8
text: "Value"
valign: 'bottom'
BoxLayout:
orientation: "horizontal"
spacing: 0, 5
Button:
text: '1'
size_hint_x: .2
TextInput:
size_hint_x: .8
BoxLayout:
orientation: "horizontal"
spacing: 0, 5
Button:
text: '2'
size_hint_x: .2
TextInput:
size_hint_x: .8
BoxLayout:
orientation: "horizontal"
padding : 10, 0
spacing: 10, 10
size_hint: .5, .7
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
on_release:
root.dismiss()
Button:
text: 'Cancel'
on_release: root.dismiss()
Can someone help me?
You can make a custom class for Row and Rows, then have a method adding rows.
I modified your example a bit. Try this:
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
Window.size = (450, 525)
class display(Screen):
def add_more(self):
self.ids.rows.add_row()
class Row(BoxLayout):
button_text = StringProperty("")
class Rows(BoxLayout):
orientation = "vertical"
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class test(App):
def build(self):
self.root = Builder.load_string(KV)
return self.root
KV = """
<Row>:
orientation: "horizontal"
spacing: 0, 5
Button:
text: root.button_text
size_hint_x: .2
TextInput:
size_hint_x: .8
display:
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
Button:
size_hint_x: .2
text: "+Add More"
valign: 'bottom'
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
Label:
size_hint_x: .2
text: "SN"
valign: 'bottom'
Label:
size_hint_x: .8
text: "Value"
valign: 'bottom'
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
padding : 10, 0
spacing: 10, 10
size_hint: .5, .7
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
on_release:
root.dismiss()
Button:
text: 'Cancel'
on_release: root.dismiss()
"""
test().run()