Python Kivy Float Layout - python

I have very little experience with Python and Kivy. I am helping my little nephew with his quest to build a game using the two. We are stuck at something that seems simple.
Consider following code:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty, ReferenceListProperty,\
ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
from random import randint
from kivy.graphics import Color, Ellipse, Rectangle
from kivy.uix.floatlayout import FloatLayout
import math
class Fly(Widget):
pass
class Stick(Widget):
pass
class FlyBox(Widget):
pass
class GameArea(FloatLayout):
pass
class FlyApp(App):
def build(self):
gameArea = GameArea()
flyBox = FlyBox()
flyBox.canvas.add(Rectangle(pos_hint={'x': 0, 'y': .3}, size_hint=(1, .3)))
flyBox.canvas.add(Color(1, 0, 0))
gameArea.add_widget(flyBox)
return gameArea
if __name__ == '__main__':
FlyApp().run()
it produces following output:
What we were trying to achieve was:
The FlyBox's height should be 1/3rd the height of the GameArea's height.
The FlyBox's width should be same as GameArea's width.
The FlyBox's x coordinate should be 0 and its y coordinate should be 1/3rd the height of GameArea.
i.e. if the game area were to be divided into 3 equal sized horizontal bands, the FlyBox should be the middle band. And as the size of game area changes (due to resizing of window), the FlyBox's size and position should change relatively.
We are trying to avoid using a .kv file and instead do everything in Python.

You only need to use size_hint_y property to set the correct height (1/3rd the parent height) and pos_hint property to position it in the center.
Using kivy languaje:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
kv_text = '''
<GameArea>:
Widget:
id: flybox
size_hint_y: 1/3
pos_hint: {'x': 0, 'center_y': .5}
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
'''
class GameArea(FloatLayout):
pass
class FlyApp(App):
def build(self):
Builder.load_string(kv_text)
return GameArea()
if __name__ == '__main__':
FlyApp().run()
Output:

Related

Why does % Window.width with (self.object.uvpos[0] + time) in clock_interval make moving textures work correctly in Kivy

I'm doing a tutorial about making a game, and still in the background period, making moving textures. But I just wonder why the wrapped problem fixed by %Window.width in the line self.cloud_texture.uvpos = {(self.cloud_texture.uvpos[0] + time_passed)%Window.width ,self.cloud_texture.uvpos[1]}
I see no problem when I just do self.cloud_texture.uvpos[0] + time_passed only, but the result told me the difference when it's changing the self.cloud_texture.uvpos[1] too, and starting to get some glitch when resizing window after few seconds.
Can someone give me an explanation so I can apply it to my other apps?
.py file
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.properties import ObjectProperty
from kivy.core.window import Window
class Background(Widget):
cloud_texture = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
#create texture
self.cloud_texture = Image(source="assets/cloud.png").texture
self.cloud_texture.wrap = "repeat"
self.cloud_texture.uvsize = {Window.width / self.cloud_texture.width, -1}
def scroll_textures(self,time_passed):
self.cloud_texture.uvpos = {(self.cloud_texture.uvpos[0] + time_passed)%Window.width ,self.cloud_texture.uvpos[1]}
texture = self.property("cloud_texture")
texture.dispatch(self)
from kivy.clock import Clock
class MainApp(App):
def on_start(self):
Clock.schedule_interval(self.root.ids.background.scroll_textures, 1/60)
pass
if __name__ == "__main__":
MainApp().run()
.kv file
FloatLayout:
Background:
id: background
canvas.before:
Rectangle:
size: self.size
pos: self.pos
source: "assets/sky.png"
Rectangle:
size: self.width, 138
pos: self.pos[0], self.pos[1] + self.height - 138
texture: self.cloud_texture
You can find the images I'm using here

How to set backgroud color to BoxLayout in kivy?

