2

I encountered some issue related to scatter object. From my codes below. After I resize a Scatter (self.size_hint_x, self.size_hint_y = 0.3, 0.3), the objects (canvas, label) inside the Scatter is not resized as well. I did tried to apply size_hint=1 to the Canvas and Label inside the Scatter, however the result still the same.

Another issue I encountered is the retrieving of the X, Y position (relative to the parent) for the Canvas/Label in a Scatter. It always give me (0,0).

My Code

from kivy.app import App
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.scatter import Scatter
from kivy.graphics import Color, Rectangle, Canvas

class Avatar(Scatter):
    def __init__(self, **kwargs):
        super(Avatar, self).__init__(size_hint=(None,None), **kwargs)

        with self.canvas:
            Color(0, 0, 0)
            Rectangle(pos=(self.x, self.y), size=(self.width, self.height))

        self.lbl = Label(text='Test', size_hint_x=1, size_hint_y=1)
        self.add_widget(self.lbl)

        # Scatter size is 30% of the GameBackground
        # ISSUE: After resize my Scatter, the objects inside is not resized as well.
        self.size_hint_x, self.size_hint_y = 0.3, 0.3


class GameBackground(FloatLayout):
    def __init__(self, **kwargs):
        super(GameBackground, self).__init__(**kwargs)

        with self.canvas:
            Color(1, 0, 1)
            Rectangle(pos = (0, 0), size = (Window.width,Window.height))

        self.elf = Avatar()
        self.add_widget(self.elf)
        self.elf.x = 200
        self.elf.y = 300

        # Get the X, Y position of the Scatter and the label inside the Scatter relative to the parent.
        print self.elf.pos      #<-- This works.
        print self.elf.lbl.pos  #<-- ISSUE: This not working.


class GameApp(App):
    def build(self):
        return GameBackground()


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

Did I miss something? Thanks for any advise.

I'm new to Kivy. So pardon me if my qns is dumb. :P

oneace
  • 117
  • 2
  • 10
  • I have found this in Widget doc. It state that "*The default size is (100, 100), if the parent is not a Layout. For example, adding a widget inside a Button, Label, will not inherit from the parent size or pos.*" Seem i will need to find alternative implementation. – oneace Jun 21 '13 at 14:04
  • did you check my last answer? I also pointed you to [ScatterLayout](http://kivy.org/docs/api-kivy.uix.scatterlayout.html) – toto_tico Jun 24 '13 at 12:05

1 Answers1

5

Did you read the documentation for Scatter at all. It says that

...specific behavior makes the scatter unique, and there are some advantages / constraints that you should consider:

  1. The children are positioned relative to 0, 0. The scatter position has no impact of the position of children.
  2. This applies to the size too. If you want to resize the scatter, use scale, not size. (read #1.)

That answer your first question. It says use scale, not size. There is also the the method apply_transform that you may find useful for other transformations. I have never tried this method though but I cannot see the translate value (I can see Rotate and Scale)

Regarding to your second question. You are adding a Rectangle in the self.x and self.y position that is (0,0). So, your Rectangle is in that position. If you drag (using your fingers or mouse) your widget. The position of the Rectangle remains relative to the Scatter. So, unless you change the position of the Rectangle (with code) it will be always be in the (0,0). The transformations are always relative to the Scatter.

This question might be related and explains a few issues with not using the Kivy Language to add Vertex Instructions (i.e. Rectangles). You should consider it because what you are doing seems to be related.

* EDIT - just the necessarily corrections according to my understanding of what you are trying to achieve *

1) Don't use size hints like the ones you are using.

1.1) Instead of:

self.lbl = Label(text='Test', size_hint_x=1, size_hint_y=1)

use:

self.lbl = Label(text='Test', width=self.width, height=self.height)

1.2) And, instead of:

self.size_hint_x, self.size_hint_y = 0.3, 0.3

use:

self.scale = 0.3

2) The position is relative to the scatter. Therefore you need to transale the coordinates to the parent.

2.1) Instead of:

print self.elf.lbl.pos  #<-- ISSUE: This not working.

use:

print self.elf.to_parent(*self.elf.lbl.pos)

Here is the complete code:

from kivy.app import App
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.scatter import Scatter
from kivy.graphics import Color, Rectangle, Canvas

class Avatar(Scatter):
    def __init__(self, **kwargs):
        super(Avatar, self).__init__(size_hint=(None,None), **kwargs)

        with self.canvas:
            Color(0, 0, 0)
            Rectangle(pos=(self.x, self.y), size=(self.width, self.height))

        #self.lbl = Label(text='Test', size_hint_x=1, size_hint_y=1)
        self.lbl = Label(text='Test', width=self.width, height=self.height)
        self.add_widget(self.lbl)

        # Scatter size is 30% of the GameBackground
        # ISSUE: After resize my Scatter, the objects inside is not resized as well.
        # self.size_hint_x, self.size_hint_y = 0.3, 0.3
        self.scale = 0.3


class GameBackground(FloatLayout):
    def __init__(self, **kwargs):
        super(GameBackground, self).__init__(**kwargs)

        with self.canvas:
            Color(0, 0, 1)
            Rectangle(pos = (0, 0), size = (Window.width,Window.height))

        self.elf = Avatar()
        self.add_widget(self.elf)
        self.elf.x = 200
        self.elf.y = 300

        # Get the X, Y position of the Scatter and the label inside the Scatter relative to the parent.
        print self.elf.pos      #<-- This works.
        print self.elf.lbl.pos  #<-- ISSUE: This not working.
        print self.elf.to_parent(*self.elf.lbl.pos)

class GameApp(App):
    def build(self):
        return GameBackground()

if __name__ == '__main__':
    GameApp().run()
Community
  • 1
  • 1
toto_tico
  • 17,977
  • 9
  • 97
  • 116
  • I did read that Scatter section and actually tested it using scale method. Unfortunately, the result is not what i desired. The label/canvas inside the Scatter still did not cover the whole Scatter. – oneace Jun 21 '13 at 13:52
  • @oneace, sorry, I didn't understand that your intention is having the label of the size of your screen. In the same page of the documentation it also says "3. The scatter is not a layout. You must take care of size of children yourself." size_hint_x, size_hint_y and size_hint are available just in Layout widgets. You have to use height, width and size for the rest of the Widget. Maybe a [ScatterLayout](http://kivy.org/docs/api-kivy.uix.scatterlayout.html) is what you are looking for. – toto_tico Jun 22 '13 at 02:14
  • @oneace, btw, when you word "The canvas inside the Scatter still did not cover the whole Scatter." you might maybe be having the same misconception that I had a few weeks ago. Look to [this question](http://stackoverflow.com/questions/16983675/why-does-it-seems-that-the-widgets-share-the-same-canvas-in-kivy). – toto_tico Jun 22 '13 at 02:17
  • Thanks and cheers for the detailed elaboration. I tried both the above example and the ScatterLayout. Both gave me the desired result. All the objects within are resized together with the Scatter object. Regarding the xy position using to_parent method, it did give me the result i wanted. However, much exploration is needed for me to understand it. I will look into the coordination translation as you suggested. Thanks for the pointers. – oneace Jun 25 '13 at 06:48
  • @oneace, no worries. You might want to start your exploration comparing two similar layouts [FloatLayout](http://kivy.org/docs/api-kivy.uix.floatlayout.html) and [RelativeLayout](http://kivy.org/docs/api-kivy.uix.relativelayout.html) and then read about the methods: to_local, to_parent, to_widget and to_window [here](kivy.uix.widget.Widget.to_parent). – toto_tico Jun 25 '13 at 07:28