Kivy Event on carousel when slide change - python

I don't have any idea to find a solution of my problem.
I have make an application with Carousel Widget. In this Carousel I have 4 slides.
welcomeSlide -> DVDSlide -> DVDPretSlide --> CategorySlide
I have make a class for each slides.
I use a ListAdpter to display the data extracted from an Sqlite3 Database.
My pblem is about the refresh of the list, when I modify a DVD (add name to pret) in the DVDSlide, when I slide to the DVDPret, the DVD do not appears because the List is not refresh.
Like the doccumentation for the carousel I don't find the event when slide change. It will be the best if an event exist to get the current slide index.
Have you got any Idea ?
Thanks,

You can observe index property:
from kivy.uix.carousel import Carousel
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.lang import Builder
Builder.load_string('''
<Page>:
Label:
text: str(id(root))
<Carousel>
on_index: print("slide #{}".format(args[1]))
''')
class Page(BoxLayout):
pass
class TestApp(App):
def build(self):
root = Carousel()
for x in range(10):
root.add_widget(Page())
return root
if __name__ == '__main__':
TestApp().run()
Or you can observe current_slide property:
from kivy.uix.carousel import Carousel
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.lang import Builder
Builder.load_string('''
<Page>:
label_id: label_id
Label:
id: label_id
text: str(id(root))
<Carousel>
on_current_slide: print(args[1].label_id.text)
''')
class Page(BoxLayout):
pass
class TestApp(App):
def build(self):
root = Carousel()
for x in range(10):
root.add_widget(Page())
return root
if __name__ == '__main__':
TestApp().run()

If you want a pure python solution rather than a Kivy Language solution you can create your own carousel that inherits from the Kivy carousel as follows.
import kivy
from kivy.uix.carousel import Carousel
class MyCarousel(Carousel):
# This class is a carousel that runs script
# when a slide gets focus (except first load).
def on_index(self, *args):
print('the slide is', self.index)
# YOUR CODE GOES HERE
Carousel.on_index(self, *args)

Related

Kivy-Add custom widget definded in py file via kv file

I have a custom button. I cannot put it on screen via kv file. I studied a lot topics. No useful info can find. Here is a simple example:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string('''
#:kivy 1.11.0
<MyGrid>:
Button
text: 'hello'
''')
class MyGrid(BoxLayout):
pass
class DropApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
DropApp().run()
Note that the Button in this kv file is native Kivy button. I run this code, I can see this button on screen. But now I have a custom Button:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string('''
#:kivy 1.11.0
<MyGrid>:
customButton:
''')
class MyGrid(BoxLayout):
pass
class customButton(Button):
def __init__(self, **kwargs):
self.text = 'hi'
super(Button, self).__init__(**kwargs)
class DropApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
DropApp().run()
I run this code, I cannot see this customButton on screen. Note that the custom widget is complex. I have to define it in py file. For example:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
class DropApp(App):
def build(self):
layout = GridLayout(cols=1, spacing=10)
for i in range(100):
btn = Button(text=str(i), size_hint_y=None, height=40)
layout.add_widget(btn)
return layout
if __name__ == '__main__':
DropApp().run()
Building this layout need for loop. I cannot find a way to build it in kv file. So I define it in Py file. But if I define it in py file, I cannot work with it in kv file.
Question 1: What's wrong with the second code?
Question 2: If I can't make it work, can I achieve the third code in kvlang(in kv file not in python)?
I am new to Kivy, hope someone can help.
When I run the code on Kivy v1.11.1 , Python v3.7.5:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
class DropApp(App):
def build(self):
layout = GridLayout(cols=1, spacing=10)
for i in range(100):
btn = Button(text=str(i), size_hint_y=None, height=40)
layout.add_widget(btn)
return layout
if __name__ == '__main__':
DropApp().run()
The output is:
If this is the output you require, try running:
pip install --upgrade kivy
For the second code, python is case-sensitive. So instead of customButton, use CustomButton.
If you want to do the 3rd code using .kv file, here is an example:
from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.lang import Builder
Builder.load_string('''
<ExampleRV>:
viewclass: 'Button'
RecycleBoxLayout:
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
''')
class ExampleRV(RecycleView):
def __init__(self, **kwargs):
super(ExampleRV, self).__init__(**kwargs)
self.data = [{'text': str(x)} for x in range(20)]
class RecycleApp(App):
def build(self):
return ExampleRV()
RecycleApp().run()
For reference, go HERE.

