Giving sizes to the widget and drawing in it - python

I would like to create a widget with a fixed size and background. It is to be added first in BoxLayout. I would like to draw a line inside this widget so that it is visible only in it and placed in relation to it.
By entering (0,0) the position of the line I mean the beginning of the widget and not the entire application window.
How to achieve this effect?
from random import random
from kivy.app import App
from kivy.graphics import Color, Ellipse, Line
from kivy.uix.button import Button
from kivy.uix.widget import Widget
class CombWidget(Widget):
pass
class MyPaintWidget(Widget):
def __init__(self, **kwargs):
super(MyPaintWidget, self).__init__(**kwargs)
class MyPaintApp(App):
def build(self):
return CombWidget()
if __name__ == '__main__':
MyPaintApp().run()
and kv file
<CombWidget>:
BoxLayout:
orientation: 'vertical'
size: root.size
padding: 20
spacing: 50
MyPaintWidget:
size: 400, 400
size_hint: 400, 400
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
canvas:
Color:
rgba: 0, 0, 0, 1
Line:
points: 0, 0, 200, 200
Button:
text: "Hallo"
Button:
text: "Hallo 1"
Button:
text: "Hallo 2"
Right now I have something like this:
But I would like to get something like this:
I would like to be able to draw only in this widget and provide positions of the drawn elements in relation to it.

You just need to adjust the points of the Line:
canvas:
Color:
rgba: 0, 0, 0, 1
Line:
points: self.x, self.y, self.x + 200, self.y + 200

Related

KIvy using a circles position to place a button

I have drawn a circle. I want to place a button at the same position of the circle. How can I get the circle's x and y coordinates. My code(in kv file):
MainWidget:
<MainWidget>:
canvas.after:
Color:
rgb: 1, 0, 0
Ellipse:
id: point
size: 100, 100
pos: 100, root.y1
Button:
id: No1
pos: point.pos
on_press: root.move()
It shows "NameError: name 'point' is not defined"
Put your widgets in BoxLayout. You can't use id for canvas, you should use groups.
Circle above the button.
from kivy.lang import Builder
from kivy.app import App
KV = '''
Screen:
BoxLayout:
orientation: 'vertical'
spacing: 10
BoxLayout:
size_hint_x: None
pos_hint: {'center_x': .5}
canvas.after:
Color:
rgb: 1, 0, 0
Ellipse:
size: 100, 100
pos: self.pos
BoxLayout:
Button:
id: No1
on_press: pass
'''
class Test(App):
def build(self):
return Builder.load_string(KV)
Test().run()
Circle in the button.
from kivy.lang import Builder
from kivy.app import App
KV = '''
Screen:
BoxLayout:
padding: 50
Button:
on_press: pass
canvas.after:
Color:
rgb: 1, 0, 0
Ellipse:
size: self.size
pos: self.pos
'''
class Test(App):
def build(self):
return Builder.load_string(KV)
Test().run()
So you can place the circle at the same position as the button.
Ellipse:
size: 100, 100
pos: self.pos

Kivy moving label inside FloatLayout

Hello I want to place a welcome message at the top of the app (Like the photo this)
I use a FloatLayout for my entire screen (since I want to add some other widgets later) but the problem is the label won't position itself at the center but like this
Here is my python code:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
class MainPage(FloatLayout):
pass
class SmartMirrorApp(App):
def build(self, **kwargs):
return MainPage()
if __name__ == "__main__":
SmartMirrorApp().run()
And this is my kv file:
#:kivy 1.10.1
<MainPage>:
canvas:
Color:
rgba: 1,0,1,0.5
Rectangle:
size: self.size
pos: self.pos
Label:
canvas:
Color:
rgba: 1,0,0,0.5
Rectangle:
size: self.size
pos: self.pos
text: "Welcome, you look beautiful today!"
font_size: 20
size_hint: None, None
size: self.texture_size
pos_hint: {'x': 0.5, 'y': 0.9}
Now if instead of putting 'x':0.5 inside the pos_hint dictionary I use center_x: root.center_x
the image moves to the desired position ONLY if I resize the window but it starts at the position of the second image.
For your pos_hint, use:
pos_hint: {'center_x': 0.5, 'top': 0.9}
That will center the Label horizontally, and the top of the Label will be at 90% of the MainPage height.

can't position label with round button to top corner kivy

I am trying to get a label with in it a rounded button to be placed in top left corner, but can't seem to get it done.
tried pos_hint in both < BackLabel > and < SubScreen >-->backlabel.
excerpts from my code:
tryout.py:
class RoundedButton(Button):
pass
class BackLabel(Label):
def __init__(self, **kwargs):
super(BackLabel, self).__init__(**kwargs)
self.RoundedButton=RoundedButton()
self.add_widget(self.RoundedButton)
class SubScreen(Screen):
def __init__(self, **kwargs):
super(SubScreen, self).__init__(**kwargs)
self.BackLabel = BackLabel(id='bl')
self.add_widget(self.BackLabel)
self.OpenLink = Button(id= 'forward')
self.add_widget(self.OpenLink)
self.Footer = Label(id='footer')
self.add_widget(self.Footer)
.kv file:
<BackLabel#Label>:
background_color: 0,0,0,0
canvas.before:
Color:
rgb: 0, 1, 0
RoundedRectangle:
size: [100,100]
radius: [50,]
<RoundedButton#Button>:
background_color: 0,0,0,0 # the last zero is the critical on, make invisible
canvas.before:
Color:
rgba: (.4,.4,.4,1) if self.state=='normal' else (0,.7,.7,1) # visual feedback of press
RoundedRectangle:
size: [100,100]
radius: [50,]
text:'<--Back'
on_release: app.root.current = 'mainmenu'
<SubScreen>
name: 'submenu'
BackLabel:
id: 'bl'
It is difficult to interpret exactly what you are attempting to do. For example, why are you adding a RoundedButton to a BackLabel in the __init__() method of your BackLabel? Anyway, here is a simpler version of your code that does what I think you want. A couple things to note: In order to position a Widget meaningfully, it must have a reasonable size. The default size of any Widget is the same as its parent, so positioning it doesn't really make sense. So my code below sets the size of your RoundButton (which requires size_hint to be (None, None). Finally, the position can be set (as in the SubScreen rule in the kv below):
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
class SubScreen(Screen):
pass
Builder.load_string('''
<RoundedButton#Button>:
size_hint: (None, None)
size: (100, 100)
background_color: 0,0,0,0 # the last zero is the critical on, make invisible
canvas.before:
Color:
rgba: (.4,.4,.4,1) if self.state=='normal' else (0,.7,.7,1) # visual feedback of press
RoundedRectangle:
pos: (self.center_x - 50, self.center_y - 50)
size: self.size
radius: [50,]
text:'<--Back'
on_release: app.root.current = 'mainmenu'
<SubScreen>
name: 'submenu'
RoundedButton:
pos: (0, root.height-self.height)
''')
class TheApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(SubScreen())
return sm
TheApp().run()

