Vollkaracho Vollkaracho - 5 months ago 38
Python Question

Export_to_png only saves background

I recently learnt about the Python framework kivy and started to follow the simple paint app tutorial. Now I want to save what was drawn as a .png file but instead of the colored dots it only exports the black background.

This is my code example:

import kivy
kivy.require("1.9.1")

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.graphics import Color, Ellipse, Line

class MyPaintWidget(Widget):
def on_touch_down(self,touch):
color=(0,0,1)
with self.canvas:
Color(*color)
d=30.
Ellipse(pos=(touch.x-d/2., touch.y-d/2.), size=(d,d))

class MyPaintApp(App):

def build(self):
parent=Widget()
self.painter=MyPaintWidget()
ssbtn=Button(text='Save')
ssbtn.bind(on_release=self.save_screenshot)
parent.add_widget(self.painter)
parent.add_widget(ssbtn)
return parent

def save_screenshot(self,obj):
self.painter.export_to_png("screenshot.png")


if __name__ == '__main__':
MyPaintApp().run()


What am I doing wrong? Thanks for your help.

Answer

You are missing one thing - Widget won't set its size and position automatically to whole Window size, but only to default ones i.e. pos = [0, 0] size = [100, 100] because Window != Layout and even adding it to something that doesn't inherit from a Layout won't make it better (Widget != Layout) which you can easily see if you look a that saved png (is too small).

self.painter=MyPaintWidget(size=[800,600])

will make the job for you if you plan to stay only on pc and only with the default Window size. If not, then use:

from kivy.core.window import Window
self.painter=MyPaintWidget(size=Window.size)

which seems to be more practical, yet you're still not there. An optimal solution would be using a Layout which does these things for you such as BoxLayout, GridLayout or some others.

And a perfect solution for you would be to use a StencilVewin a Layout, which when is placed won't take a screenshot of the whole canvas, but only the part you'd think it'll take i.e. the part sized as the Widget itself placed on its position.

Try drawing outside of the red box. Inspector will provide you with showing widgets in a color and other functions, so definitely try it as it was mentioned in the comments.

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.uix.stencilview import StencilView
from kivy.graphics import Color, Ellipse, Line, Rectangle

class MyPaintWidget(StencilView):
    def on_touch_down(self,touch):
        color=(0,0,1)
        with self.canvas:
            Color(*color)
            d=30.
            Ellipse(pos=(touch.x-d/2., touch.y-d/2.), size=(d,d))

class MyPaintApp(App):
    def build(self):
        parent=Widget()
        self.painter=MyPaintWidget(size=[i/2.0 for i in Window.size])
        with self.painter.canvas:
            Color(1, 0, 0, 0.3)
            Rectangle(pos=self.painter.pos, size=self.painter.size)
        ssbtn=Button(text='Save')
        ssbtn.bind(on_release=self.save_screenshot)
        parent.add_widget(self.painter)
        parent.add_widget(ssbtn)
        return parent

    def save_screenshot(self,obj):
        self.painter.export_to_png("screenshot.png")
MyPaintApp().run()
Comments