Error when making rounded corners for buttons in Kivy v2.0.0 - kivy

I'm trying to make rounded corners for a button in a kv file like so:
test.kv
#:kivy 2.0
<CustomGridLayout>
GridLayout:
cols: 1
RoundedButton:
text: 'Button #1'
<RoundedButton#Button>
background_color: (51/255.0, 51/255.0, 51/255.0, 1)
background_normal: ''
background_down: ''
size_hint: None, None
size: 300, 50
canvas.before:
Color:
rgba: self.background_color
RoundedRectangle:
size: self.size
pos: self.pos
radius: 10,
test.py
import kivy
kivy.require('2.0.0')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
class CustomGridLayout(Widget):
pass
class TestApp(App):
def build(self):
Window.size = (360,640)
Window.clearcolor = (238/255.0, 238/255.0, 238/255.0, 1)
return CustomGridLayout()
if __name__ == '__main__':
TestApp().run()
This does not result in rounded corners for me.
However when I add border: 0, in RoundedButton like this:
test.kv
<RoundedButton#Button>
...
border: 0,
canvas.before:
...
RoundedRectangle:
radius: 10,
The button is then rounded. But then upon starting the app, as well as every time I click the button, I get the following error:
ValueError: need more than 1 value to unpack
Exception ignored in: 'kivy.graphics.vertex_instructions.BorderImage.bui
ld'
This is referring to their being only a single value in border so I changed it to 4 values (i.e. 0, 0, 0, 0) and the error went away but corners are no longer rounded.
I also tried border: 10, 10, 10, 10 but again no rounding.
And lastly I've also tried using the border property with no canvas.before but to no avail.

You need to eliminate the background_color by making it transparent. The background_color is what you are seeing. By making it transparent, it allows you to see the rounded rectangle:
<RoundedButton#Button>
background_color: (0, 0, 0, 0)
background_normal: ''
background_down: ''
size_hint: None, None
size: 300, 50
canvas.before:
Color:
rgba: 51/255.0, 51/255.0, 51/255.0, 1
RoundedRectangle:
size: self.size
pos: self.pos
radius: 10,

Related

Kivy .kv file global variables puzzle

I declared some color constants as global variables in .kv file. They work in certain situations but not in others. An example ColorConstants.kv is
#:kivy 2.0.0
#:set BLUE (0, 0, 1, 1)
#:set WHITE (1, 1, 1, 1)
<Header#BoxLayout>:
# color constants don't work here: NoneType errors
# font_color: WHITE
# header_color: BLUE
# need to use numeric lists for font_color, header_color
font_color: (1, 1, 1, 1)
header_color: (0, 0, 1, 1)
header_text: ""
size_hint: 1, None
height: dp(50)
canvas.before:
Color:
rgba: self.header_color
Rectangle:
size: self.size
pos: self.pos
Label:
color: root.font_color
text: root.header_text
bold: True
BoxLayout:
orientation: "vertical"
Header:
header_text: "My Header"
Label:
# color constants work here, no errors
color: BLUE
text: "This is blue text on white"
canvas.before:
Color:
rgba: WHITE
Rectangle:
size: self.size
pos: self.pos
Accompanying ColorConstants.py:
from kivy.app import App
class ColorConstantsApp(App):
pass
ColorConstantsApp().run()
I am confused why I can use BLUE and WHITE in Label but not in Header. If I use WHITE and BLUE for font_color and header_color instead of the (1,1,1,1) and (0,0,1,1), I encounter a TypeError: 'NoneType' object is not iterable error.
It appears that the canvas instructions are being created before the header_color is assigned. You can work around that by changing:
rgba: self.header_color
to:
rgba: self.header_color if self.header_color else (0,1,0,1)
This just checks if header_color is None and uses something else in that case. Then, when header_color is assigned, the correct color is used.

Kivy. Checkbox on top of background image

