In the following code i don't explain two problems:
If I use method __init__ --> Scene.canvas = None
I don't underestand to relative position objects on image.
I wanted to obtain knowledges about coordinates system from Kivy Manual, but without success.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.image import Image
from kivy.graphics import Ellipse
class Scene(Widget):
"""
def __init__(self):
self.x = 0
self.y = 100
self.dir = 1
"""
def set_par(self):
self.x = 0
self.y = 100
self.dir = 1
def create_ball(self):
with self.canvas:
Ellipse(pos = (0,0), size = (40, 40))
img = Image(pos = (0,0), source = 'image1.png') # square 40x40pixels
self.add_widget(img)
class SceneApp(App):
def build(self):
scene = Scene()
scene.create_ball()
return scene
if __name__ == '__main__':
SceneApp().run()
Printscreen form my code:
You did not call super() in your __init__ method. So Widget's __init__ method just get completely overrited.
Then use FloatLayout instead of Widget
You can to do something like this:
from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import Ellipse
Window.size = (300, 300)
class Scene(FloatLayout):
def __init__(self, **kwargs):
super(Scene,self).__init__(**kwargs)
self.size = 300,300
def create_ball(self):
img = Image(pos = (-130, -130), source = 'image1.png') # square 40x40pixels
self.add_widget(img)
with self.canvas:
Ellipse(pos = (0,0), size = (40, 40))
class SceneApp(App):
def build(self):
scene = Scene()
scene.create_ball()
return scene
if __name__ == '__main__':
SceneApp().run()
Related
from kivy.uix.button import Button
from kivy.uix.behaviors.button import ButtonBehavior
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock
from kivy.uix.widget import Widget
from kivy.graphics import BorderImage
from kivy.graphics import Color, RoundedRectangle, Rectangle, Triangle
from kivy.core.window import Window
#from kivy.config import Config
from kivy.uix.checkbox import CheckBox
from kivy.uix.popup import Popup
from kivy.uix.scrollview import ScrollView
from kivy.uix.filechooser import FileChooserListView
from kivy.properties import ObjectProperty
class OpeningPage(FloatLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.but = RoButton(text = 'START', pos = (350,100), font_size=14, size=(100,60), size_hint=(None,None))
self.add_widget(self.but)
class RoButton(Button):
butt = ObjectProperty()
def __init__(self, **kwargs):
super(RoButton, self).__init__(**kwargs)
text = self.text
with self.canvas:
# Color(1., 0, 0)
self.butt = RoundedRectangle( size= self.size, pos = self.pos, radius =[400])
class UI(App):
def build(self):
self.screen_manager = ScreenManager()
self.opening_page = OpeningPage()
screen = Screen(name ='Opening_Page')
screen.add_widget(self.opening_page)
self.screen_manager.add_widget(screen)
return self.screen_manager
if __name__ == '__main__':
the_app = UI()
the_app.run()
Everytime I try to make a circular button using this code I get a box behind the circle. I tried doing self.canvas.before but still no luck if possible could answers be in python rather than .kv language thanks.
Attached image of problem]1
The box you see is the normal Button image. If you don't want that, probably don't use a Button, instead use class RoButton(ButtonBehavior, Widget):.
I want to draw image (*.png file) at FlayoutBox, on pc is result OK, after using KivyLauncher is on phone screen only white square. I tested two variants for drawing (draw_img_cnv and draw_img_wdg), but both results are bad.
Cann you explain me:
why is result white square on phone screen,
why draw_img_wdg isn't centered on pc,
how is diferent between both solutions?
Thank You!
from kivy.app import App
from kivy.graphics import Color, Rectangle, Ellipse
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.image import Image
import math
class Screen(FloatLayout):
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
self.li_item = []
return
def draw_img_cnv(self):
size_img = (498, 498)
pos_img = (self.center[0] -size_img[0]/2.0, self.center[1] -size_img[1]/2.0)
with self.canvas:
Color(0, 1, 0, 1)
self.rect1 = Rectangle(size=self.size, pos=self.pos)
self. rose = Image(source="rose.png",pos=pos_img,size=size_img )
def draw_img_wdg(self):
size_img = (498, 498)
pos_img = (self.center[0] -size_img[0]/2.0, self.center[1] -size_img[1]/2.0)
with self.canvas:
Color(0, 1, 0, 1)
self.rect1 = Rectangle(size=self.size, pos=self.pos)
self. rose = Image(source="rose.png",pos=pos_img,size=size_img )
self.add_widget(self.rose)
return
class MainApp(App):
def build(self):
self.pos_sun = None
root = BoxLayout(orientation = 'vertical')
self.screen = Screen()
button = Button(text = 'Press',size_hint=(1, None), height=50)
root.add_widget(self.screen)
root.add_widget(button)
self.screen.draw_img_wdg()
self.screen.bind(size=self._update_rect, pos=self._update_rect)
return root
def _update_rect(self, instance, value):
self.screen.rect1.pos = instance.pos
self.screen.rect1.size = instance.size
self.screen.rose. pos = (instance.center[0] -498/2.0, \
instance.center[1] -498/2.0)
return
if __name__ == '__main__':
MainApp().run()
I am trying to display the speedometer in my MainWindow screen. Right now when i run the code, the speedometer works but it is not displayed on the MainWindow screen which i want rather it is just appearing on a normal screen. It is possible to combine class Gauge(Widget): and class MainWindow(Screen): together so that the speedometer will actually be displayed on the MainWindow?
.py file
import kivy
kivy.require('1.6.0')
from kivy.app import App
from kivy.clock import Clock
from kivy.properties import NumericProperty
from kivy.properties import StringProperty
from kivy.properties import BoundedNumericProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.uix.scatter import Scatter
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.uix.progressbar import ProgressBar
from os.path import join, dirname, abspath
from kivy.uix.screenmanager import Screen, ScreenManager
class WindowManager(ScreenManager):
pass
class MainWindow(Screen):
pass
class Gauge(Widget):
unit = NumericProperty(1.8)
value = BoundedNumericProperty(0, min=0, max=100, errorvalue=0)
path = dirname(abspath(__file__))
file_gauge = StringProperty(join(path, "cadran.png"))
file_needle = StringProperty(join(path, "needle.png"))
size_gauge = BoundedNumericProperty(128, min=128, max=256, errorvalue=128)
size_text = NumericProperty(10)
def __init__(self, **kwargs):
super(Gauge, self).__init__(**kwargs)
self._gauge = Scatter(
size=(1350,600),
do_rotation=False,
do_scale=False,
do_translation=False
)
_img_gauge = Image(
source=self.file_gauge,
size=(1350,600)
)
self._needle = Scatter(
size=(self.size_gauge, self.size_gauge),
do_rotation=False,
do_scale=False,
do_translation=False
)
_img_needle = Image(
source=self.file_needle,
size=(self.size_gauge, self.size_gauge)
)
self._glab = Label(font_size=self.size_text, markup=True)
self._progress = ProgressBar(max=100, height=20, value=self.value , size=(500,400))
self._gauge.add_widget(_img_gauge)
self._needle.add_widget(_img_needle)
self.add_widget(self._gauge)
self.add_widget(self._needle)
self.add_widget(self._glab)
self.add_widget(self._progress)
self.bind(pos=self._update)
self.bind(size=self._update)
self.bind(value=self._turn)
def _update(self, *args):
'''
Update gauge and needle positions after sizing or positioning.
'''
self._gauge.pos = self.pos
self._needle.pos = (self.x, self.y)
self._needle.center = self._gauge.center
self._glab.center_x = self._gauge.center_x
self._glab.center_y = self._gauge.center_y + (self.size_gauge / 4)
self._progress.x = self._gauge.x + (self.size_gauge/0.468 )
self._progress.y = self._gauge.y + (self.size_gauge/4 )
self._progress.width = self.size_gauge
def _turn(self, *args):
'''
Turn needle, 1 degree = 1 unit, 0 degree point start on 50 value.
'''
self._needle.center_x = self._gauge.center_x
self._needle.center_y = self._gauge.center_y
self._needle.rotation = (50 * self.unit) - (self.value * self.unit)
self._glab.text = "[b]{0:.0f}[/b]".format(self.value)
self._progress.value = self.value
class GaugeApp(App):
increasing = NumericProperty(1)
begin = NumericProperty(50)
step = NumericProperty(1)
def build(self):
box = BoxLayout(orientation='horizontal', padding=5)
self.gauge = Gauge(value=50, size_gauge=256, size_text=25)
box.add_widget(self.gauge)
Clock.schedule_interval(lambda *t: self.gauge_increment(), 0.05)
return box
def gauge_increment(self):
begin = self.begin
begin += self.step * self.increasing
if begin > 0 and begin < 100:
self.gauge.value = begin
else:
self.increasing *= -1
self.begin = begin
if __name__ == '__main__':
GaugeApp().run()
You need to create an instance of ScreenManager and an instance of Screen. Next you add_widget the Screen to ScreenManager and to the Screen you add box
sm = ScreenManager()
s1 = Screen()
s1.add_widget(box)
sm.add_widget(s1)
This is the complete code which uses your new classes
from kivy.app import App
from kivy.clock import Clock
from kivy.properties import NumericProperty
from kivy.properties import StringProperty
from kivy.properties import BoundedNumericProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.uix.scatter import Scatter
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.uix.progressbar import ProgressBar
from os.path import join, dirname, abspath
from kivy.uix.screenmanager import Screen, ScreenManager
class WindowManager(ScreenManager):
pass
class MainWindow(Screen):
pass
class Gauge(Widget):
unit = NumericProperty(1.8)
value = BoundedNumericProperty(0, min=0, max=100, errorvalue=0)
path = dirname(abspath(__file__))
file_gauge = StringProperty(join(path, "cadran.png"))
file_needle = StringProperty(join(path, "needle.png"))
size_gauge = BoundedNumericProperty(128, min=128, max=256, errorvalue=128)
size_text = NumericProperty(10)
def __init__(self, **kwargs):
super(Gauge, self).__init__(**kwargs)
self._gauge = Scatter(
size=(1350,600),
do_rotation=False,
do_scale=False,
do_translation=False
)
_img_gauge = Image(
source=self.file_gauge,
size=(1350,600)
)
self._needle = Scatter(
size=(self.size_gauge, self.size_gauge),
do_rotation=False,
do_scale=False,
do_translation=False
)
_img_needle = Image(
source=self.file_needle,
size=(self.size_gauge, self.size_gauge)
)
self._glab = Label(font_size=self.size_text, markup=True)
self._progress = ProgressBar(max=100, height=20, value=self.value , size=(500,400))
self._gauge.add_widget(_img_gauge)
self._needle.add_widget(_img_needle)
self.add_widget(self._gauge)
self.add_widget(self._needle)
self.add_widget(self._glab)
self.add_widget(self._progress)
self.bind(pos=self._update)
self.bind(size=self._update)
self.bind(value=self._turn)
def _update(self, *args):
'''
Update gauge and needle positions after sizing or positioning.
'''
self._gauge.pos = self.pos
self._needle.pos = (self.x, self.y)
self._needle.center = self._gauge.center
self._glab.center_x = self._gauge.center_x
self._glab.center_y = self._gauge.center_y + (self.size_gauge / 4)
self._progress.x = self._gauge.x + (self.size_gauge/0.468 )
self._progress.y = self._gauge.y + (self.size_gauge/4 )
self._progress.width = self.size_gauge
def _turn(self, *args):
'''
Turn needle, 1 degree = 1 unit, 0 degree point start on 50 value.
'''
self._needle.center_x = self._gauge.center_x
self._needle.center_y = self._gauge.center_y
self._needle.rotation = (50 * self.unit) - (self.value * self.unit)
self._glab.text = "[b]{0:.0f}[/b]".format(self.value)
self._progress.value = self.value
class GaugeApp(App):
increasing = NumericProperty(1)
begin = NumericProperty(50)
step = NumericProperty(1)
def build(self):
box = BoxLayout(orientation='horizontal', padding=5)
self.gauge = Gauge(value=50, size_gauge=256, size_text=25)
box.add_widget(self.gauge)
Clock.schedule_interval(lambda *t: self.gauge_increment(), 0.05)
sm = WindowManager()
s1 = MainWindow()
s1.add_widget(box)
sm.add_widget(s1)
return sm
def gauge_increment(self):
begin = self.begin
begin += self.step * self.increasing
if begin > 0 and begin < 100:
self.gauge.value = begin
else:
self.increasing *= -1
self.begin = begin
if __name__ == '__main__':
GaugeApp().run()
I have some simple code below that is just creating some rectangles with a color assigned to them, and then storing them into a FloatLayout. For some reason, the very first rectangle 'Brick' that I create, doesnt get a color, but all subsequent ones do. I have issues with my game also where when another widget collides with a brick, it updates the attributes of the brick to its left, and not itself. I think the two issues are related.
What is going on with the first instance of Brick (brick1) that is being added to the FloatLayout that it doesnt get the color created?
import kivy
kivy.require('1.10.0')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.properties import NumericProperty, ReferenceListProperty
from kivy.clock import Clock
from kivy.graphics import Rectangle, Ellipse, Color
from kivy.uix.floatlayout import FloatLayout
from kivy.vector import Vector
from kivy.utils import get_color_from_hex
import random
from kivy.config import Config
Window.size = (300,600)
class Brick(Widget):
def __init__(self, xloc, yloc, **kwargs):
super().__init__(**kwargs)
with self.canvas:
self.size = (25,25)
self.x = xloc
self.y = yloc
self.pos = (self.x,self.y)
self.body = Rectangle(pos=self.pos,size = self.size)
self.c = Color(1,0,1)
class Game(Widget):
def __init__(self,**kwargs):
super().__init__(**kwargs)
self.brick_container = FloatLayout(size = (25,25))
brick1 = Brick(50,100)
brick2 = Brick(100,100)
self.brick_container.add_widget(brick1)
self.brick_container.add_widget(brick2)
self.add_widget(self.brick_container)
def update(self,dt):
self.name = 'nothing'
class MyApp(App):
def build(self):
game = Game()
Clock.schedule_interval(game.update, 1.0/60.0)
return game
if __name__ == '__main__':
MyApp().run()
You have to set the color first and then the rectangle
class Brick(Widget):
def __init__(self, xloc, yloc, **kwargs):
super().__init__(**kwargs)
self.size = (25,25)
self.pos = (xloc , yloc)
with self.canvas:
self.c = Color(1,0,1)
self.body = Rectangle(pos=self.pos,size = self.size)
According to the docs when using a Drawing Instruction, use the color set above.
Drawing instructions
Drawing instructions range from very simple
ones, like drawing a line or a polygon, to more complex ones, like
meshes or bezier curves:
with self.canvas:
# draw a line using the default color
Line(points=(x1, y1, x2, y2, x3, y3))
# lets draw a semi-transparent red square
Color(1, 0, 0, .5, mode='rgba')
Rectangle(pos=self.pos, size=self.size)
For that reason in your original code the first Brick used the color by default(white), and the others if they had the correct color.
I am getting to know with kivy's manual slowly. I need to centered image in FloatLayout ans I set up size for FloatLayout according to advice: Kivy: Image sometimes is not centered in BoxLayout . Image is now in center FloatLayout sometimes. Position image in center dependes on value of parameter orientation. Influence of parameter' value is described here:
orientation = 'horizontal' - ---> image is centered
orientation = 'vertical' -----> image isn't centered
Thank You for your help!
from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import Ellipse
Window.size = (300, 300)
class Scene(FloatLayout):
def __init__(self, **kwargs):
super(Scene,self).__init__(**kwargs)
self.size = 300,300
def create(self):
img = Image(pos = (0, 0), source = 'grase40.png') # square 40x40pixels
self.add_widget(img)
with self.canvas:
Color=(1,0,0)
Ellipse(pos = (80,80), size = (40, 40))
class Title(BoxLayout):
def __init__(self,**kwargs):
super(Title, self).__init__(**kwargs)
self.orientation ='vertical'
self.scene = Scene()
self.add_widget(self.scene)
but = Button(text ='hallo', size_hint = (0.2, 1))
self.add_widget(but)
class SceneApp(App):
def build(self):
title = Title()
title.scene.create()
return title
if __name__ == '__main__':
SceneApp().run()