I want to make time counter with progressbar.The bar should be filled as time progresses.
I've progresed with the logic in the codes below, but the code starts before the program opens.
The bar should be stuffed every second.At least that's what I think.
'''
def update_time(self):
while self.ids.pb.value < 30:
time.sleep(1)
self.ids.pb.value+=1
'''
Related .kv file.
'''
<Question>:
name:"questions"
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'bg2.jpg'
FloatLayout:
Label:
id:quest
pos_hint: {"x":0.1,"y":0.62}
size_hint: 0.7,0.5
text:root.sendquest()
color:1, 0, 0, 1
ProgressBar:
id : pb
min :0
max :30
pos_hint: {'x': 0.1,"y":0.45}
size_hint_x :0.8
size_hint_y :0.03
background_color:0.8, 0.1, 0.1, 0
Button: #A
id:A
pos_hint: {"x":0.045,"y":0.376}
size_hint: 0.91,0.055
on_press:
root.reset() if root.check_truth("A") else root.popup()
'''
There are functions that are not relevant to this subject in main.py file.
Kivy Programming Guide ยป Events and Properties
In Kivy applications, you have to avoid long/infinite loops or
sleeping.
Solution
The solution is to use either Triggered Events (e.g. create_trigger() function) or Schedule Interval (e.g. schedule_interval() function).
Snippets - schedule_interval()
from kivy.properties import ObjectProperty
from kivy.clock import Clock
class RootWidget(ProgressBar):
tick = ObjectProperty(None)
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
self.max = 30
self.tick = Clock.schedule_interval(lambda dt: self.update_time(), 1)
def update_time(self):
self.value += 1
if self.value >= 30:
self.tick.cancel() # cancel event
Snippets - create_trigger()
from kivy.properties import ObjectProperty
from kivy.clock import Clock
class RootWidget(ProgressBar):
tick = ObjectProperty(None)
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
self.max = 30
self.tick = Clock.create_trigger(lambda dt: self.update_time(), 1)
self.tick()
def update_time(self):
self.value += 1
if self.value < 30:
self.tick()
else:
self.tick.cancel() # cancel event
Related
I am new in kivy and I am trying to change image of float layout with a button
I tried everything I can but it didn't worked out.
I am getting the below error
AttributeError: 'Chat_Bot' object has no attribute 'ids'
May be I need to extend the class but I am not sure
Below is my 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
from kivy.clock import Clock
from kivy.core.text import LabelBase
from kivymd.uix.label import MDLabel
from kivymd.uix.label import MDLabel
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import StringProperty,NumericProperty
from kivymd.uix.textfield import *
import lk_k
Window.keyboard_anim_args = {"d":.2,"t":"in_out_quart"}
Window.softinput_mode = ""
class Command(MDLabel):
text = StringProperty()
size_hint_x = NumericProperty()
halign = StringProperty()
font_size=26
class Response(MDLabel):
text = StringProperty()
size_hint_x = NumericProperty()
halign = StringProperty()
font_size=26
class main(MDApp):
def change_screen(self, name):
screen_manager.current = name
def build(self):
global screen_manager
screen_manager = ScreenManager()
screen_manager.add_widget(Builder.load_file("Chats.kv"))
return screen_manager
def response(self, *args):
q=lk_k.get_response(message)
if len(q)<6:
s=.22
h="center"
elif len(q)<11:
s=.32
h="center"
elif len(q) < 16:
s = .45
h = "center"
elif len(q) < 21:
s = .58
h = "center"
elif len(q) < 26:
s = .71
h = "center"
else:
s = .77
h = "center"
screen_manager.get_screen('chats').chat_list.add_widget(Response(text=q, size_hint_x=s,halign=h))
def send(self):
global message, size, halign
if screen_manager.get_screen('chats').text_input != "":
message = screen_manager.get_screen('chats').text_input.text
if len(message)<6:
size=.22
halign="center"
elif len(message)<11:
size=.32
halign="center"
elif len(message) < 16:
size = .45
halign = "center"
elif len(message) < 21:
size = .58
halign = "center"
elif len(message) < 26:
size = .71
halign = "center"
else:
size = .77
halign = "left"
screen_manager.get_screen('chats').chat_list.add_widget(Command(text=message,size_hint_x=size,halign=halign))
Clock.schedule_once(response, 1)
screen_manager.get_screen('chats').text_input.text = ""
global counter
counter = 0
def clear_image(self):
global counter
if counter==0:
self.ids.img2.source ='LOGO.png'
self.ids.img2.reload()
counter += 1
elif counter==1:
self.ids.img2.source ='on.png'
self.ids.img2.reload()
counter += 1
elif counter==2:
self.ids.img2.source ='off.png'
self.ids.img2.reload()
counter += 1
elif counter==3:
self.ids.img2.source =''
self.ids.img2.reload()
counter =0
if __name__ == "__main__":
main().run()
My chats.kv file
<Command>
size_hint_y:None
pos_hint:{"right": .99}
height: self.texture_size[1]
padding: 12,10
theme_text_color: "Custom"
text_color:53/255,56/255,60/255,1
canvas.before:
Color:
rgb: (1, 1,1,1)
RoundedRectangle:
size:self.width,self.height
pos:self.pos
radius:[23,0,23, 23]
<Response>
size_hint_y:None
pos_hint:{"x": .01}
height: self.texture_size[1]
padding: 12,10
theme_text_color: "Custom"
text_color: 53/255,56/255,60/255,1
canvas.before:
Color:
rgb: ( 0,1,1, 1)
RoundedRectangle:
size:self.width,self.height
pos:self.pos
radius:[0,23,23,23]
MDScreen:
bot_name: bot_name
text_input: text_input
chat_list: chat_list
name: "chats"
MDFloatLayout:
canvas :
Color:
rgb:1,1,1, 1
Rectangle:
id: img2
source:'q3.png'
size:self.size
pos:self.pos
MDFloatLayout:
md_bg_color: 0,1,1,1
size_hint_y:.11
pos_hint: {"center_y":.96}
MDLabel:
id: bot_name
text:"OLIVIA"
right_action_items: [["dots-vertical", lambda x: app.callback(x)]]
font_size: "25sp"
pos_hint: {"center_y": .43}
halign: "center"
theme_text_color: "Custom"
text_color: 53/255,56/255,60/255,1
MDIconButton:
icon:"emma.png"
pos_hint:{"center_x":.2,"center_y":.43}
user_font_size:"15sp"
theme_text_color:"Custom"
text_color:53/255,56/255,60/255,1
md_bg_color: 127/255,1, 212/255, 1
MDIconButton:
icon:"video-outline"
pos_hint:{"center_x":.80,"center_y":.43}
user_font_size:"31sp"
theme_text_color: "Custom"
text_color:53/255,56/255,60/255,1
MDIconButton:
text:"M"
pos_hint:{"center_x":.90,"center_y":.43}
user_font_size:"31sp"
theme_text_color: "Custom"
text_color:53/255,56/255,60/255,1
on_release: app.clear_image()
ScrollView:
size_hint_y:.78
background_color:1,1,1,1
pos_hint:{"x":0,"y":.116}
do_scroll_x:False
do_scroll_y:True
BoxLayout:
id:chat_list
orientation:'vertical'
size:(root.width,root.height)
height:self.minimum_height
size_hint:None, None
pos_hint:{"top": 1}
cols:1
spacing:3
MDFloatLayout:
size_hint_y:.08
md_bg_color:0,1,1,1
MDFloatLayout:
size_hint:.8, .75
pos_hint:{"center_x":.43,"center_y":.5}
md_bg_color:0,1,1,1
canvas:
Color:
rgb:1,1,1, 1
RoundedRectangle:
size:self.size
pos:self.pos
radius:[23, 23, 23, 23]
TextInput:
id:text_input
hint_text:"Type your message"
size_hint:1, None
pos_hint:{"center_x":.5,"center_y":.5}
multiline:False
font_size:"18sp"
height:self.minimum_height
cursor_color:1, 170/255, 23/255, 1
cursor_width:"2sp"
foreground_color:53/255,56/255,60/255,1
background_color:0,0,0,0
padding:30
MDIconButton:
icon:"send-outline"
pos_hint:{"center_x":.91,"center_y":.5}
user_font_size:"23sp"
theme_text_color:"Custom"
text_color:1,1,1,1
md_bg_color: 0,1,1,1
on_press:app.send()
Any help would be great
You cannot assign an id to a canvas instruction, but you can assign one to the widget that contains the canvas instruction. And, if you want to change the canvas instruct using python, it will be easier if the canvas instructions are defined in python rather than in kv. In order to do that, you can define an extension of MDFloatLayout that does the canvas instructions:
class MyMDFloatLayout(MDFloatLayout):
def __init__(self, **kwargs):
super(MyMDFloatLayout, self).__init__(**kwargs)
with self.canvas:
Color(1, 1, 1, 1) # set the colour
# Setting the size, position, and source of canvas
self.rect = Rectangle(pos=self.pos,
size=self.size,
source='q3.png')
# Update the canvas when the position/size changes
self.bind(pos=self.update_rect,
size=self.update_rect)
# update function which makes the canvas adjustable.
def update_rect(self, *args):
self.rect.pos = self.pos
self.rect.size = self.size
Then you can use this widget in your kv file in place of the MDFloatLayout that contains the canvas that we want to adjust:
MyMDFloatLayout:
id: img2
# canvas :
# Color:
# rgb:1,1,1, 1
# Rectangle:
# id: img2
# source:'q3.png'
# size:self.size
# pos:self.pos
Note that these canvas instructions in the kv are no longer required
Then, in your python code:
def clear_image(self):
global counter
if counter == 0:
widget = self.root.get_screen('chats').ids.img2
widget.rect.source = 'LOGO.png'
# self.ids.img2.source = 'LOGO.png'
# self.ids.img2.reload()
counter += 1
and similar for the other counter values.
I have a simple app with 2 buttons and their attached callback functions. When a button is pressed, I need to get and use the spos info. I'm using the following code
Python:
class HomeScreen(Screen):
print('Start')
port = "COM7"
bluetooth = serial.Serial(port, 9600)
print("Connected to HC-06")
def button_press_down(self, *args):
print("button pressed #location:")
self.bluetooth.write(b"2")
def button_press_up(self, *args):
print("button pressed #location:")
self.bluetooth.write(b"3")
def on_touch_down(self, touch):
print(touch)
def on_touch_move(self, touch):
pass
class SecondScreen(Screen):
pass
class WindowManager(ScreenManager):
pass
kv=Builder.load_file('touch.kv')
class MainApp(App):
def build(self):
return kv
if __name__ == "__main__":
TestApp = MainApp()
TestApp.run()
.kv file:
#:import utils kivy.utils
WindowManager:
HomeScreen:
SecondScreen:
<HomeScreen>:
name: "button press"
FloatLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
GridLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
rows: 1
cols: 2
padding:10
Button:
text: "Button_1"
id:send_data_bluettooh
on_press:
root.button_press_down()
Button:
text: "Button_2"
id:send_data_bluettooh_2
on_press:
root.button_press_up()
<SecondScreen>:
name: "SecondScreen"
I can get the spos by overwriting the "on_touch_down" fct. The problem there is that my fct button_press_down() is no longer called when I press button 1. Is there any way I can use the spos info and still keep the callback function button_press_down() of my button?
You can get the touch.spos by extending the Button class so that it remembers that information. Here is a modified version of your code that does that:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ListProperty
from kivy.uix.button import Button
from kivy.uix.screenmanager import Screen, ScreenManager
class MyButt(Button):
last_touch_down = ListProperty([])
last_touch_up = ListProperty([])
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
self.last_touch_down = touch.spos
return super(MyButt, self).on_touch_down(touch)
def on_touch_up(self, touch):
if self.collide_point(*touch.pos):
self.last_touch_up = touch.spos
return super(MyButt, self).on_touch_up(touch)
class HomeScreen(Screen):
print('Start')
port = "COM7"
bluetooth = serial.Serial(port, 9600)
print("Connected to HC-06")
def button_press_down(self, button):
print("button pressed #location:", button.last_touch_down)
self.bluetooth.write(b"2")
def button_press_up(self, button):
print("button pressed #location:", button.last_touch_down)
self.bluetooth.write(b"3")
# def on_touch_down(self, touch):
# print(touch)
# return super(HomeScreen, self).on_touch_down(touch)
#
# def on_touch_move(self, touch):
# pass
class SecondScreen(Screen):
pass
class WindowManager(ScreenManager):
pass
kv=Builder.load_file('touch.kv')
class MainApp(App):
def build(self):
return kv
if __name__ == "__main__":
TestApp = MainApp()
TestApp.run()
And replacing Button with MyButt in the kv:
#:import utils kivy.utils
WindowManager:
HomeScreen:
SecondScreen:
<HomeScreen>:
name: "button press"
FloatLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
GridLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
rows: 1
cols: 2
padding:10
MyButt:
text: "Button_1"
id:send_data_bluettooh
on_press:
root.button_press_down(self)
MyButt:
text: "Button_2"
id:send_data_bluettooh_2
on_press:
root.button_press_up(self)
<SecondScreen>:
name: "SecondScreen"
How can make a menu with two or more options when I click on FileBox object in below code? Plesae have a look on the attached pic if you don't know what I mean.
CODE
from kivy.config import Config
Config.set('graphics', 'multisamples', '0')
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
from kivy.lang.builder import Builder
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.boxlayout import BoxLayout
kv = """
<FileBox>
size_hint: None, None
size: 100, 100
canvas.before:
Color:
rgba: (0.337, 0.760, 0.968, 1)
Rectangle:
pos: self.pos
size: self.size
RelativeLayout:
FileBox:
pos_hint: {'center_x':0.5, 'center_y': 0.5}
"""
class FileBox(BoxLayout):
def __init__(self, **kwargs):
super(FileBox, self).__init__(**kwargs)
self.oryg_text = ''
def on_touch_down(self, touch):
if touch.button == 'right':
print('DROP A MENU\n Delete \n Copy')
def function_called_from_drop_menu(self, choosed):
print('CHOOSED', choosed)
sm = Builder.load_string(kv)
class NewApp(App):
def build(self):
self.title = 'Drop Menu'
return sm
if __name__ == '__main__':
NewApp().run()
John must have answered while I was looking at the question. John's answer is perfectly reasonable. My answer is a bit different because it depends on Popup.
from kivy.config import Config
Config.set('graphics', 'multisamples', '0')
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
from kivy.lang.builder import Builder
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.core.window import Window
kv = """
<FileBox>
size_hint: None, None
size: 100, 100
canvas.before:
Color:
rgba: (0.337, 0.760, 0.968, 1)
Rectangle:
pos: self.pos
size: self.size
RelativeLayout:
FileBox:
pos_hint: {'center_x':0.5, 'center_y': 0.5}
<MenuPopup>:
BoxLayout:
orientation: "vertical"
Button:
text: "Delete"
on_press: print("Delete")
Button:
text: "Copy"
on_press: print("Copy")
"""
class MenuPopup(Popup):
pass
class FileBox(BoxLayout):
def __init__(self, **kwargs):
super(FileBox, self).__init__(**kwargs)
self.oryg_text = ''
def on_touch_down(self, touch):
print(touch.pos)
if touch.button == 'right':
print('DROP A MENU\n Delete \n Copy')
popup = MenuPopup(title='Menu',
auto_dismiss=True,
size_hint=(None, None),
size=(180, 180),
pos_hint={'x': touch.pos[0] / Window.width,
'y':(touch.pos[1] - self.height)/ Window.height})
popup.open()
def function_called_from_drop_menu(self, choosed):
print('CHOOSED', choosed)
sm = Builder.load_string(kv)
class NewApp(App):
def build(self):
self.title = 'Drop Menu'
return sm
if __name__ == '__main__':
NewApp().run()
Update
If you don't like the frame by Popup you can also use the class on which Popup is based. It is called ModalView. You also need to delete the title since ModalView has no title.
from kivy.config import Config
Config.set('graphics', 'multisamples', '0')
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
from kivy.lang.builder import Builder
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.uix.modalview import ModalView
from kivy.uix.label import Label
from kivy.core.window import Window
kv = """
<FileBox>
size_hint: None, None
size: 100, 100
canvas.before:
Color:
rgba: (0.337, 0.760, 0.968, 1)
Rectangle:
pos: self.pos
size: self.size
RelativeLayout:
FileBox:
pos_hint: {'center_x':0.5, 'center_y': 0.5}
<MenuPopup>:
BoxLayout:
orientation: "vertical"
Button:
text: "Delete"
on_press: print("Delete")
Button:
text: "Copy"
on_press: print("Copy")
"""
class MenuPopup(ModalView):
pass
class FileBox(BoxLayout):
def __init__(self, **kwargs):
super(FileBox, self).__init__(**kwargs)
self.oryg_text = ''
def on_touch_down(self, touch):
print(touch.pos)
if touch.button == 'right':
print('DROP A MENU\n Delete \n Copy')
popup = MenuPopup(
auto_dismiss=True,
size_hint=(None, None),
size=(180, 180),
pos_hint={'x': touch.pos[0] / Window.width,
'y':(touch.pos[1] - self.height)/ Window.height})
popup.open()
def function_called_from_drop_menu(self, choosed):
print('CHOOSED', choosed)
sm = Builder.load_string(kv)
class NewApp(App):
def build(self):
self.title = 'Drop Menu'
return sm
if __name__ == '__main__':
NewApp().run()
Typically, a DropDown is attached to a Button, but that is not necessary. You can create the DropDown as described in the documentation and instead of binding it to a Button to open it, you can just call open() in your on_touch_down() method. Here is a modified version of your code that does that:
from kivy.config import Config
from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
Config.set('graphics', 'multisamples', '0')
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
from kivy.lang.builder import Builder
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.boxlayout import BoxLayout
kv = """
<FileBox>
size_hint: None, None
size: 100, 100
canvas.before:
Color:
rgba: (0.337, 0.760, 0.968, 1)
Rectangle:
pos: self.pos
size: self.size
RelativeLayout:
FileBox:
pos_hint: {'center_x':0.5, 'center_y': 0.5}
"""
class FileBox(BoxLayout):
def __init__(self, **kwargs):
super(FileBox, self).__init__(**kwargs)
self.oryg_text = ''
def on_touch_down(self, touch):
if touch.button == 'right':
print('DROP A MENU\n Delete \n Copy')
# create the DropDown
self.dropdown = DropDown(auto_dismiss=False)
# add Buttons
btn = Button(text='Delete', size_hint_y=None, height=44)
btn.bind(on_release=self.function_called_from_drop_menu)
self.dropdown.add_widget(btn)
btn = Button(text='Copy', size_hint_y=None, height=44)
btn.bind(on_release=self.function_called_from_drop_menu)
self.dropdown.add_widget(btn)
# open the DropDown
self.dropdown.open(self)
def function_called_from_drop_menu(self, choosed):
print('CHOOSED', choosed)
# dismiss the DropDown
self.dropdown.dismiss()
sm = Builder.load_string(kv)
class NewApp(App):
def build(self):
self.title = 'Drop Menu'
return sm
if __name__ == '__main__':
NewApp().run()
im traying to do a progress bar in kivy, i can build the app with it but it can't be udpated when i run a function (loop) how can i do this please ?
here is my code :
import libraries :
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.properties import ObjectProperty
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.logger import Logger
from kivy.uix.progressbar import ProgressBar
My builder :
Builder.load_string("""
<RootWidget>:
pb : pb
some code here
ActionView:
ActionPrevious:
with_previous: False
ActionButton:
text: 'Run analysis'
color: 29/255, 185/255, 84/255, 1
on_release: root.clicked()
BoxLayout:
ProgressBar:
id : pb
min :0
max :1
pos_hint: {'x': .1}
size_hint_x :.8
size_hint_y :.5
value: 0
""")
other code with my update_bar function:
class Myapp(BoxLayout):
pb = ProgressBar()
box = ObjectProperty()
def __init__(self, *args, **kwargs):
super(Myapp, self).__init__(*args, **kwargs)
def update_bar(self,dt=None):
self.ids.pb.value = self.ids.pb.value
here is the problem : the progress bar is not updated each iteration, but it take the last value (for i = 9999)
def clicked(self):
for i in range(10000) :
self.ids.pb.value = i/10000
Clock.schedule_interval(self.update_bar,0.5)
self.update_bar()
Build my app :
class EventScreen(App,Myapp):
def on_stop(self):
Logger.critical("Good bye")
def build(self):
return Myapp()
if __name__ == "__main__":
EventScreen().run()
thank you in advance
Use Clock.create_trigger() to update progress bar.
Snippet
def __init__(self, *args, **kwargs):
super(Myapp, self).__init__(*args, **kwargs)
self.update_bar_trigger = Clock.create_trigger(self.update_bar)
def clicked(self):
self.i = 0
self.update_bar_trigger()
def update_bar(self, dt):
if self.i <= 10000:
self.ids.pb.value += self.i
self.i += 1
self.update_bar_trigger()
I want to use Kivy to rotate an image of a 45RPM record. I discovered that this can be done using an image widget on a scatter layout. However I can't seem to find the code to make the image of the 45RPM record be resized to match the size of the window. I've tried for hours different iterations of code and I've become quite frustrated. Full code below with link to image.
Any Suggestions?
Appreciated In Advance.
....brad....
Image for code at: https://drive.google.com/open?id=0B-T2cvsAoZ2vQ2hmaHM0SnlQVlU
# Modified from https://gist.github.com/tshirtman/6222891
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.lang import Builder
from kivy.clock import Clock
kv = """
BoxLayout:
Widget:
Scatter:
center: self.parent.center
do_rotation: False
do_translation: False
do_scale: False
rotation: app.angle
Image:
source: '45rpm.png'
"""
class RotateRecordApp(App):
angle = NumericProperty(0)
def build(self):
Clock.schedule_interval(self.update_angle, 0)
return Builder.load_string(kv)
def update_angle(self, dt, *args):
self.angle += dt * 100
if __name__ == '__main__':
RotateRecordApp().run()
Use scale property:
# Modified from https://gist.github.com/tshirtman/6222891
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.lang import Builder
from kivy.clock import Clock
kv = """
BoxLayout:
Widget:
# Gray background
canvas.before:
Color:
rgba: 0.1, 0.1, 0.1, 1
Rectangle:
pos: self.pos
size: self.size
Scatter:
center: self.parent.center
do_rotation: False
do_translation: False
do_scale: False
rotation: app.angle
scale: min(self.parent.width/self.width,\
self.parent.height/self.height)
Image:
source: '45rpm.png'
"""
class RotateRecordApp(App):
angle = NumericProperty(0)
def build(self):
Clock.schedule_interval(self.update_angle, 0)
return Builder.load_string(kv)
def update_angle(self, dt, *args):
self.angle += dt * 100
if __name__ == '__main__':
RotateRecordApp().run()
Output:
I added a gray background just to improve image visibility.