My goal is to set the checkbox on top of the image in below class. I'm struggling to find a layout in which I can position one layout above another. The only way I could think of at the moment is to show the image as the background image of RelativeLayout not as AsyncImage but I believe there is a clean way to achieve this.
Class
<FriendTile>
orientation: 'vertical'
size_hint: None, None
height: pic.height + username.height
width: pic.width
background_color: app.alert_color
active_color: app.main_bcolor
unactive_color: app.main_bcolor
canvas.before:
Color:
rgba: (0, 0, 1, 1) if self.background_color is None else self.background_color
Rectangle:
pos: self.pos
size: self.size
RelativeLayout:
id: pic
size_hint: None, None
size: 100, 100
CheckBox:
size_hint: .1, .1
pos_hint: {'top': 1, 'right': 1}
canvas.after:
Color:
rgba: (0, 1, 0, 1)
Rectangle:
pos: self.pos
size: self.size
AsyncImage:
id: image
size_hint: .9, .9
pos_hint: {'center_x': .5, 'center_y': .5}
source: root.avatar
canvas.before:
Color:
rgba: (0, 1, 1, 1) # if root.background_color is None else root.background_color
Rectangle:
pos: self.pos
size: self.size
Expectations
Reality

Invalid indentation, must be a multiple of 8 spaces, rounded button kivy .kv file

so yeah I was learning kivy - "rounded buttons" and when I ran the tutorial's program ---------------
ERROR:
https://i.stack.imgur.com/rGhSa.png
python:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.core.window import Window
Builder.load_file("my.kv")
class MyLayout(Widget,App):
def __init__(self,*args,**kwargs):
super(MyLayout, self).__init__(**kwargs)
class AwesomeApp(App):
def build(self):
Window.clearcolor = (1,1,1,1)
return MyLayout()
if __name__ == '__main__':
AwesomeApp().run()
.kv
<MyLayout>
BoxLayout:
orientation: "vertical"
size: root.width, root.height
padding: 50
spacing: 20
Button:
text: "Hello World!"
RoundedButton:
text: "Goodbye World!"
pos_hint: {'center_x': 0.5}
size_hint: (1, .3)
#background_color: (0/255,255/255,203/255,1)
#background_normal: ''
<RoundedButton#Button>
background_color: (0,0,0,0)
background_normal: ''
canvas.before:
Color:
rgba: (0/255,255/255,203/255,1)
RoundedRectangle:
size: self.size
pos: self.pos
radius: [58]
thanks,can anyone help, don't like these errors,
indentation error it seems like
You are not doing proper indentation you must use only one type of indentation in a file but you are using 8 spaces and 4 spaces both as indentation that is why error is coming.
Here,I have used 4 spaces as indentation in whole code that is why its working fine.
<MyLayout>
BoxLayout:
orientation: "vertical"
size: root.width, root.height
padding: 50
spacing: 20
Button:
text: "Hello World!"
RoundedButton:
text: "Goodbye World!"
pos_hint: {'center_x': 0.5}
size_hint: (1, .3)
#background_color: (0/255,255/255,203/255,1)
#background_normal: ''
<RoundedButton#Button>
background_color: (0,0,0,0)
background_normal: ''
canvas.before:
Color:
rgba: (0/255,255/255,203/255,1)
RoundedRectangle:
size: self.size
pos: self.pos
radius: [58]

How can I make border to the text in the label?

I'm still learning kivy language .
please can you tell me how to add a border to a text in a label in the kv file
and thanks
In the kivy language documentation, you can redefine a widget's style by adding a - to the beginning of the kv rule. So, in the kv you can define a new widget like this:
<-LabelWithBorder#Label>:
border_width: 0
border_color: [1,1,1,1]
canvas.before: # draw the border
Color:
rgba: root.border_color if root.border_width > 0 else [0,0,0,1]
Rectangle:
size: self.size
pos: self.pos
Color:
rgba: 0, 0, 0, 1
Rectangle:
size: self.width - 2*root.border_width, self.height - 2*root.border_width
pos: int(self.center_x - (self.width - 2*root.border_width)/2.), int(self.center_y - (self.height - 2*root.border_width)/2.)
canvas: # modified from Label
Color:
rgba: 1, 1, 1, 1
Rectangle:
texture: self.texture
size: self.texture_size[0] - 2*root.border_width, self.texture_size[1] - 2*root.border_width
pos: int(self.center_x - self.width/2.) + root.border_width, int(self.center_y - self.height/2.) + root.border_width
The canvas.before is the section that draws the border, and the canvas section is the normal Label style with slight modifications to account for the border.
This can be used, for example, like this:
FloatLayout:
LabelWithBorder:
text: 'Hello, World'
font_size: 50
border_width: 10
border_color: [1,0,0,1]
size_hint: None, None
size: self.texture_size
pos_hint: {'center_x':0.5, 'center_y':0.5}
I believe you are looking for 'outline'
This is the docs link for it Label Outline - Kivy Docs
Here's some example code (color defaults to black .. 0, 0, 0, 1):
Label:
id: label_StackOverflowSample
pos_hint: {"x": 0.25, "y": 0.18}
size_hint: 0.6, 0.365
font_size: 18
text_size: self.size
halign: 'left'
italic: True
outline_width: 10
outline_colour: (0, 0, 0, 1)
text:
'''
long long long
long long long
long long long
long long long
long long long
textt
'''
And this is a picture showing its example:
sorry, not enough reputation to post pictures yet
Hope this helps