I have BoxLayout in kivy
root = BoxLayout(
orientation = "horizontal",
padding = 1,
background_color = [0, 1, 0, 1]
)
Unfortunately, the BoxLayout has a horrible background (default)
How can I set a custom background color for the BoxLayout?
Doing this you will get a TypeError as the class BoxLayout has no background_color property.
In kivy you are reasonably free to create your own widget graphical representation. For that you have to create a subclass inheriting from BoxLayout with the desired property.
Below is a sample example implemented with kivy lang, but you can do that in python also with some binding (that will be a little bit verbose).
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ColorProperty
from kivy.uix.boxlayout import BoxLayout
Builder.load_string(
"""
<CustomRoot>:
canvas:
Color:
rgba: root.background_color
Rectangle:
pos: self.pos
size: self.size
""")
class CustomRoot(BoxLayout):
background_color = ColorProperty() # The ListProperty will also work.
class MyApp(App):
def build(self):
return CustomRoot(background_color = (1, 0, 1, 1))
MyApp().run()
For more have a look at kivy documentation.

Kivy, opacity around mouse, revealing picture

I would like to make a puzzle where someone has to follow a maze and collect letters which have to be typed in later as an answer. (Not collected by the program but just remembering which letters are passed and typing it in later while exiting the maze.)
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.config import Config
Config.set('graphics', 'width', '806')
Config.set('graphics', 'height', '706')
class Touch(Widget):
def __init__(self, **kwargs):
super(Touch, self).__init__(**kwargs)
def on_touch_down(self, touch):
pass
def on_touch_down(self, touch):
pass
def on_touch_down(self, touch):
pass
class MyGrid(GridLayout):
pass
class DrawingWindow(App):
def build(self):
return MyGrid()
if __name__ == "__main__":
DrawingWindow().run()
<MyGrid>:
GridLayout:
cols:1
size:1000,706
canvas:
Rectangle:
size: 808,706
source: 'Puzzle.png'
I have found out how to draw a circle where your mouse is (not added to the code as I think a different method is probably going to be used), but how to make everything around a certain radius black so that it only reveals a small circle within this radius. Maybe using opacity within a radius is a sollution. If someone could push me in the right direction, that would be really helpful.
It does not have to stay revealed, rather not actually. Hopefully that makes it somewhat easier as well.
I hope I've stated clearly what the problem is. Thank you in advance for the time and effort.
You can use Stencil Instructions to accomplish that. Here is a simple example:
from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.properties import NumericProperty, ListProperty
from kivy.uix.widget import Widget
kv = '''
RelativeLayout:
ImageWithHole:
id: hole
canvas:
StencilPush
Ellipse: # draw the hole
pos: self.hole_pos[0] - self.radius, self.hole_pos[1] - self.radius
size: self.radius*2, self.radius*2
StencilUse
Color:
rgba: 1,1,1,1
Rectangle:
source: 'Puzzle.png' # draw the maze
pos: 0,0
size: self.size
StencilUnUse
Ellipse: # erase the hole (must be identical to original draw above)
pos: self.hole_pos[0] - self.radius, self.hole_pos[1] - self.radius
size: self.radius*2, self.radius*2
StencilPop
'''
class ImageWithHole(Widget):
radius = NumericProperty(50)
hole_pos = ListProperty([400, 300])
class TestApp(App):
def build(self):
Window.bind(mouse_pos=self.on_motion)
return Builder.load_string(kv)
def on_motion(self, src, mouse_pos):
hole = self.root.ids.hole
hole.hole_pos = mouse_pos
TestApp().run()

Kivy create pulsing background

