Kivy Image size changed automatically - python

I am new to the Kivy framework and have an issue with the size of the loaded Image on my canvas. I have a png image of size 647x1778, and load it into a custom widget as follows:
class CharWidget(Widget):
def __init__(self, **kwargs):
self.glyph = kwargs.pop("glyph")
Widget.__init__(self, **kwargs)
self.path = "/tmp/satie.png"
self.png = Image(source=self.path)
self.add_widget(self.png)
def on_touch_down(self, touch):
self.png.pos = (touch.x, touch.y)
with self.canvas:
Color(1, 0, 0, .5)
Rectangle(pos=self.png.pos, size=(self.glyph["width"], self.glyph["height"]))
class SatieApp(App):
def build(self):
parent = Widget()
with parent.canvas:
Color(1,0,0)
parent.add_widget(CharWidget(glyph=Char(name="clefs.G", font="haydn").glyph))
return parent
But when I click on the window the image size is smaller that it's original size. I don't understand where this re-scaling happens, how can I prevent it. The original size is for instance in the texture_size but doing self.png.size = self.png.texture_size i.e. resizing the image size has no effect. Can any one help understanding this?

Related

In Kivy programming, where should buttons be created/resized/repositioned in a class created to be used other classes?

#This class is to be used with other classes of widgets, not with the class of kivy.app.
class TempatureFloatLayout(FloatLayout):
tempature = NumericProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_interval(self.update, 1)
self.btn = Button()
self.btn.bind(on_press=self.do_something)
self.add_widget(self.btn)
def do_something(self, self_button):
pass
def update(self, dt):
self.btn.size = self.size # I can only resize and reposition the button here.
self.btn.pos = self.pos # pos and size are assigned with the pos and size
# values of the widget used
... the other codes
class TempatureFloatLayout(FloatLayout) can be used successfully in other classes. The code works correctly as it is. But, When every update, the position and size of the button is to be resized and repositioned. This doesn't feel right to me. How to bind a widget that is used and a button that is used in a different class. Where did I do wrong or is this usage correct?

Python Kivy - Save canvas to a file

Here I have a simple kivy paint app taken from their docs https://kivy.org/doc/stable/tutorials/firstwidget.html and modified by me, attempting to add a save button which would save the canvas to the file image.jpg
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):
with self.canvas:
Color(255, 255, 255)
Ellipse(pos=(touch.x/ 2, touch.y/ 2), size=(1, 1))
touch.ud['line'] = Line(points=(touch.x, touch.y))
def on_touch_move(self, touch):
touch.ud['line'].points += [touch.x, touch.y]
class MyPaintApp(App):
def build(self):
parent = Widget()
self.painter = MyPaintWidget()
clearbtn = Button(text='Clear',font_size=30,pos=(100,0))
clearbtn.bind(on_release=self.clear)
savebtn = Button(text='Save',font_size=30)
savebtn.bind(on_release=self.save)
parent.add_widget(self.painter)
parent.add_widget(savebtn)
parent.add_widget(clearbtn)
return parent
def save(self, obj):
self.painter.export_as_image().save('image.jpg')
def clear(self, obj):
self.painter.canvas.clear()
MyPaintApp().run()
the save button does appear next to the clear button, and it does create the file image.jpg when I click it. But for some reason the file is always a blank black image with nothing on it, instead of the canvas with whatever I have drawn.
The problem is that your MyPainter widget has its default size of (100,100), and its default position of (0,0), so it is actually behind your Save Button. Any drawing that you do in the middle of the App display is not in the MyPainter widget, so saving to an image will be blank.
The fix is to set pos and size of the MyPainter widget so that it can be drawn on. You probably also want to use collide_point() in your on_touch_down() and on_touch_move() methods to ensure that you can only draw in the MyPainter widget.

Python / Kivy - Changing Screen with phone screen orientation (android)