Kivy. Position of GridLayout inside ScrollView

I give up. I think I have tried everything I possibly could. I need some explatanion how to position nested layouts classes. In below code I need these labels to be positioned in the center of the screen. Anything I've tried leaves the Labels on the left side.
from kivy.app import App
from kivy.lang import Builder
kv = """
<StorageLabel#Label>
background_normal: ''
size_hint: None, None
size: 65, 50
canvas.before:
Color:
rgba: (1, 0, 0.5, 1)
Rectangle:
pos: self.pos
size: self.size
halign: "left"
valign: "middle"
<Storage#BoxLayout>
ScrollView:
size_hint_x: 1
bar_width: 10
scroll_type: ['bars', 'content']
bar_color: [0, 0, 0, 1]
bar_inactive_color: [0, 0, 0, 1]
pos_hint: {'center_x': 0.5}
GridLayout:
cols: 3
size_hint_y: None
size: self.minimum_size
height: self.minimum_height
StorageLabel:
text: '1m'
StorageLabel:
text: '2m'
StorageLabel:
text: '3m'
Storage:
"""
sm = Builder.load_string(kv)
class Main(App):
def build(self):
return sm
if __name__ == '__main__':
Main().run()
The easiest way to center the Labels is to let the GridLayout size and position them. This results in a larger width for each Label, but they are centered:
from kivy.app import App
from kivy.lang import Builder
kv = """
<StorageLabel#Label>
background_normal: ''
# leave size_hint_x at default of 1
size_hint_y: None
height: 50
canvas.before:
Color:
rgba: (1, 0, 0.5, 1)
Rectangle:
pos: self.pos
size: self.size
<Storage#BoxLayout>
ScrollView:
size_hint_x: 1
bar_width: 10
scroll_type: ['bars', 'content']
bar_color: [0, 0, 0, 1]
bar_inactive_color: [0, 0, 0, 1]
pos_hint: {'center_x': 0.5}
GridLayout:
cols: 3
# add some padding and spacing
padding: 5
spacing: 5
size_hint_y: None
height: self.minimum_height
StorageLabel:
text: '1m'
StorageLabel:
text: '2m'
StorageLabel:
text: '3m'
Storage:
"""
sm = Builder.load_string(kv)
class Main(App):
def build(self):
return sm
if __name__ == '__main__':
Main().run()
If you want the labels to be your original size, then you can place each in its own Layout (perhaps a FloatLayout), and let the GridLayout size and position those Layouts:
from kivy.app import App
from kivy.lang import Builder
kv = """
<StorageLabel#Label>
background_normal: ''
size_hint: None, None
size: 65, 50
# position the label in the center of its FloatLayout
pos_hint: {'center_x':0.5}
canvas.before:
Color:
rgba: (1, 0, 0.5, 1)
Rectangle:
pos: self.pos
size: self.size
<Storage#BoxLayout>
ScrollView:
size_hint_x: 1
bar_width: 10
scroll_type: ['bars', 'content']
bar_color: [0, 0, 0, 1]
bar_inactive_color: [0, 0, 0, 1]
pos_hint: {'center_x': 0.5}
GridLayout:
cols: 3
size_hint_y: None
height: self.minimum_height
# set the default row height to the height of the Labels
row_default_height: 50
FloatLayout:
StorageLabel:
text: '1m'
FloatLayout:
StorageLabel:
text: '2m'
FloatLayout:
StorageLabel:
text: '3m'
Storage:
"""
sm = Builder.load_string(kv)
class Main(App):
def build(self):
return sm
if __name__ == '__main__':
Main().run()

Resources