Kivy - Draw Rectangle Around Text - user-interface

I'm brand new to Kivy and trying to make a UI for a project. I'm trying to develop an understanding for how everything gets sized in the different layouts.
I'm having an issue where I have two labels side by side in a box layout (nested in another box layout). I want the 2nd label to have a rectangle drawn behind only the text. I can get 90% of the way there, but I'm stumbling over positioning the rectangle behind the text, since there is no "self.texture_pos" like there is "self.texture_size".
How can I dynamically draw a rectangle at the size and position of a label string, or am I doing this a really dumb way?
My .KV, sorry for the funky colors, as I said I'm trying to understand how everything is positioned:
#:kivy 1.8.0
BoxLayout:
size: root.size
pos: root.pos
id: foo_bar
orientation: 'vertical'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
size: self.size
StatusBarWidget:
ProcessValWidget:
ProcessSliderWidget:
StartStopWidget:
<startstopwidget>:
BoxLayout:
orientation: 'horizontal'
Label:
font_size: 70
center_x: root.width / 4
top: root.top - 50
text: "2"
canvas.before:
Color:
rgba: 0,1,0,1
Rectangle:
size: self.size
pos: self.pos
Label:
font_size: 70
center_x: root.width * 3 / 4
top: root.top - 50
text: "3"
canvas.before:
Color:
rgba: 0,0,1,1
Rectangle:
size: self.size
pos: self.pos
<processvalwidget>:
BoxLayout:
orientation: 'horizontal'
Label:
id: lbl_pval
font_size: 50
text: "Pressure:"
text_size: self.size
halign: 'right'
valign: 'middle'
canvas.before:
Color:
rgba: 1,0,0,1
Rectangle:
size: self.size
pos: self.pos
Label:
id: val_pval
font_size: 50
text: "100 PSI"
canvas.before:
Color:
rgba: 0,1,0,1
Rectangle:
size: self.texture_size
pos: self.pos
<processsliderwidget>:
BoxLayout:
orientation: 'vertical'
Slider:
id: slider
min: 0
max: 100
step: 1
orientation: 'horizontal'
Label:
text: str(slider.value)
<statusbarwidget>:
size_hint_y: None
height: 50
canvas.before:
Color:
rgba: 0,0,0,1
Rectangle:
size: self.size
pos: self.pos
Label:
text: "STATUS BAR"
text_size: self.size
size_hint_x: None
halign: 'left'
valign: 'middle'
padding_x: 5

You can use the texture_size to adjust the position of the Rectangle:
Label:
font_size: 70
center_x: root.width * 3 / 4
top: root.top - 50
text: "3"
canvas.before:
Color:
rgba: 0,0,1,1
Rectangle:
size: self.texture_size
pos: self.center_x - self.texture_size[0]/2, self.center_y - self.texture_size[1]/2

Related

Kivy switching widgets using a toolbar