I haven't found anything on the internet so far, all I want to know is if its possible to change the current screen in kivy depending on the orientation of the phone's screen (Landscape or portrait) and how to do it. or at least a link to a tutorial because I couldn't find one myself.
I haven't found a way of doing this by recognizing the android device's orientation. However, the following program changes it's contents by comparing the window's height and width. The program's Label changes dynamically, so when the width is greater (landscape mode) it's Label has a different text then when the height is greater (portrait mode). Currently it works on Windows, but unfortunately I don't have a Linux system to build an android version. Theoretically it should work, but i'm not 100% sure.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.graphics import Rectangle, Color
class MainScreen(FloatLayout, Label):
"""MAIN WINDOW CLASS"""
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
with self.canvas.before:
Color(0.988, 0.725, 0.074, 1, mode='rgba')
self.rect = Rectangle(pos=self.pos, size=self.size)
self.bind(size=self.update_rect)
self.titlos = Label(text="",
bold=True,
text_size=(None,None),
font_size="20sp",
pos_hint={'center_x': 0.5, 'center_y': .85},
size_hint_y=None,
size = self.size,
height=self.texture_size[1],
halign="center",
valign = "middle",
color=(0.055, 0.235, 0.541, 1))
self.add_widget(self.titlos)
self.bind(size=self.update_orientation)
def update_rect(self, *args):
"""FUNCTION TO UPDATE THE RECATANGLE OF CANVAS TO FIT THE WHOLE SCREEN OF MAINSCREEN ALWAYS"""
self.rect.pos = self.pos
self.rect.size = self.size
def update_orientation(self, *args):
"""FUNCTION TO UPDATE THE SCREEN CONTENTS WHEN THE WINDOW SIZE CHANGES"""
if self.parent.size[1] > self.parent.size[0]:
self.titlos.text = "This is\nPortrait\nOrientation"
else:
self.titlos.text = "This is Landscape Orientation"
# This is just for checking. Not essential to the program.
print("Width:", self.parent.size[0], ", Height:", self.parent.size[1])
class main(App):
"""BUILDING THE APP"""
def build(self):
return MainScreen()
if __name__ == "__main__":
main().run()
You can use the update_orientation function to include whatever you need to change when the orientation changes.

Get size from widget init

How can I find out the size of the screen (widget in this case) from the init of the widget? Below there are two print functions: one returns a default widget size, the other returns the real size of the widget.
from kivy.app import App
from kivy.uix.image import Image
from kivy.config import Config
class MyScreen(Image):
def __init__(self, **kwargs):
super(MyScreen, self).__init__ (**kwargs)
self.size_hint = 1, 1
print self.size #returns 100, 100
def on_touch_down(self, *ignore):
print self.size #returns real size for the screen 1280 800
class TemplateApp(App):
Config.set('graphics', 'fullscreen', 'auto')
def build(self):
return MyScreen()
if __name__ == "__main__" :
TemplateApp().run()
Both return the correct result, the widget size is 100, 100 during the __init__. It is updated later by its parent, in this case the Window itself.
If you care about size changes, bind a function to its size that does whatever updating you need.

How to allow user to choose file as background image in kivy?

Or, how to do so using python, give it an ID, and set it as background image in kv language?
I would like to be able to draw on top of an image instead of a black screen, which I am doing here:
edited
new problem: upload button does not work, here is new code
from random import random
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.graphics import Color, Line, Rectangle
from kivy.uix.filechooser import FileChooserListView, FileChooserIconView
from kivy.uix.floatlayout import FloatLayout
class MyPaintWidget(Widget):
def on_touch_down(self, touch):
color = (random(), random(), random())
with self.canvas:
Color(*color)
d = 30.
touch.ud['line'] = Line(points=(touch.x, touch.y))
def on_touch_move(self, touch):
touch.ud['line'].points += [touch.x, touch.y]
class MyPaintApp(App):
def build(self):
parent = Widget()
painter = MyPaintWidget()
Choose = Button(text = 'upload image')
parent.add_widget(painter)
parent.add_widget(Choose)
def chooose_file(obj):
fc = FileChooserIconView(title= 'upload image')
image_path = self.fc.selection[0]
image_name = file_path.split('/')[-1]
with self.canvas.before:
Rectangle(
size=self.size,
pos=self.pos,
source=image_name)
Choose.bind(on_release=choose_file)
return parent
if __name__ == '__main__':
MyPaintApp().run()
What about this:
If you used the kivy filechooser to get the user to select an image file,
then you could use the .selection attribute of the filechooser to get the name and/or path of that file. Once you have that, you could use it to set the source of a Rectangle on the canvas of the layout etc. where you want the background image.
For instance, to set a background image on a BoxLayout, inside the class that inherits from the BoxLayout:
fc = FileChooserIconView(title="Choose Image")
image_path = self.fc.selection[0]
image_name = file_path.split('/')[-1]
with self.canvas.before:
Rectangle(
size=self.size,
pos=self.pos,
source=image_name)
This is of course a very simplistic example, and isn't really taking the rest of your code into account, but with the kivy docs on FileChooser you should get it. Worth noting also that you could do this in the kv file, perhaps much more cleanly.

Categories

Resources