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.
Related
I am learning every day and invest many hours in a simple looking project.
Now I am faced with the problem that kivy rotates backwards my windrose after input of values over 360 degree.
Example:
First input: 356 degree -> rotates forwards to next input 360 degree.
Third input: 10 degree -> rotates backwards from 360 degree all the way back to 10 degree instead of using the shortest way.
What can I do to teach kivy to rotate always the shortest way? Forward and backwards?
See the example picture here
import socket
from kivy.animation import Animation
from kivy.clock import Clock, mainthread
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.app import App
from kivy.config import Config
from kivy.core.window import Window
from kivy.properties import NumericProperty
Config.set('graphics', 'width', '600')
Config.set('graphics', 'height', '650')
Window.size = (550, 650)
Window.clearcolor = (0.219, 0.247, 0.282, 1)
icon = "meteo_icon.ico"
title = "AWOS 1.0 display"
UDP_IP = ""
UDP_PORT = 6999
sock=socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
class DirWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
KV = """
WindowManager:
DirWindow:
<DirWindow>:
angle: 0
name: 'AWOS_windrose'
Image:
source: 'rwy_pic.png'
size_hint: None, None
size: 400, 400
pos_hint: {'center_x': 0.5, 'center_y': 0.4}
canvas.before:
PushMatrix
Rotate:
angle: 110
axis: (0, 0, 1)
origin: (self.center_x, self.center_y , 0)
canvas.after:
PopMatrix
Image:
source: 'arrow_thin.png'
size_hint: None, None
size: 530, 530
pos_hint: {'center_x': 0.5, 'center_y': 0.4}
# apply rotation matrix to this Image
canvas.before:
PushMatrix
Rotate:
angle: root.angle
axis: (0, 0, 1)
origin: (self.center_x, self.center_y , 0)
canvas.after:
PopMatrix
Image:
source: 'wind_dial.png'
size_hint: None, None
size: 500, 500
pos_hint: {'center_x': 0.5, 'center_y': 0.4}
"""
class MyMainApp(App):
angle = NumericProperty(0)
def build(self):
self.title = 'AWOS 1.0 - Wind Display'
Clock.schedule_interval(self.animate_needle, 2) # start the animation in 2 seconds
return Builder.load_string(KV)
def animate_needle(self, dt):
data, addr = sock.recvfrom(1024)
wind_direction = (data.decode()[35:38])
#wind_speed = (data.decode()[26:30])
wind_control = (data.decode()[20:24])
a = "WIND"
if wind_control == a:
self.anim = Animation(angle=(-int(wind_direction)), duration=2)
self.anim.repeat = True
windrose = self.root.get_screen('AWOS_windrose')
self.anim.start(windrose)
print(wind_direction)
def on_angle(self, item, angle):
if angle == 360:
item.angle = 0
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
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'
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]
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