I'm trying to make a monitoring app where you can switch which stat would be the main widget. I was thinking of having a screen manager and then having separate screens for each stat, but it seemed like there would be a better way.
Below is my kv file where I have separate screens for each layout and the tool bar is outside of the screens:
<Mytest>
GridLayout
cols: 1
size: root.size
StackLayout:
orientation: 'lr-tb'
size_hint_y: .05
Button:
text: "pog"
size_hint_x: .1
background_color: (0, 0, 0, 0)
on_press: root.ids.manager.current = 'first'
Button:
text: "p"
size_hint_x: .1
background_color: (0, 0, 0, 0)
on_press: root.ids.manager.current = 'second'
Button:
text: " o"
size_hint_x: .1
background_color: (0, 0, 0, 0)
on_press: root.ids.manager.current = 'third'
Button:
text: "G"
size_hint_x: .1
background_color: (0, 0, 0, 0)
on_press: root.ids.manager.current = 'fourth'
ScreenManager:
id:manager
Screen:
name: 'first'
GridLayout:
cols: 2
rows: 1
GridLayout:
cols: 1
spacing: (3, 5)
Label:
text:"Idk"
canvas.before:
Color:
rgba: (.2, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text:"Idk"
canvas.before:
Color:
rgba: (1, 1, .2, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text:"Idk"
canvas.before:
Color:
rgba: (0, 1, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Splitter:
sizeable_from: "left"
strip_size: "7pt"
Label:
text:"POGER"
canvas.before:
Color:
rgba: (1, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Screen:
name: 'second'
GridLayout:
cols: 2
rows: 1
GridLayout:
cols: 1
spacing: (3, 5)
Label:
text:"POGER"
canvas.before:
Color:
rgba: (1, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text:"Idk"
canvas.before:
Color:
rgba: (1, 1, .2, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text:"Idk"
canvas.before:
Color:
rgba: (0, 1, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Splitter:
sizeable_from: "left"
strip_size: "7pt"
Label:
text:"Idk"
canvas.before:
Color:
rgba: (.2, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
Screen:
name: 'third'
GridLayout:
cols: 2
rows: 1
GridLayout:
cols: 1
spacing: (3, 5)
Label:
text:"Idk"
canvas.before:
Color:
rgba: (.2, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text:"POGER"
canvas.before:
Color:
rgba: (1, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text:"Idk"
canvas.before:
Color:
rgba: (0, 1, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Splitter:
sizeable_from: "left"
strip_size: "7pt"
Label:
text:"Idk"
canvas.before:
Color:
rgba: (1, 1, .2, 1)
Rectangle:
pos: self.pos
size: self.size
Screen:
name: 'fourth'
GridLayout:
cols: 2
rows: 1
GridLayout:
cols: 1
spacing: (3, 5)
Label:
text:"Idk"
canvas.before:
Color:
rgba: (.2, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text:"Idk"
canvas.before:
Color:
rgba: (1, 1, .2, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text:"POGER"
canvas.before:
Color:
rgba: (1, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Splitter:
sizeable_from: "left"
strip_size: "7pt"
Label:
text:"Idk"
canvas.before:
Color:
rgba: (0, 1, 0, 1)
Rectangle:
pos: self.pos
size: self.size
# GridLayout:
# cols: 2
# rows: 1
# GridLayout:
# cols: 1
# spacing: (3, 5)
# Label:
# text:"Idk"
# canvas.before:
# Color:
# rgba: (1, 0, 0, 1)
# Rectangle:
# pos: self.pos
# size: self.size
# Label:
# text:"Idk"
# canvas.before:
# Color:
# rgba: (1, 1, .2, 1)
# Rectangle:
# pos: self.pos
# size: self.size
# Label:
# text:"POGER"
# canvas.before:
# Color:
# rgba: (.2, 1, 1, 1)
# Rectangle:
# pos: self.pos
# size: self.size
# Splitter:
# sizeable_from: "left"
# strip_size: "7pt"
# Label:
# text:"IDK"
# canvas.before:
# Color:
# rgba: (0, 1, 0, 1)
# Rectangle:
# pos: self.pos
# size: self.size
The python file is just the imports and then building the app:
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.graphics import Rectangle, Color
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.pagelayout import PageLayout
from kivy.uix.splitter import Splitter
from kivy.uix.screenmanager import ScreenManager, Screen
Good day. I recommend a class in python that could hold the values for a given stat. When you change the stat, call a function that loads each attribute of the stat into the main widget. Each stat will be its own object.

Is there a way to put a border around kivy BoxLayouts?

I am designing a main menu for an app that i am creating, but i cant seem to figure out how to border a boxlayout in kivy, is there a way to do this? If so could someone help. I have tried to use a canvas.before and bordering the rectangle but that doesn't work.
<MainMenuWindow>:
id: Main_Menu_window ## setting the id to Login_window
BoxLayout: ## whole screen
orientation: 'horizontal'
BoxLayout: ## left hand side 1/3
canvas.before:
Color:
rgba: 0, 0, 0, 1
Line:
width:
rectangle: self.x, self.y, self.width, self.height
orientation: 'vertical' ## setting orientation of the screen to vertical
size_hint_x: 1/3 ## setting size of box to 1/3 of the screen
canvas.before:
Color: ## just for debugging reasons
rgba: (255/255,255/255,255/255, 1) ## setting colour
Rectangle:
size: self.size ## setting size to the size of the box layout
pos: self.pos ## setting position to the position of the box layout
A BoxLayout tries to use all its available space by allocating a share to each child. Since your inside BoxLayout is the only child of the outside BoxLayout, it will be allocated the entire space of the outside BoxLayout. So, you can control the size of your inner BoxLayout either by adjusting the size of the outer BoxLayout, or by explicitly setting the size of the inner BoxLayout (with size_hint: None, None).
So, here is one way to get the inner BoxLayout to one third the screen width:
<MainMenuWindow>:
id: Main_Menu_window ## setting the id to Login_window
BoxLayout: ## whole screen
orientation: 'horizontal'
BoxLayout: ## left hand side 1/3
canvas.before:
Color:
rgba: 1, 0, 0, 1
Line:
width: 20
rectangle: self.x, self.y, self.width, self.height
orientation: 'vertical' ## setting orientation of the screen to vertical
Label: ## middle third
text: 'Abba'
Label: ## right third
text: 'Dabba'

Kivy regarding Label Background colours

I am new to Kivy. Currently i have problem, i want to have a Label with Background colours. I wrote these code but it seems that the Label of the background colour is still displaying black.
May I know if there is any other solution to resolve this issue?
label = Label(text='test',pos=(20, 20),size=(180, 100),size_hint=(None,None))
with label.canvas:
Color(0, 1, 0, 0.25)
Rectangle(pos=label.pos, size=label.size)
The way I do it, is by using my own label MyLabel
In the .py
class MyLabel(Label):
pass
In the .kv:
<MyLabel>:
back_color: .1, .1, .1, 1
canvas.before:
Color:
rgba: root.back_color
Rectangle:
pos: self.pos
size: self.size
After that, you can just do:
a_label = MyLabel()
a_label.back_color = [1, 0, 1, 1]

Action based on scrolling up or down in Framer.js

I'm a designer and very new to Framer.
Id like to be able to hide/show the navigation at the top of screen based on the direction the content below is scrolled. If I start to scroll down the page, the nav hides by moving up. And then the opposite.
Here's what I've been playing around with, but no luck so far.
scroll.on Events.Scroll, ->
if scroll.scroll > scroll.scrollY then psd.subHead.animate
properties:
y: -50
else scroll.scroll < scroll.scrollY then psd.subHead.animate
properties:
y: 0
I suppose I want to move up if scroll position is less than the current position and down if it's greater.
Any help is much appreciated!
The ScrollComponent layer has a direction property. From the docs:
scroll.direction
Current scrolling direction. Returns "up", "down", "left", or "right".
The scrolling direction is the inverse of the direction of the drag
action: when dragging downwards, you're effectively scrolling upwards.
This property is read-only.
Below is some example code to get you started. You can find the scroll.direction usage near the bottom.
Framer.Defaults.Animation = time: 0.3
scroll = new ScrollComponent
width: Screen.width
height: Screen.height
scrollHorizontal: false
backgroundColor: "blue"
contentInset:
top: 10
bottom: 10
borderRadius: 8
for i in [0..10]
layerA = new Layer
width: Screen.width - 20, height: 150
x: 10, y: 160 * i
backgroundColor: "#fff"
superLayer: scroll.content
borderRadius: 4
navBar = new Layer
x: 0
y: 0
width: Screen.width
height: 130
borderRadius: 8
backgroundColor: "red"
scroll.on Events.Scroll, ->
if scroll.direction == "up"
navBar.animate
properties:
y: 0
if scroll.direction == "down"
navBar.animate
properties:
y: -130

Kivy - [Critical] Warning too much iteration, when drawing Ellipse

I have been struggling recently creating a filled Circle in Kivy that stays a circle when the window is re-sized to a different width or height. I looked at the question here:
Centering an object in Kivy
But when I implement my Circle like so:
<BigCircle>
width: min(self.size)
height: min(self.size)
pos_hint: {'center_x': .5, 'center_y': .5}
canvas:
Color:
rgb: 1, 1, 0
Ellipse:
size: self.size
pos: self.pos
<MainScreen>:
FloatLayout
size: root.size
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
size: self.size
BigCircle:
id: big_cir
class MainScreen(Screen):
pass
class MyApp(App):
def build(self):
sm = ScreenManager(transition=NoTransition())
sm.add_widget(MainScreen(name="Main"))
return sm
I get the error:
[Critical][Clock ]Warning, too much iteration done before the next frame. Check your code, or increase the Clock.max_iteration attribute
I am doing nothing with the Clock, but I am using a ScreenManager. Currently, MainScreen is the only screen. If I change the height/width to not include the min() then it works, but that is necessary to keep the Circle circular. Otherwise it becomes elongated when re-sized and looks bad.
The problem is you have an infinite loop due to BigCircle width and height being adjusted based on its size (width, height). Try changing your BigCircle to:
<BigCircle>
canvas:
Color:
rgb: 1, 1, 0
Ellipse:
size: min(self.size), min(self.size)
pos: root.center_x - min(self.size)/2, root.center_y - min(self.size)/2

Resources