How Can I Animate a Label in Kivy? - python

Ok, My question goes this way How Can I Animate a Label in Kivy, My apologies if this question is annoyingly way too easy :)
Here is the Label in which I want animation. Can I have edits of the code in the comments?
Actually, I am obsessed with this script, racking my brains off to know the way to animate this thingy!! Pls Help!..
import kivy
from kivy.app import App
from kivy.uix.label import Label
class MyApp(App):
def build(self):
lu = Label(text = "This is a label! Pls help me with Animation!")
return lu
if __name__ == '__main__':
MyApp().run()

If you want to update text on Label every few seconds then you can use Clock and Clock.schedule_interval(function_name, seconds) to execute function_name(dt) every seconds and in this function you should change text in Label
Minimal example which displays current time.
from kivy.app import App
from kivy.uix.label import Label
from kivy.clock import Clock
import datetime
def update_label(dt):
new_text = datetime.datetime.now().strftime('%H:%M:%S')
label.text = new_text
#print(new_text)
label = None # create global variable to access the same `label` in two different functions
class MyApp(App):
def build(self):
global label # inform function to assign `Label` to global variable
label = Label(text="???")
Clock.schedule_interval(update_label, 1)
return label
#Clock.schedule_interval(update_label, 1)
if __name__ == '__main__':
MyApp().run()
EDIT:
Another example which scroll text
from kivy.app import App
from kivy.uix.label import Label
from kivy.clock import Clock
import datetime
label = None
text = 'Hello World of Python!'
text_length = len(text)
index = 0
temp_text = text + ' ' + text
def update_label(dt):
global index
label.text = temp_text[index:index+15]
index += 1
if index >= text_length:
index = 0
class MyApp(App):
def build(self):
global label
label = Label(text="???")
Clock.schedule_interval(update_label, 0.20)
return label
if __name__ == '__main__':
MyApp().run()
EDIT:
For numerical values you can use Animation.
Here is blinking text.
It changes color to black (in 0.2 second) and next it change back to white (in 0.2 second). And it repeats it.
from kivy.app import App
from kivy.uix.label import Label
from kivy.animation import Animation
class MyApp(App):
def build(self):
label = Label(text='Hello World of Python!')
anim = Animation(color=(0, 0, 0, 1), duration=.2) + Animation(color=(1, 1, 1, 1), duration=.2)
anim.repeat = True
anim.start(label)
return label
if __name__ == '__main__':
MyApp().run()

Related

A clock with kivy python

I would like to display the time with kivy. I don't want that the label use the whole page. How can I do ?
I want it to appear the same as in the following photo:
from kivy.app import App
from datetime import datetime
from datetime import timedelta
from kivy.clock import Clock
from kivy.uix.label import Label
class myApp(App):
def build(self):
self.now = datetime.now()
# Schedule the self.update_clock function to be called once a second
Clock.schedule_interval(self.update_clock, 1)
self.my_label = Label(text= self.now.strftime('%H:%M:%S'))
return self.my_label # The label is the only widget in the interface
def update_clock(self, *args):
# Called once a second using the kivy.clock module
# Add one second to the current time and display it on the label
self.now = self.now + timedelta(seconds = 1)
self.my_label.text = self.now.strftime('%H:%M:%S')
myApp().run()

Kivy: How to make label size and size of a canvas equal?

