Kivy moving label inside FloatLayout - python

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.

Related

Background rectangle fit to label text in Kivy

I am trying to get a background around a label that fits the number of lines in the texted in it. For example, a label with text 'Line1\nLine1\nLine3' would have a larger Y dimension that just 'line1'
What currently happens is all of the labels are the same size and clip-off text that doesn't fit within them, the labels are also inside a recycleview layout because I would like to be able to scroll and update large amount of the labels often.
I have tried a few things but have had no luck, and am struggling to get a variable to be understood where I have added # HERE in the .kv file
from kivy.app import App
from kivy.properties import NumericProperty, Clock, ObjectProperty, StringProperty
from kivy.uix.widget import Widget
from kivy.uix.recycleview import RecycleView
from kivy.uix.button import Button
from kivy.uix.label import Label
class TopPostsTest(RecycleView):
def __init__(self, **kwargs):
super().__init__(**kwargs)
message_height = NumericProperty(20)
items = ["hello\ntest\ntest", "test, gghgjhgjhgjhgjhghjghjgjhgjhgjhgjhgjhgjhgjhgjhg", "cheese"]
self.data = [{'text':str(p)} for p in items]
class LabelColor(Label):
pass
class TruthApp(App):
# def build(self):
# return super().build()
pass
if __name__ == "__main__":
TruthApp().run()
<MainControl#PageLayout>:
border: "25dp"
swipe_threshold: 0.4
TopPostsTest:
Settings:
<LabelColor>:
color: 0,0,0,1
text_size: self.size
halign: 'left'
valign: 'top'
font_name: "Assets/Fonts/Nunito-Bold.ttf"
font_size: "12dp"
multiline: True
canvas.before:
Color:
rgba: (0.8, 0.8, 0.8, 1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [5, 5, 5, 5]
canvas:
Color:
rgba:0,0.9,0.9,1
Line:
width:0.8
rounded_rectangle:(self.x,self.y,self.width,root.height, 5) # HERE
<TopPostsTest>:
viewclass: 'LabelColor'
scroll_y: 1
RecycleBoxLayout:
id: message_view
default_size: None, dp(40) # NewHERE
default_size_hint: 1, None
size_hint_y: None
padding: ["10dp", "16dp"]
spacing: "8dp"
height: self.minimum_height
orientation: 'vertical'
Thank you for any help :)
Edit:
I have found that I have been changing the wrong value and that the variable that needs changing has been marker with # NewHERE, however I am still unable to get it to work or get a variable from the py file into the kv
In order to get a Label that expands vertically as it's text-content grows you can set its height to its texture height.
Also, to fit the text within available space (width) you can change text_size.
Thus you can modify the kvlang for LabelColor as,
<LabelColor>:
color: 0,0,0,1
text_size: self.width, None
size_hint_y: None
height: self.texture_size[1]

Why does the kivy labels text show out of the label?

I am new to kivy. I want to insert a text into a kivy label at the startup. But the text of the lable shows out of the label as shown below. I can't find a way to fix this. So please give me a solution.
This is the code of the kv file.
<SmoothLabel#Label>
background_color: (0,0,0,0)
background_normal: ''
back_color: (255,255,255,1)
border_radius: [18]
canvas.before:
Color:
rgba: (255,255,255,0.3)
RoundedRectangle:
size: 50,50
pos: 100,10
radius: self.border_radius
<Money_Manager>
FloatLayout:
size_hint_y: None
height:100
Image:
source:'image4.png'
size: self . texture_size
allow_stretch: True
keep_ratio: False
SmoothLabel:
d: Total_Wealth
text: "Total_Wealth"
This is the code of the python file.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
Builder.load_file('total_wealth.kv')
class Money_Manager(App, FloatLayout):
def build(self):
return self
Money_Manager().run()
In your kv file, you have set the pos and size of the RoundedRectangle to fixed values. You need to set them to the pos and size of the Label. So change this:
<SmoothLabel#Label>
background_color: (0,0,0,0)
background_normal: ''
back_color: (255,255,255,1)
border_radius: [18]
canvas.before:
Color:
rgba: (255,255,255,0.3)
RoundedRectangle:
size: 50,50
pos: 100,10
radius: self.border_radius
to:
<SmoothLabel#Label>
background_color: (0,0,0,0)
background_normal: ''
back_color: (255,255,255,1)
border_radius: [18]
canvas.before:
Color:
rgba: (255,255,255,0.3)
RoundedRectangle:
size: self.size
pos: self.pos
radius: self.border_radius
Here is my answer for yours
# import kivy module
import kivy
# this restricts the kivy version i.e
# below this kivy version you cannot use the app or software
kivy.require("1.9.1")
# base Class of your App inherits from the App class.
# app:always refers to the instance of your application
from kivy.app import App
# if you not import label and use it it through error
from kivy.uix.label import Label
# defining the App class
class MyLabelApp(App):
def build(self):
# label display the text on screen
lbl = Label(text ="Label is Added on screen !!:):)")
return lbl
# creating the object
label = MyLabelApp()
# run the window
label.run()
Output:

Python-Kivy: BoxLayout with stretch capability

How can I make my boxlayout expand according to dynamically added content?
Here is my code to illustrate what I am trying to do:
main.py
from kivy.app import App
from kivy.uix.label import Label
class TestApp(App):
def add_label(self):
label = Label(text='StackOverflow', color=(0,0,0,1))
self.root.ids.myBox.add_widget(label)
if __name__ == '__main__':
TestApp().run()
test.kv
BoxLayout:
orientation: 'vertical'
spacing: 400
BoxLayout:
orientation: 'vertical'
size_hint: None, None
size: dp(280), dp(100)
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
#width: self.minimum_width
#height: self.minimum_height
id: myBox
background_color: (1,1,1,1)
canvas.before:
Color:
rgba: self.background_color
Rectangle:
pos: self.pos
size: self.size
Button:
text: 'BUTTON'
size_hint: None, None
size: dp(100), dp(50)
pos_hint: {'center_x': 0.5, 'center_y': 0.1}
on_release: app.add_label()
The button has the effect of dynamically adding a label to the boxlayout. But the more the labels are added, the size of the boxlayout does not change and the texts are superimposed.
Thanks in advance for your help.
One way to do this is do recalculate the size of the BoxLayout yourself. By changing your add_label() method to:
def add_label(self):
label = Label(text='StackOverflow', color=(0,0,0,1))
self.root.ids.myBox.add_widget(label)
label.texture_update()
boxlayout = self.root.ids.myBox
height = 0
for child in boxlayout.children:
height += child.texture_size[1]
height += 2 * child.padding_y
boxlayout.height = height
The BoxLayout changes height on each Label addition. You would think that you could use the child.height in the calculation, but the default value for height is always 100 until the layout is actually calculated. But, as you have seen, when the layout is calculated, the height of the label is reduced to fit in the BoxLayout. The texture of the Label can be updated before layout, and therefore, I have used its height in the calculation. This will decrease the size of the BoxLayout with the first Label added, and will increase it on every following addition. Note that this will only work for widgets that have a texture property like the Label or Button.

Kivy Treeview Position Issues

I am trying to create a layout with 2 sections that have a label over each and a view below (TreeView on the left and a window showing details on the right, e.g. "click on this node and see details"). I've got the labels sized and positioned, but when I add the TreeView, instead of fitting under the label, it pushes both labels over, no matter the position.
Here's the current result:
My main.py file--
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.treeview import TreeView, TreeViewLabel
class MainScreen(BoxLayout):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
bridge_view = TreeView(root_options=dict(text='Clients'),
hide_root=False, indent_level=4,
pos_hint={"x": 0, "y": 0},
size_hint=(0.1, 0.5))
clients = {'client1': 'Connection A',
'client2': 'Connection B'}
for client in clients.keys():
node = bridge_view.add_node(TreeViewLabel(text=client))
bridge_name = clients[client]
bridge = bridge_view.add_node(TreeViewLabel(text=bridge_name), node)
self.add_widget(bridge_view)
class ConnectionApp(App):
def build(self):
self.title = 'My Support App'
return MainScreen()
if __name__ == '__main__':
ConnectionApp().run()
This is my kv file--
<Label>:
font_size: 30
<MainScreen>:
Label:
text: "Connections"
size_hint: 0.1, 0.5
pos_hint: {"left": 0.2, "top": 1.2}
color: 1,0,1,1
outline_color: 1,0,1,1
Label:
text: "Modules"
size_hint: 0.1, 0.5
pos_hint: {"right": 0.2, "top": 1.2}
Another thing that seems strange to me was how I had to use pos_hint to get my label spacing to work. As I understand it, these values should be on a scale between 0-1. A tutorial I read indicated as much--
Pos_hint gives a hint at the position, which is measured relatively
between 0 and 1, where 1 is "completely" something and 0 is "not"
something.
Does anyone know why it took using a value greater than 1 for "top" to get these labels at the top? I'm guessing this may be a hint as to why my layout isn't showing up correctly.
TreeView under Labels
The solution is to use GridLayout as child of BoxLayout (root widget, MainScreen), Labels and TreeViews as child of GridLayout. Added an ObjectProperty, container to hook it up to the GridLayout widget (place holder for the TreeView widget) created in the kv file. Please to the example for details.
Example - TreeView under Labels
main.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.treeview import TreeView, TreeViewLabel
from kivy.properties import ObjectProperty
from kivy.lang import Builder
Builder.load_string('''
#:kivy 1.10.0
<Label>:
font_size: 30
<MainScreen>:
container: tree_view
orientation: 'vertical'
GridLayout:
cols: 2
size_hint: 0.5, 0.1
Label:
canvas.before:
Color:
rgba: 1, 0, 0, 1 # red
Rectangle:
size: self.size
pos: self.pos
text: "Connections"
color: 1,0,1,1
outline_color: 1,0,1,1
Label:
canvas.before:
Color:
rgba: 0, 0, 1, 1 # blue
Rectangle:
size: self.size
pos: self.pos
text: "Modules"
GridLayout:
cols: 1
id: tree_view
''')
class MainScreen(BoxLayout):
container = ObjectProperty(None)
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
bridge_view = TreeView(root_options=dict(text='Clients'),
hide_root=False, indent_level=4,
pos_hint={"x": 0, "y": 0},
size_hint=(0.1, 0.5))
clients = {'client1': 'Connection A',
'client2': 'Connection B'}
for client in clients.keys():
node = bridge_view.add_node(TreeViewLabel(text=client))
bridge_name = clients[client]
bridge = bridge_view.add_node(TreeViewLabel(text=bridge_name), node)
self.container.add_widget(bridge_view)
class DemoApp(App):
def build(self):
return MainScreen()
if __name__ == '__main__':
DemoApp().run()
Output - TreeView under Labels
pos_hint: {'top': 1}
The reason you have to use a value greater than 1 for top because the Label widget's height is 0.5 (size_hint: 0.1, 0.5). The solution to use pos_hint: {'top': 1} is to reduce size_hint_y as shown in the snippets.
In my example, Label's canvas color were added for visualization/demonstration.
Snippets
Label:
...
size_hint: 0.1, 0.1
pos_hint: {"top": 1}
Example - pos_hint
kv file
#:kivy 1.10.0
<Label>:
font_size: 30
<MainScreen>:
Label:
canvas.before:
Color:
rgba: 1, 0, 0, 1 # red
Rectangle:
size: self.size
pos: self.pos
text: "Connections"
size_hint: 0.1, 0.1
pos_hint: {"left": 0.2, "top": 1}
color: 1,0,1,1
outline_color: 1,0,1,1
Label:
canvas.before:
Color:
rgba: 0, 0, 1, 1 # blue
Rectangle:
size: self.size
pos: self.pos
text: "Modules"
size_hint: 0.1, 0.1
pos_hint: {"right": 0.2, "top": 1}
Output - pos_hint

