I am trying to make a Kivy label that shows a string that is just a list of names. My end goal is to make it so you can add or remove to the list of names and the label will indicate the names on the list. As of now I have a label and a function in my .py file that compiles the list of names into a string.
Each name in the string is separated by a "\n". My problem however, is that the label does not update and show the names even though the function returns the names. I researched this problem and heard about threading. However, I do not understand how to use it in my case and am asking for some guidance.
Below is my code:
kv CODE:
<SettingsWindow>:
name:"settings"
FloatLayout:
Widget:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: "Images/logo_br.png"
Color:
rgba: 0,0,0,.5
Rectangle:
size: 200, 330
pos: self.width/10, self.height/4
Button:
text:"Back"
size_hint: 0.1, 0.1
pos_hint: {"x":0, "y":0}
background_color: 1,1,1,.6
on_release:
app.root.current = "main"
root.manager.transition.direction = 'right'
Label:
text: root.pretty_list_people
size: self.texture_size
pos_hint: {"x":0.35, "y":-0.46}
color: 1,1,1,1
Button:
text:"Show Bros"
size_hint: 0.3, 0.3
pos_hint: {"x":0.3, "y":0.1}
on_press: root.Pretty_Print_People(root.get_str_People())
py CODE:
class SettingsWindow(Screen):
pretty_list_people = ""
def get_str_Jobs(self):
return WindowManager.jobs
def get_str_People(self):
return WindowManager.people
def Pretty_Print_People(self, ppl_list):
for person in ppl_list:
self.pretty_list_people += person + "\n"
class HelpWindow(Screen):
pass
class WindowManager(ScreenManager):
jobs = ["Scrub", "Wash", "Clean"]
people = ["Anthony", "Tim", "John"]
job_assignments = {}
I tried to show only the necessary code.
This should work, uses kivy properties:
Change:
pretty_list_people = ""
To:
pretty_list_people = StringProperty ("")
And add the import:
from kivy.properties import StringProperty
At the start of your program
Hope this helps you to solve your problem
Related
.
I'm new into kivy and I want to make an android app. I almost finish GUI, the front-end part, but I have a very big problem. I've searched all over the internet but without answer. I don't know how to access ids from .kv to use them into .py functions.
I've tried all of what I've found on the internet, but didn't work. I want to access ids from .kv file to work with them. For exemple, I have a profile screen, where user write his first name, and last name, and in the next page I want to show his first and last name by using a function.
Here's the .kv profile page:
<Profile>
FloatLayout:
canvas.before:
Color:
rgba:(1,1,1,1)
Rectangle:
source:"CreateProfileImg.png"
size: root.width, root.height
pos: self.pos
Label:
pos_hint: {"top": 1, "left": 1}
size_hint: 1, .1
text:"Create your profile"
font_size: 65
font_name:"FreeSansBoldOblique-BYJ3.otf"
color: rgba(247,251,246,255)
id: profile_label
Label:
text: "First Name: "
font_size: 45
color: rgba(247,251,246,255)
size_hint: 0.1, 0.1
pos_hint: {"x":0.20, "top":0.8}
TextInput:
id: name
multiline: False
size_hint: 0.5, 0.1
pos_hint: {"x": 0.35, "top": 0.8}
Label:
text: "Last Name: "
font_size: 45
color: rgba(247,251,246,255)
size_hint: 0.1, 0.1
pos_hint: {"x":0.16, "top":0.7}
TextInput:
id: prenume
multiline: False
size_hint: 0.5, 0.1
pos_hint: {"x": 0.35, "top": 0.7}
Label:
text: "Currency: "
font_size: 45
color: rgba(247,251,246,255)
size_hint: 0.1, 0.1
pos_hint: {"x":0.18, "top":0.6}
Spinner:
id: moneda
text:"Select currency"
color: 0, 0, 0 ,1
background_normal:"MoneyButton.png"
size_hint: 0.5, 0.1
pos_hint: {"x":0.35, "top":0.6}
values: ['Ron', 'Euro', 'Dolar','Lira Sterlina']
sync_height: True
#on_text: root.currency_clicked(moneda.text)
GridLayout:
rows:1
pos_hint:{"top": .2, "left": 1}
size_hint: 1, .2
ImageButton:
source:"Next_Button_On_Press.png"
on_press:
self.source = "Next_Button_On_Release.png"
app.printname()
on_release:
self.source = "Next_Button_On_Press.png"
app.change_screen("page1")
I have more .kv files with lots of ids, but I think if I learn how to work with thise two, next will be easier.
I want to specify that I have a 'main.kv' which contains: 1. name
2.ids
from all over my .kv files. I use those ids to navigate between pages.
Here's the code:
#:include homescreen.kv
#:include page1.kv
#:include profile.kv
GridLayout:
cols: 1
ScreenManager:
id: screen_manager
HomeScreen:
name: "home_screen"
id: home_screen
Profile:
name: "profile"
id: profile
Page1:
name: "page1"
id: page1
Let me explain for the last time what I want to do, maybe will be usefull for you to understand and trying to help me. As you see, into 'profile' I have 3 ids. When get TextInput from user, those ids store the information. I want to use those information into next page, where I want to say [[[" Hello " + ids]]].
So, please help me!! Make me to understand!
I also had trouble with this as well when I was first leaning Kivy a couple years back, but I finally figured out the way. there is a bit of boilier-plate required to maintain the connection.
in this example my_label is a kivy id and I am connecting it to a Python object of the same name. this is done with the line: my_label: my_label
<Screen2>:
# Python: KIVY id(s)
my_label: my_label
BoxLayout:
Label:
text: "Screen2"
MDLabel:
id: my_label
text: "-"
and in the Python code matching that object there is a line in the class definitionl my_label: MDLabel
which is providing a type hint. If you are using an IDE such as PyCharm this can help you to have auto-complete in your code according to the object type.
class Screen2(Screen):
my_label: MDLabel
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.my_label.text = "test"
and the line self.my_label.text = "test" is of course to show how you can use the object.
you can also do more complicated things such as put multiple items from a kv layout into a list or even a dictionary.
kivy code:
# a list of spinners kv_spinner_list is a ListProperty
kv_spinner_list: [kv_spinner_0, kv_spinner_1, kv_spinner_2,]
and this can be a more organized way to bring multiple items into the Python code.
I´m learning kivy, and it has passed 3 weeks since i face this problem without encounter a solution, so i hope any of u guys could help me, i would appreciate it.
I have a main file:
from app import MyProgramApp
if __name__ == "__main__":
winapp = MyProgramApp()
winapp.run()
from where i start my app. Then i have a directory called "app", inside there is the following "init.py" file.
from kivy.app import App
from kivy.utils import QueryDict, rgba
from kivy.core.window import Window
from .view import MainWindow
Window.minimum_width = 500
Window.minimum_height = 650
Window.maximize()
class MyProgramApp(App):
colors = QueryDict()
colors.primary = rgba('#2D9CDB')
colors.secondary = rgba('#16213E')
colors.succes = rgba('#1FC98E')
colors.warning = rgba('#F2C94C')
colors.danger = rgba('#E85757')
colors.grey_dark = rgba('#C4C4C4')
colors.grey_light = rgba('#F5F5F5')
colors.black = rgba('#A1A1A1')
colors.white = rgba('#FFFFFF')
def build(self):
return MainWindow()
Same folder app, i have the following "view.py".
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.properties import StringProperty
from kivy.uix.screenmanager import ScreenManager
class MainWindow(BoxLayout):
username = StringProperty("Usuario")
def __init__(self, **kw):
super().__init__(**kw)
def on_press_home(self):
self.ids.scrn_mngr.current = "scrn_home"
class ViewManager(ScreenManager):
def __init__(self, **kw):
super().__init__(**kw)
class NavTab(ToggleButtonBehavior, BoxLayout):
text = StringProperty('')
icon = StringProperty('')
def __init__(self, **kw):
super().__init__(**kw)
and finally for that folder i have "myprogram.kv"
#:kivy 2.1.0
#:import Home views.home.Home
<MainWindow>:
spacing: dp(8)
canvas.before:
Color:
rgba: app.colors.white
Rectangle:
pos: self.pos
size: self.size
# NAVIGATION BAR
BoxLayout:
id: nav_menu
size_hint_x: .2
orientation: "vertical"
size_hint_min_x: dp(100)
# LOGO
BoxLayout:
id: logo_nbox
size_hint_y: .1
size_hint_min_y: dp(70)
padding: dp(16)
AnchorLayout:
anchor_x: "right"
size_hint_x: None
width: dp(52)
halign: "left"
Label:
text: "COMPANY"
halign: "center"
BoxLayout:
orientation: "vertical"
Label:
text: "COMPANY"
halign: "center"
Label:
text: "Phrase"
halign: "center"
# OPTIONS
GridLayout:
id: tabs_box
cols: 1
spacing: dp(4)
size_hint_y: .5
canvas.before:
Color:
rgba: app.colors.grey_dark
Rectangle:
pos: self.pos
size: [self.size[0], dp(1)]
NavTab:
text: "Home"
state: "down"
on_press: root.on_press_home()
# BODY
BoxLayout:
size_hint_x: .8
spacing: dp(8)
orientation: "vertical"
padding: [dp(16), dp(8), dp(12), dp(8)]
canvas.before:
Color:
rgba: app.colors.grey_light
Rectangle:
pos: self.pos
size: self.size
# SCREENS
BoxLayout:
ViewManager:
id: scrn_mngr
<ViewManager>:
Screen:
name: "scrn_home"
Home:
id: home
<NavTab>:
background_normal: ""
background_down: ""
background_color: [0,0,0,0]
group: "tabs"
size_hint_y: None
height: dp(45)
spacing: dp(4)
canvas.before:
Color:
rgba: [0,0,0,0] if self.state == "normal" else rgba("#E1F1FF")
Rectangle:
pos: self.pos
size: self.size
Color:
rgba: [0,0,0,0] if self.state == "normal" else app.colors.primary
Rectangle:
pos: [self.pos[0]+self.size[0]-dp(1), self.pos[1]]
size: [dp(8), self.size[1]]
Label:
halign: "left"
valign: "middle"
text: root.text
color: app.colors.grey_dark if root.state == "normal" else app.colors.primary
Then i got another folder called "views" inside i have another folder called "home", inside home we encounter 3 files "init.py", "home.kv", "home.py". the first one "init.py" is the following.
from .home import Home
then we got "home.kv".
#:kivy 2.1.0
<Home>:
orientation: "vertical"
Label:
size_hint_y: .1
text: "Other"
Button:
size_hint_y: .1
text: "popup"
on_press: root.open_popup()
BoxLayout:
size_hint_y: .8
id: home_box
<SomePopup>:
title: "SOME TITLE"
title_align: "center"
title_color: app.colors.primary
size_hint: .25, .8
size_hint_min_x: dp(200)
pos_hint: {"x": .1, "top": .9}
BoxLayout:
orientation: "vertical"
padding: [dp(0), dp(12), dp(0), dp(12)]
Label:
text: "Some text"
Button:
text: "create buttons on box"
on_press: root.modify_home_box()
and finally and the problem that i´m facing is whit the following file "home.py"
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.factory import Factory
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.app import App
Builder.load_file('views/home/home.kv')
class Home(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def open_popup(self):
Factory.SomePopup().open()
class SomePopup(Popup):
def __init__(self, **kw):
super().__init__(**kw)
def modify_home_box(self):
my_app = App.get_running_app().root
my_box = my_app.ids.home.ids.home_box
custom_button = Button(
text = "something"
)
my_box.add_widget(custom_button)
That i´m trying to do is actually modify "home_box" with is store on ids Home dictionary, i also try with ObjectProperty (but that gives and Attribute Error, since i only could read propertys but doesnt modify it), instance of a new Home class doesnt work... searching for current app in App appear doesnt work since Home is store i think on screenManager...
I need add a button or some widget to "home_box" from outside class "SomePopup". I also drop here a repository on github with the whole code. github_repo
I don't know how to solve my issue, and i try with the resources available here on stack as well other net places... any help would be appreciate.
Just a very complicated path to the widget of interest. In your modify_home_box() method, try replacing:
my_app = App.get_running_app().root
my_box = my_app.ids.home.ids.home_box
with:
my_app = App.get_running_app().root
my_box = my_app.ids.scrn_mngr.ids.home.ids.home_box
I am doing an App in kivy using kivyMD but I Want to insert a MDcard, the thing is that I want the MDCard look like this:
But it looks like this:
I know it can be with border_radius but I dont know how to do it,
here is my code:
PY:
import kivy
from kivymd.app import MDApp
from kivymd.uix.card import MDCard
class Home(MDCard):
pass
class Manage(MDApp):
title = 'QUICKP'
def build(self):
return Home()
if __name__ == '__main__':
Manage().run()
KV:
<Home>
MDCard:
size_hint: None, None
size: "280dp", "180dp"
pos_hint: {"center_x": .5, "center_y": .5}
You do not need to modify the card.py file nor do you have to use canvas you just have to place the following in your kivy code
border_radius: 20
radius: [15]
In border_radius you put the border limit that you will be able to use and in radius you put the border level that your mdcard will have.
People advise to use canvas its OK, but it increase your coding and make it very complex. Just go to the Kivymd>uix>card.py line 631 change the default from 3dp to for example 20dp or whatever you want. then go back to your code and type radius: [] and insert your desire number from 20 to 0.
Done!!!
#BernardoOlisan You can use this directly
MDCard:
size_hint: None, None
size: "280dp", "180dp"
pos_hint: {"center_x": .5, "center_y": .5}
elevation: 15
radius: 10
MDLabel:
text: 'Your title'
halign: 'center'
pos_hint: {"center_x": .5, "center_y": .5}
It works for sure
I had the same problem, and there is a border_radius property for MDCards, but it does not work. But i have solved this with this code:
<MyCard>:
orientation: 'vertical'
size_hint: 0.1, 1
canvas.before:
Color:
rgba: app.theme_cls.primary_color
RoundedRectangle:
radius: [10]
size: self.size
pos: self.pos
FloatLayout:
size: self.size
pos: self.pos
pos_hint: {"x": -0.1, "y": -0.6}
And here is a part from .py file:
class Plan(RectangularElevationBehavior, RectangularRippleBehavior, FloatLayout):
ripple_scale = 1.4
text = StringProperty()
text_label = StringProperty()
So, it creates a MyCard(FloatLayout class) with Canvas in it, which inherits from FloatLayout, RippleBehaviour and ElevationBehaviour. And then you can add to that FloatLayout in it to manage content of it. But if it looks strange because of the position, try playing with pos_hint-s.
I have a realy simple program in Kivy with 3 windows.But when I run it it says
The file C:\Users\ab79\Documents\GPX WEATHER\weather.kv is loaded multiples times, you might have unwanted behaviors.
I can run it but there is actually an unwanted behaviour, one of my three windows desappears !
When I run the code now it is skipping the "infoWindow" in the middle. I can observe it since I put FloatLayout instead of GridLayout, but the error message was already here before. I don't understand what's going wrong.
Here is the minimal code
python
today = datetime.datetime.now()
class ImportFileWindow(Screen):
pass
class InfoWindow(Screen):
pass
class ResultWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("weather.kv")
class WeatherApp(App):
def build(self):
return kv
if __name__=="__main__":
WeatherApp().run()
Kivy
WindowManager:
ImportFileWindow:
InfoWindow:
ResultWindow:
<Label>
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
font_size:40
color: 0,0,0,1
<Button>
font_size:40
color: 0,0,0,1
background_normal: ''
<ImportFileWindow>:
name: "import"
Button:
text: "Importer"
on_release:
app.root.current = "info"
root.manager.transition.direction="left"
<InfoWindow>:
name: "info"
day: day
FloatLayout:
cols:2
size:root.width,root.height/2
Label:
text:"Jour :"
TextInput:
id:day
multiline:False
Button:
text:"Valider"
on_release:
app.root.current="result"
root.manager.transition.direction="left"
Button:
text:"Retour"
on_release:
app.root.current="import"
root.manager.transition.direction="right"
<ResultWindow>:
name: "result"
Button:
text: "Retour"
on_release:
app.root.current="info"
root.manager.transition.direction="right"
```
The error is are since the begining but the real issues are here since I use a FloatLayout instead of GridLayout.
Any ideas ?
:)
The file weather.kv is loaded automatically, see documentation. But you are also loading it explicitly with:
kv = Builder.load_file("weather.kv")
I think you just need to delete the above line, and change your WeatherApp class to:
class WeatherApp(App):
pass
You have to assign full code of your 'kv' file in to a variable(ex:- kv = """kv code here"""). And create a new function to load it using Builder.load_string(kv). After that use 'kivy.clock' module to schedule that function once when the build method is started.
I am using kivy to make a very simple gui for an application. Nothing complex, very simple layout.
Nevertheless I am having a hard time with TextInputs...They always display with full height and I can't manage to make them adjust to a "reasonable" text-height like height.
I am using the kv files style since I find it cleaner and easier to integrate it in an already existing app...I would like to reduce as much as possible the gui-python code of the app.
Here is what I got for the TextInput (useless to add other parts of the gui).
Python code
# textInput.py
from kivy import require
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder
Builder.load_file('path/to/kv/file/textInput.kv')
require('1.10.0')
class MainScreen(BoxLayout):
pass
class Test(App):
def build(self):
self.title = 'Testing textInput'
return MainScreen()
if __name__ == '__main__':
Test().run()
KV code
# textInput.kv
<MainScreen>
orientation: 'vertical'
# Third section title
Label:
size_hint: (1, .1)
text: 'Setup Connection'
font_size: 25
# Third section Box
BoxLayout:
size_hint: (1, .2)
padding: [100, 0, 100, 0]
BoxLayout:
Label:
size_hint: (.2, 1)
text: 'Host'
TextInput:
height: self.minimum_height
multiline: False
text: 'localhost'
Label:
size_hint: (.2, 1)
text: ''
Label:
size_hint: (.2, 1)
text: 'Port'
TextInput:
size_hint: (.2, 1)
multiline: False
text: '502'
I have tried lot of stuff, in the code here I am trying both to use size_hint and height...but none works..
To set a height of a widget, first set the size_hint_y to None and then you can set the height to whatever you want.
TextInput:
size_hint: (.2, None)
height: 30
multiline: False
text: '502'
in addition to the answer size_hint_x and size_hint_y must be set to None respectively before the height and width attribute can be used i.e size_hint: (None, None) for less typing. If you want to set the width attribute, size_hint_x is set to None and vice-versa.