I have made a square shaped grid of labels using Gridlayout. Now i want to add a background color the labels(each having different rectangles). I tried to do this by the following code.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Rectangle, Color
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
class MyGrid(FloatLayout):
def __init__(self,**kwargs):
super(MyGrid,self).__init__(**kwargs)
self.grid=GridLayout()
self.grid_size=4
self.grid.cols=self.grid_size
for k in range(self.grid_size):
for i in range(self.grid_size):
with self.grid.canvas:
Rectangle(size=(100,100),pos=(k*160+100,i*160+100),source="52852.JPG")
for h in range(self.grid_size):
for j in range(self.grid_size):
self.grid.add_widget(Label(text="labwl"+str(h)+str(j),size=(100,100),pos=(h*160+100,j*160+100)))
self.add_widget(self.grid)
class GameApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
GameApp().run()
In this code if I do not specify "self.grid.cols" it generates a warning in the python console and also when the window is turned to full screen mode the rectangles from canvas retain there original size and position but the labels do not. I want to get the labels in front of the rectangles of canvas and they should also retain the size of the screen as specified. Moreover if I change the "self.grid.size" to any other number it should make the grid of labels of that length and corresponding number of canvas too. I tried float layout for this purpose also but it was of no help. The canvas rectangles and labels should fit in the window whatever the size of window has. It would be better if I can get the solution to above problem written in python file(not in .kv file). If you know any other solution to this problem or any other widget please let me know. Like for button widget we can specify the background color and text also your can add any of that widget which will do above task. You should replace the "source" in the rectangle canvas to any known image file. I hope you understand. If you do not please do let me know. :)
Setting the Widgets to not change size or pos is the easiest solution. Basically just use size_hint=(None, None) and don't use the GridLayout:
from kivy.app import App
from kivy.graphics import Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
class MyGrid(FloatLayout):
def __init__(self,**kwargs):
super(MyGrid,self).__init__(**kwargs)
self.grid_size=4
for k in range(self.grid_size):
for i in range(self.grid_size):
with self.canvas:
Rectangle(size=(100,100),pos=(k*160+100,i*160+100),source="52852.JPG")
for h in range(self.grid_size):
for j in range(self.grid_size):
self.add_widget(Label(text="labwl"+str(h)+str(j),size=(100,100),pos=(h*160+100,j*160+100), size_hint=(None, None)))
class GameApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
GameApp().run()
To make the Rectangles and Labels change pos and size is a bit more complex. In the modified version of your code below, I keep lists of the Labels and the Rectangles, and bind the adjust_common_size() method to run whenever the size of MyGrid changes. That method then adjusts the size and pos of the Labels and Rectangles to match:
from kivy.app import App
from kivy.properties import ListProperty
from kivy.graphics import Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
class MyGrid(FloatLayout):
common_size = ListProperty((100, 100))
def __init__(self,**kwargs):
super(MyGrid,self).__init__(**kwargs)
self.grid_size=4
self.rects = []
self.labels = []
for k in range(self.grid_size):
one_row = []
self.rects.append(one_row)
for i in range(self.grid_size):
with self.canvas:
one_row.append(Rectangle(size=self.common_size,pos=(k*160+100,i*160+100),source="52852.JPG"))
for h in range(self.grid_size):
one_row = []
self.labels.append(one_row)
for j in range(self.grid_size):
label = Label(text="labwl"+str(h)+str(j),size=self.common_size,pos=(h*160+100,j*160+100), size_hint=(None, None))
one_row.append(label)
self.add_widget(label)
self.bind(size=self.adjust_common_size)
def adjust_common_size(self, instance, new_size):
self.common_size = (new_size[0] * 0.9 / self.grid_size, new_size[1] * 0.9 / self.grid_size)
for k in range(self.grid_size):
for i in range(self.grid_size):
adjusted_pos = (k * new_size[0] / self.grid_size, i * new_size[1] / self.grid_size)
rect = self.rects[k][i]
label = self.labels[k][i]
label.size = self.common_size
label.pos = adjusted_pos
rect.size = self.common_size
rect.pos = adjusted_pos
class GameApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
GameApp().run()
Using a ListProperty for the common_size is not necessary, but would be handy if you decide to use kv.
This is an interesting question. Here is a better way to make the Rectangle and the Label match. The code below uses the GridLayout, but defines MyLabel to include its own Rectangle and to keep its Rectangle matched in pos and size:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
class MyLabel(Label):
def __init__(self, **kwargs):
super(MyLabel, self).__init__(**kwargs)
with self.canvas.before:
self.rect = Rectangle(size=self.size,pos=self.pos,source="52852.JPG")
self.bind(size=self.adjust_size)
self.bind(pos=self.adjust_pos)
def adjust_pos(self, instance, new_pos):
self.rect.pos = new_pos
def adjust_size(self, instance, new_size):
self.rect.size = new_size
class MyGrid(FloatLayout):
def __init__(self,**kwargs):
super(MyGrid,self).__init__(**kwargs)
self.grid=GridLayout()
self.grid_size=4
self.grid.cols=self.grid_size
for h in range(self.grid_size):
for j in range(self.grid_size):
self.grid.add_widget(MyLabel(text="labwl"+str(h)+str(j),size=(100,100),pos=(h*160+100,j*160+100)))
self.add_widget(self.grid)
class GameApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
GameApp().run()
With this approach, you don't have to create the Rectangles in the MyGrid at all, since each Label creates its own.

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()

Kivy Python very basic Binding of Label Text

I know this might be a very basic question, but after spending hours wrapping my head around it I still can't figure it out.
I basically just want to bind the text of a label to a variable in the python code. lets call it value. however it should get updated everytime I run a loop Clock.schedule_interval(RootWidget.update, 1.0/1.0)
here is the python, simplified so its basically just the time, which is also printed just to see if it is actually working.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.clock import Clock
from kivy.core.window import Window
import time
class RootWidget(FloatLayout):
def update(self, *args):
value = time.time()
print value
self.ids.value_label.text = str(value)
class MainApp(App):
def build(self):
Window.size = (800, 480)
r = RootWidget()
Clock.schedule_interval(r.update, 1)
print 'build running'
return r
def on_pause(self):
return True
if __name__ == '__main__':
MainApp().run()
the kv file looks as such:
<RootWidget>:
Label:
id: value_label
text:
y: 20.0
x: 0.0
width: 100.0
italic: False
height: 50.0
Clock.schedule_interval(RootWidget.update, 1.0/1.0)
You need to schedule the update method of an instance, not the class itself.
For instance:
r = RootWidget()
Clock.schedule_interval(r.update, 1)
return r
The clock will pass some arguments by default, so you should also declare the update method to accept these. If you don't want to use them then you can just do:
def update(self, *args):
...

live input managment in kivy

In a part of my app I want to show a list of numbers (1 to 100) and when the "filter" button selected list numbers change (1 to 10). I've tried several solutions like this but none of them worked !
what is the problem in your idea?
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.listview import ListView
from kivy.uix.label import Label
class SingleApp(App):
def build(self):
hole = BoxLayout()
right = BoxLayout(size_hint_x=0.2)
left = BoxLayout(size_hint_x=0.8, orientation='vertical')
side_panel = ListView(item_strings=['no %i' %i for i in range(100)])
right.add_widget(side_panel)
btn = Button(text='Show 1 to 10 ')
lbl = Label(text='Show list of numbers (test)')
btn2 = Button(text='reset')
left.add_widget(btn)
left.add_widget(lbl)
left.add_widget(btn2)
hole.add_widget(right)
hole.add_widget(left)
btn.bind(on_press=self.change(right))
btn2.bind(on_press=self.reset(right))
return hole
def change(self, side):
side.clear_widgets()
side_panel = ListView(item_strings=['NUMBER %i' %i for i in range(10)])
side.add_widget(side_panel)
def reset(self, side):
side.clear_widgets()
side_panel = ListView(item_strings=['no %i' %i for i in range(100)])
side.add_widget(side_panel)
if __name__=='__main__':
SingleApp().run()

Categories

Resources