Centering an object in Kivy

I am trying to center a circle inside a layout. I'm currently doing some padding calculations, but I'm also looking for a better way. I imagine one of the predefined layouts may be a better choice. Here's what my code is producing...
For square layouts:
For wide layouts:
This is the right behavior, which is great, but is there a better way? I can imagine this getting messy with non-circle shapes, for example.
Here's my code:
#!/usr/bin/kivy
import kivy
kivy.require('1.7.2')
from random import random
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.graphics import Color, Ellipse, Rectangle
class MinimalApp(App):
title = 'My App'
def build(self):
root = RootLayout()
return(root)
class RootLayout(AnchorLayout):
pass
class Circley(RelativeLayout):
pass
if __name__ == '__main__':
MinimalApp().run()
And the KV:
#:kivy 1.7.2
#:import kivy kivy
<RootLayout>:
anchor_x: 'center' # I think this /is/ centered
anchor_y: 'center'
canvas.before:
Color:
rgba: 0.4, 0.4, 0.4, 1
Rectangle:
pos: self.pos
size: self.size
Circley:
anchor_x: 'center' # this is /not/ centered.
anchor_y: 'center'
canvas.before:
Color:
rgba: 0.94, 0.94, 0.94, 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)
Label:
text: unicode(self.size) # this is /not/ appearing
color: 1,0,0,1
Snippet using FloatLayout, size_hint and pos_hint:
from kivy.app import App
from kivy.lang import Builder
kv = '''
FloatLayout:
Widget:
size: min(root.size), min(root.size)
size_hint: None, None
pos_hint: {'center_x': .5, 'center_y': .5}
canvas:
Color:
rgb: 1, 0, 0
Ellipse:
size: self.size
pos: self.pos
'''
Builder.load_string(kv)
class MyApp(App):
def build(self):
return Builder.load_string(kv)
MyApp().run()
Flag of Japan:
from kivy.app import App
from kivy.lang import Builder
kv = '''
FloatLayout:
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
size: self.size
pos: self.pos
Widget:
size: min(root.size)/2, min(root.size)/2
size_hint: None, None
pos_hint: {'center_x': .5, 'center_y': .5}
canvas:
Color:
rgb: 1, 0, 0
Ellipse:
size: self.size
pos: self.pos
'''
Builder.load_string(kv)
class MyApp(App):
def build(self):
return Builder.load_string(kv)
MyApp().run()

Categories