Kivy - updating label text periodically [duplicate]

This question already has an answer here:
How to have an updating time in Kivy
(1 answer)
Closed 3 years ago.
New to python and kivy. Working on a dashboard to display time and other parameters. Dashboard is currently set and displays all values perfectly. But still can't figure out how to update the time dynamically in those labels used for time. Found similar posts but still struggling. Posting below the summarised portion of my codes.
Worked with the Clock object to trigger a method every one sec which need to update the label text in the kv file. But unable to put this logic into working.
sample.py
import time
import datetime
import kivy
kivy.require('1.11.0')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.core.text import LabelBase
from kivy.clock import Clock
class MySec(BoxLayout):
seconds_string = time.strftime("%S")
class MyApp(App):
def build(self):
#Clock.schedule_interval('periodic_method', 1)
return MySec()
if __name__ == '__main__':
MyApp().run()
my.kv file
<mysec>:
orientation: 'vertical'
Label:
id: kv_sec
text: root.seconds_string
font_size: 200
In short, how should I modify the .py file so that so that my .kv label text gets updated every second with the updated value. Thanks a lot in advance.
Use a Kivy StringProperty to automatically update the Label's text, and use Kivy Clock object e.g. Clock.schedule_interval() to update the StringProperty at every time interval.
Replace seconds_string = time.strftime("%S") with class attribute of type StringProperty, seconds_string = StringProperty('')
Implement a method, update_time() to update class attribute, seconds_string
Use Kivy Clock.schedule_interval() to invoke method update_time()
Kivy ยป Introduction to Properties
Properties are an awesome way to define events and bind to them.
Essentially, they produce events such that when an attribute of your
object changes, all properties that reference that attribute are
automatically updated.
Example
The following example uses time() function to extract time. It can be replaced with datetime.now() e.g. replace time.strftime("%S") with datetime.now().strftime("%S"), and add import statement, from datetime import datetime
main.py
import time
import kivy
kivy.require('1.11.0')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.properties import StringProperty
Builder.load_string("""
<MySec>:
orientation: 'vertical'
Label:
id: kv_sec
text: root.seconds_string
font_size: 200
""")
class MySec(BoxLayout):
seconds_string = StringProperty('')
class MyApp(App):
def build(self):
Clock.schedule_interval(lambda dt: self.update_time(), 1)
return MySec()
def update_time(self):
self.root.seconds_string = time.strftime("%S")
if __name__ == '__main__':
MyApp().run()
Output

Understanding Kivy properities and binding methods

I am having problems understanding the usage of custom Properities and ways of binding methods to events.
Here's my code:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.properties import StringProperty
kivy_lang = '''
<MainWidget>:
on_my_property: my_label.text = 'from button bind method via StringProperty' + my_property
Label:
id: my_label
text: root.my_property
Button:
id: my_button
text: 'intro button'
'''
class MainWidget(BoxLayout):
# bind some properties
my_property = StringProperty('0')
def __init__(self, **kwargs):
super(MainWidget, self).__init__(**kwargs)
# if needed to do sth on widget construction
self.ids.my_button.bind(on_press=self.my_method)
def my_method(self,*args,**kwargs):
self.my_property = str(int(self.my_property)+1)
self.ids.my_button.text = 'new'
class MyApp(App):
def build(self):
Builder.load_string(kivy_lang)
return MainWidget()
if __name__ == '__main__':
MyApp().run()
When I run it it renders OK, but when I click a button, as a result I get
NameError: name 'my_property' is not defined
I tried binding method for Button in kv lang with (and removing whole 'init()' on python side):
on_press: root.my_method
and then when I press button the app doesn't crash but nothing happens
Can someone explain me how to adjust this code to work?
I understand the code is a little 'mixed techniques' but I did it that way to get to know different approaches, so I would appreciate if You don't turn it all around :)
1/ you are missing 'self' before 'my_property' in 'on_my_property' bindind, hence the crash
2/ in kv bindings. the python code is called as written, so you need '()' after 'root.my_method', or the statement has no effect.