I'm trying to create pulsing background in my app. Following this question Pulsing Background Color in Kivy
i've tried to make it work also, but for some reason it doesn't work. Here's my main.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.core.window import Window
from kivymd.app import MDApp
from kivy.uix.image import Image
from kivy.animation import Animation
from kivy.clock import Clock
Window.size = (360,600)
class MyGridLayout(Screen):
def blink(self):
x = Clock.schedule_once(self.start_pulsing,2)
return x
def start_pulsing(self,*args):
anim = Animation(animated_color=(1,0,0,1))
anim.start(self)
anim.repeat = True
class mainApp(App):
def build(self):
return MyGridLayout()
if __name__ == '__main__':
mainApp().run()
And my main.kv file
<MyGridLayout>:
FloatLayout:
size: root.width, root.height
animated_color:(1,1,1,1)
canvas.before:
Color:
rgba :self.animated_color
Rectangle:
pos: self.pos
size: self.size
Any help will be much appreciated
A couple problems with your code:
The animated_color property in your kv is a property of the FloatLayout, but your python code references it as a property of MyGridLayout.
The anim.repeat = True will cause the Animation to be repeated, but after the first animation, the animated_color is already (1,0,0,1), so the repeated Animation will have no effect.
I don't see any code calling the blink() method to actually start the pulsing.
Here is a modified version of your code that reflects the above changes:
from kivy.app import App
from kivy.properties import ColorProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.core.window import Window
from kivy.animation import Animation
from kivy.clock import Clock
Window.size = (360,600)
class MyGridLayout(Screen):
animated_color = ColorProperty() # the color property to be animated
pulse_interval = 4 # the interval for pulsing
def blink(self):
x = Clock.schedule_once(self.start_pulsing,2)
return x
def start_pulsing(self,*args):
d = self.pulse_interval /2
anim = Animation(animated_color=(1,0,0,1), duration=d) + \
Animation(animated_color=(1,1,1,1), duration=d)
anim.repeat = True
anim.start(self)
class mainApp(App):
def build(self):
root = MyGridLayout()
root.blink() # star the pulsing
return root
if __name__ == '__main__':
mainApp().run()
And the modified main.kv:
<MyGridLayout>:
FloatLayout:
size: root.width, root.height
# animated_color:(1,1,1,1) # property needs to be attribute of MyGridLayout
canvas.before:
Color:
rgba :root.animated_color # reference the animated_color property of MyGridLayout
Rectangle:
pos: self.pos
size: self.size

Kivy Digital Clock Issues

I'm trying to add a digital clock to my Kivy program, it seems to be having trouble.
Here is the .py:
import kivy
kivy.require('1.10.0')
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.stacklayout import StackLayout
from kivy.clock import Clock
from kivy.properties import ObjectProperty
from kivy.properties import StringProperty
import time
class IntroScreen(Screen):
pass
class ContScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
backbone = Builder.load_file("main.kv")
class Status(FloatLayout):
_change = StringProperty()
_tnd = ObjectProperty(None)
def update(self, *args):
self.time = time.asctime()
self._change = str(self.time)
self._tnd.text = str(self.time)
print (self._change)
class XGApp(App):
time = StringProperty()
def update(self, *args):
self.time = str(time.asctime()) # + 'time'?
def build (self):
Clock.schedule_interval(self.update, 1)
return backbone
xApp = XGApp()
if __name__ == "__main__":
xApp.run()
and the .kv
<ContScreen>:
FloatLayout
size_hint: .1,.1
canvas.before:
Color:
rgba: 0,0,0,1
Rectangle:
pos: self.pos
size: self.size
Label:
text: app.time
ContScreen is the title of the screen I want to show the clock on, it's served by a separate Builder (main.kv).
Any help would be appreciated! Been struggling with this clock for a few hours now. The trouble seems to be on the .kv side from what I can tell.
BONUS: If you want to go the extra mile, I also want to add a timer that counts down x amount on press of a button on the .kv. The x amount would be different depending on which button you press.
I have made a fork of the original kivydigitalclock here. It should be easier to use than the original. You can add it to your .kv file just as any other widget. For example, something like:
<ContScreen>:
FloatLayout
size_hint: .1,.1
canvas.before:
Color:
rgba: 0,0,0,1
Rectangle:
pos: self.pos
size: self.size
Label:
text: app.time
DigitalClock:
pos_hint: {'right': 1.0, 'center_y': 0.5}
size_hint: (0.2, 0.2)
should work. Note that in your main .py file you will need to include:
from digitalclock.digitalclock import DigitalClock
(assuming that the digitalclock.py file is in a digitalclock folder)

Categories

Resources