update: After discussing with others, I decided that it is a bit silly question. I wanted to animate Bezier curve with changed width, but it has no width property. with Line Bezier, I can change width, but then can't animate.
I can't change witdh of Bezier curve like Line.
here is the code:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import *
class MyLayout(Widget):
def __init__(self):
super(MyLayout, self).__init__()
with self.canvas:
self.L=Bezier(points=[200,450,500,300,600,150],width=12)
self.k=Line (bezier=[100,350,400,200,500,50 ],width=12)
class MyApp(App):
def __init__(self):
super(MyApp, self).__init__()
def build(self):
return MyLayout()
if __name__=="__main__":
MyApp().run()
and outupt:
the problem is,
the upper curve isn't width=12.
I think that's because Kivy's Bezier Class has no attribute width cuz when I do it on kv lang, it gives me AttributeError: 'kivy.graphics.vertex_instructions.Bezier' object has no attribute 'width'. Well, why not using Line with bezier ? I want to use Animation on it and when I try to on Line with bezier, I get AttributeError: attribute 'bezier' of 'kivy.graphics.vertex_instructions.Line' objects is not readable.
so the question,
how can I change width of Bezier. if it is not possible, is there any way like finding the y of cruve (or ys) for given x so I can put Ellipse on these points and resize them to simulate width ?
thanks and pardon my english ♥
The line can use bezier:, example:
Line:
bezier:[n1,n2,n3,n4]
width:3
This is a Line, not a Bezier, but you get the same result...
One example:
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout
posicao=[]
class Draw(BoxLayout):
def __init__(self, **kwargs):
super(Draw, self).__init__(**kwargs)
def on_touch_down(self,touch):
posicao.append(touch.pos)
def on_touch_up(self,touch):
posicao.clear()
def on_touch_move(self,touch):
Line = Builder.load_string(
"""
FloatLayout:
canvas:
Color:
rgba:11,.1,1,1
Line:
points: {pos}
width:14
""".format(pos=(touch.pos, posicao[0])))
self.add_widget(Line)
posicao.clear()
posicao.append(touch.pos)
class Code(App):
def build(self):
return Draw()
if __name__ == '__main__':
Code().run()
Or:
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import *
posi = []
Builder.load_string(
"""
<Draw>:
""")
class Draw(BoxLayout):
def __init__(self, **kwargs):
super(Draw, self).__init__(**kwargs)
def on_touch_down(self,touch):
posi.clear()
posi.append(touch.pos)
def on_touch_up(self,touch):
posi.clear()
def on_touch_move(self,touch):
with self.canvas:
Line(points=[posi[0], touch.pos],width=14)
posi.clear()
posi.append(touch.pos)
class Code(App):
def build(self):
return Draw()
if __name__ == '__main__':
Code().run()
The Bezier has no width property, but the Line does. So you can animate that width. An easy way to do that is by animating a NumericProperty that holds the width. Here is a modified version of your code that does that:
from kivy.animation import Animation
from kivy.app import App
from kivy.clock import Clock
from kivy.properties import NumericProperty
from kivy.uix.widget import Widget
from kivy.graphics import *
class MyLayout(Widget):
line_width = NumericProperty(12)
def __init__(self):
super(MyLayout, self).__init__()
with self.canvas:
self.L=Bezier(points=[200,450,500,300,600,150],width=self.line_width)
self.k=Line (bezier=[100,350,400,200,500,50 ],width=self.line_width)
def on_line_width(self, instance, new_width):
self.k.width = new_width
class MyApp(App):
def build(self):
Clock.schedule_once(self.anim)
return MyLayout()
def anim(self, dt):
a = Animation(line_width=3)
a.start(self.root)
if __name__=="__main__":
MyApp().run()
If you build the Line in kv, then you don't even need the on_line_width() method since kivy will do the binding for you.
Related
I'm trying to draw a rectangle and place it on the screen depending
on the size of the window / screen.
I've got this but it doesn't work:
with self.canvas:
Color: xyz
Rectangle(pos=(Window.size[0]-50,Window.size[1]-50),size=(50,50))
This didn't have any effect either:
with self.canvas:
Color: xyz
Rectangle(pos=(Window.height-50,Window.width-50),size=(50,50))
Runnable example:
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.app import App
from kivy.graphics import *
Window.size = (375, 812)
class Temporary(Widget):
def __init__(self, **kwargs):
super(Temporary, self).__init__(**kwargs)
with self.canvas:
Color(255/255.0, 99/255.0, 71/255.0)
Rectangle(pos=(0,0),size=(50,50))
class MainApp(App):
def build(self):
return Temporary()
if __name__ == '__main__':
MainApp().run()
I've managed to make it work as I intended:
class Temporary(Widget):
def __init__(self, **kwargs):
super(Temporary, self).__init__(**kwargs)
with self.canvas:
Color(255/255.0, 99/255.0, 71/255.0)
Rectangle(pos=(Window.size[0] / 2,Window.size[1] / 2),size=(50,50))
Nothing else worked. The above will do the trick.
I have a very simplistic case of a window with a single button. With a button release I want to pop up a modal view with some text on it. In every button release I create and open an instance of ModalView and it works:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.modalview import ModalView
from kivy.uix.label import Label
class AButton(Button):
def on_release(self, *largs):
view = ModalView(size_hint=(None, None), size=[200, 200])
view.add_widget(Label(text='I am a modal view'))
view.open()
class MyApp(App):
def build(self):
return AButton()
if __name__ == '__main__':
MyApp().run()
Now let's say I want to create a subclass of ModalView so I don't have to specify size_hint and size every time I pop up a modal view. This is the code after that change:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.modalview import ModalView
from kivy.uix.label import Label
from kivy.properties import ListProperty
class AButton(Button):
def on_release(self, *largs):
view = ModalView2()
view.add_widget(Label(text='I am a modal view'))
view.open()
class ModalView2(ModalView):
size_hint = ListProperty([None, None])
size = ListProperty([200, 200])
def __init__(self, **kwargs):
super(ModalView2, self).__init__(**kwargs)
class MyApp(App):
def build(self):
return AButton()
if __name__ == '__main__':
MyApp().run()
ModalView and Label position get totally messed up. I tried with anchor_x and anchor_y in ModalView2 in an attempt to fix the label position with no luck. What am I doing wrong?
The ModalView already has size_hint and size attributes, so you don't need to create new ones, just set the existing attributes to the values you want:
class ModalView2(ModalView):
def __init__(self, **kwargs):
super(ModalView2, self).__init__(**kwargs)
self.size_hint = (None, None)
self.size = (200, 200)
I want to draw circle in center of FloatLayout. With my knowledges I obtained only default values for this. Why circle in showed code isn't red? Can You explain me process for obtaining necessary coordinates, please?
import kivy
from kivy.config import Config
kivy.config.Config.set('graphics','resizable', False)
from kivy.app import App
from kivy.graphics import Color, Ellipse
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
class Scene(FloatLayout):
def __init__(self, **kwargs):
super(Scene, self).__init__(**kwargs)
def draw_circle(self):
with self.canvas:
Color=(1,0,0)
circ = Ellipse(pos = (self.center_x, self.center_y), size=(20,20))
def on_touch_down(self, touch):
pass
class Game(BoxLayout):
def __init__ (self,**kwargs):
super(Game, self).__init__(**kwargs)
self.orientation = 'vertical'
but1 = Button(text = 'button 1')
self.add_widget(but1)
self.scene = Scene()
self.add_widget(self.scene)
class TestApp(App):
def build(self):
game = Game()
game.scene.draw_circle()
return game
if __name__ == '__main__':
TestApp().run()
You should define the size of your float layout when you create it.
self.scene = Scene(size=(300, 300))
Then your circle should be at the center of the FloatLayout dimensions.
I also think FloatLayout is better used with size_hint and pos_hint instead of fixed coordinates.
You can call draw_circle with Clock to make sure the layout is completely initiated first.
Then make sure to create your color like this Color(1, 0, 0). Not Color = ()
from kivy.config import Config
Config.set('graphics','resizable', False)
from kivy.app import App
from kivy.graphics import Color, Ellipse
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.clock import Clock
class Scene(FloatLayout):
def draw_circle(self, dt):
with self.canvas:
Color(1,0,0)
circ = Ellipse(pos = (self.center_x, self.center_y), size=(20,20))
class Game(BoxLayout):
def __init__ (self,**kwargs):
super(Game, self).__init__(**kwargs)
self.orientation = 'vertical'
but1 = Button(text = 'button 1')
self.add_widget(but1)
self.scene = Scene()
self.add_widget(self.scene)
class TestApp(App):
def build(self):
game = Game()
Clock.schedule_once(game.scene.draw_circle) # call draw_circle on next frame
return game
if __name__ == '__main__':
TestApp().run()
I'm trying to make some text in a label fade in using the animation tool in kivy but I can't get it to work and I found NOTHING on the internet to help anywhere.
Heres the code:
.py:
class TestScreen(Screen):
def animate (self):
anim = Animate(opacity=1, duration=2)
anim.start(self.lbl)
.kv
<TestScreen>
lbl: label
Label
id: label
text: "Welcome"
change Animate with Animation
opacity=1 means label is visible, what you want is opacity=0
you should call animate function
somewhere
Here's fully working example (Python 2.7):
from __future__ import absolute_import, division, print_function, unicode_literals
__metaclass__ = type
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.animation import Animation
Builder.load_string(b'''
<RootWidget>:
lbl: label
Label
id: label
text: "Welcome"
''')
class RootWidget(Screen):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
self.animate()
def animate(self):
anim = Animation(opacity=0, duration=2)
anim.start(self.lbl)
class TestApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
TestApp().run()
how do i change the text of a label to the value of the slider immediately.
this is my current code
import kivy
kivy.require('1.10.0')
from kivy.app import App
from kivy.uix.slider import Slider
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label``
class app(App):
def build(self):
layout = BoxLayout(orientation='vertical')
slide = Slider(min=-100, max=100,value=0)
label = Label(text=str(slide.value))
layout.add_widget(slide)
layout.add_widget(label)
return layout
app().run()
i want the answer in python
You need to create a Kivy Property and bind the slider value to an on_ event where you can then update the label's text. Here's one way to do that:
from kivy.app import App
from kivy.uix.slider import Slider
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.properties import NumericProperty
import kivy
kivy.require('1.10.0')
class Container(BoxLayout):
slider_val = NumericProperty(0)
def __init__(self, *args, **kwargs):
super(Container, self).__init__(*args, **kwargs)
self.orientation = 'vertical'
slide = Slider(min=-100, max=100, value=0)
slide.fbind('value', self.on_slider_val)
self.label = Label(text=str(self.slider_val))
self.add_widget(slide)
self.add_widget(self.label)
def on_slider_val(self, instance, val):
self.label.text = str(val)
class app(App):
def build(self):
return Container()
app().run()