Kivy GUI - fill color in circle like water fill in circle container level wise

As shown in the image above I need to code a .kv file in the Kivy GUI so I can show a circle filling with color as a value increase. For 0 value it is empty as value increase circle is fill with color.
How can I do that?
That kind of effect can be done by creating a mask for this you can use Stencil instructions as shown below:
from kivy.app import App
from kivy.lang import Builder
main_widget_kv = '''
BoxLayout:
border: 10
WaterFill:
level: slider.value_normalized
color: 1, 1, 0
Slider:
id: slider
orientation: 'vertical'
value: 50
<WaterFill#Widget>:
level: 0.1
width: self.height
size_hint: None, 1
color: 0, 0, 1
canvas:
StencilPush
Ellipse:
pos: root.pos
size: root.size
StencilUse
Color:
rgb: root.color
Rectangle:
pos: root.pos
size: (root.width, root.level*root.height)
StencilUnUse
StencilPop
'''
class TestApp(App):
def build(self):
return Builder.load_string(main_widget_kv)
if __name__ == '__main__':
TestApp().run()
Update:
The following example shows an example of how to update the height value using a method with the help of Clock:
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.widget import Widget
from kivy.uix.anchorlayout import AnchorLayout
from kivy.lang import Builder
Builder.load_string("""
<WaterFill>:
level: 0.0
width: self.height
size_hint: None, 1
color: 0, 0, 1
canvas:
StencilPush
Ellipse:
pos: root.pos
size: root.size
StencilUse
Color:
rgb: root.color
Rectangle:
pos: root.pos
size: (root.width, root.level*root.height)
StencilUnUse
StencilPop
""")
class WaterFill(Widget):
def __init__(self, *args, **kwargs):
Widget.__init__(self, *args, **kwargs)
self.delta = 0.01
Clock.schedule_interval(self.on_timeout, 0.05)
def on_timeout(self, *args):
self.level += self.delta
if self.level >= 1:
self.delta = -0.01
elif self.level <= 0:
self.delta = 0.01
class TestApp(App):
def build(self):
lay = AnchorLayout(anchor_x='center', anchor_y='center')
lay.add_widget(WaterFill())
return lay
if __name__ == "__main__":
TestApp().run()

Loading Image in Kivy

I want an image to be displayed in the center of the layout. I could not figure it out. Is there any way to display the image on the center of the layout and be there till the animation is stopped?
Here is my code.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.animation import Animation
from kivy.properties import NumericProperty
Builder.load_string('''
<Loading>:
canvas:
Rotate:
angle: root.angle
origin: self.center
Color:
rgb: .0, 0, -.1
Ellipse:
size: min(self.size), min(self.size)
pos: 0.5*self.size[0] - 0.5*min(self.size), 0.5*self.size[1] - 0.5*min(self.size)
Color:
rgb: .5, 0, 1
Ellipse:
size: 30, 30
pos: 0.5*root.size[0]+25, 0.8*root.size[1]-25
''')
class Loading(FloatLayout):
angle = NumericProperty(0)
def __init__(self, **kwargs):
super(Loading, self).__init__(**kwargs)
anim = Animation(angle = 1009, duration=2.5)
anim += Animation(angle = 1900, duration=2.5)
anim.repeat = True
anim.start(self)
def on_angle(self, item, angle):
if angle == 360:
item.angle = 0
class TestApp(App):
def build(self):
return Loading()
TestApp().run()
I don't think your canvas should be "loose" like that. Place it inside of a Widget, this will let you use Kivy's various layouts to arrange things. It will also let you insert an Image above the widget and without making the image spin around.
A second thing, use rgba so you can specify transparencies for the background. This example below works for me, just replace the Builder string with this:
"""<Loading>:
FloatLayout:
Image:
source: 'logo.png'
Widget:
canvas:
Rotate:
angle: root.angle
origin: self.center
Color:
rgba: 1, 1, 1, 0
Ellipse:
size: min(self.size), min(self.size)
pos: 0.5*self.size[0] - 0.5*min(self.size), 0.5*self.size[1] - 0.5*min(self.size)
Color:
rgba: .5, 0, 1, 1
Ellipse:
size: 30, 30
pos: 0.5*root.size[0]+25, 0.8*root.size[1]-25
Color:
rgba: 0.5, 0, 1"""
I also attached our Departments logo that I used for the example. I leave it to you to tweak sizes and add the appropriate resizing calls.logo

Categories