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

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

Related

Kivy animation rotation over 360 degrees - wind direction indicator

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

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]

rgba() is producing a blackish tone in HTML5 Canvas Gradient

I wanted to draw three gradients on top of the other on a HTML5 Canvas. But it wasn't not producing the desired effect. So I dug into the thing a little bit, and found out that rgba(0, 0, 0, 0) was not completely transparent when used in canvas gradient. Rather it was producing an unexpected blackish tone.
In CSS, it works fine though.
How can I have the same effect as it works in CSS? (see attached screenshot please)
CSS properties:
background: linear-gradient(rgba(0, 0, 0, 0), rgb(255, 0, 0));
Canvas properties:
var grad = ctx.createLinearGradient(0, 0, 0, height);
grad.addColorStop(0, 'rgba(0, 0, 0, 0)');
grad.addColorStop(1, 'rgb(255, 0, 0)');
Indeed the algorithms seem to be different.
Not quite sure why, but I'd say that CSS doesn't consider rgba(0,0,0,0) as transparent black pixel like canvas does, but instead just as transparent.
The 2D canvas will composite straight from all the 4 RGBA channels values, until the ones of the next stop, while CSS one seems to comprehend transparent as a particular case.
To get the same result as CSS on a canvas, you'd have to set your first transparent stop to the next one, by only changing the alpha value:
var ctx = c.getContext('2d'),
grad = ctx.createLinearGradient(0,0,0,150);
grad.addColorStop(0, 'rgba(255,0,0,0)'); // transparent red
grad.addColorStop(1, 'rgba(255,0,0)');
ctx.fillStyle = grad;
ctx.fillRect(0,0,300,150);
#html{
background: linear-gradient(rgba(0, 0, 0, 0), rgb(255, 0, 0));
height: 150px;
width: 300px;
display: inline-block;
}
<div id="html"></div>
<canvas id="c"></canvas>

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

Resources