FactoryException when trying to create a "IconButton" in Kivy

I've tried to create an Icon that can be clicked, which means an Image with a ButtonBehavior.I followed the documentation (http://kivy.org/docs/api-kivy.uix.behaviors.html), and I've got a FactoryException with the following code:
# coding: utf-8
from kivy.uix.behaviors import ButtonBehavior
from kivy.core.image import Image
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
kv_string = """
BoxLayout:
IconButton
"""
class IconButton(ButtonBehavior, Image):
def on_press(self):
print("on_press")
class DashboardApp(App):
pass
Builder.load_string(kv_string)
if __name__ == "__main__":
DashboardApp().run()
When I change the parent class of IconButton from (ButtonBehavior, Image) to (ButtonBehavior, Widget), the problem disappears.
You want kivy.uix.image, not kivy.core.image.

Python kivy text input

I'm a newbie at python, and now doing a dictionary with kivy. Issue is when I type text, it's not working. Below there I just want to check if it's working or not, so I put some popup, and if input text is 'a' then print true. It's just checking it's working or not, hope you guys help me, thank you.
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.bubble import Bubble
class CustomPopup(Popup):
pass
class Diction(GridLayout):
def __init__(self, **kwargs):
super(Diction, self).__init__(**kwargs)
self.cols=2
self.add_widget(Label(text="Search"))
self.search=TextInput(multiline=False)
self.add_widget(self.search)
if self.search=='A':
print 'True'
else:
print 'False'
self.add_widget(Button(text="click",on_press=self.show_popup))
def show_popup(self, b):
p = CustomPopup()
p.open()
class MyApp(App):
def build(self):
return LoginScreen()
if __name__=="__main__":
MyApp().run()
There are two reasons why is not working:
The if should be in the method that handles the events, i.e. show_popup
You should compare the text in the Label, not the Label itself. Instead of self.search=='A', you should use self.search.text=='A'
Here is the corrected __init__ and show_popup code:
class Diction(GridLayout):
def __init__(self, **kwargs):
super(Diction, self).__init__(**kwargs)
self.cols=2
self.add_widget(Label(text="Search"))
self.search=TextInput(multiline=False)
self.add_widget(self.search)
self.add_widget(Button(text="click",on_press=self.show_popup))
def show_popup(self, b):
if self.search.text=='A':
print 'True'
else:
print 'False'
p = CustomPopup()
p.open()
An alternative approach using the Kivy Language
The Kivy Language could help you to have a cleaner code. Your code could look like this:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
# DON'T forget to import Label!!!
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.lang import Builder
Builder.load_string("""
<CustomPopup#Popup>:
title: "My Custom Poput"
<Diction#GridLayout>:
cols: 2
search: id_search
Label:
text: "Search"
TextInput:
id: id_search
Button:
text: "click"
on_press: root.show_popup(self)
""")
class CustomPopup(Popup):
pass
class Diction(GridLayout):
def show_popup(self, b):
if self.search.text=='A':
print 'True'
else:
print 'False'
# You can send any content to the popup with the content attribute
CustomPopup(content=Label(text=self.search.text)).open()
class MyApp(App):
def build(self):
return Diction()
It helps to keep the logic separated from the interface. You can even keep in separate files if you use the load_file function instead of the load_string.

Categories

Resources