Domanda

I'm new to kivy and need some assistance with the following problem. I adding numbers/operators as widgets (labels) dynamically and at a random position to a layout(FloatLayout). The idea is that when I clicked on a number/operator it will draw a circle around the number/operator. I get some very strange behaviour. Does not matter what number/operator I click the selection circle is only drawn around the last added label. Then to confuse me even more the other number/operator is circled if I press on some random point on the screen

following is the core of my code:

class SelectedObject(Label):
    selected = BooleanProperty()
    refresh = BooleanProperty()

    def __init__(self, **kwargs):
        super(SelectedObject, self).__init__(**kwargs)
        self.center_x = randint(0, Window.width/2) 
        self.center_y = randint(0, Window.height/2)

        self.bind( refresh = self.redraw )

    def redraw(self, *args):
        #print('Redraw for: ' + self)
        self.canvas.after.clear()
        if self.selected:
            with self.canvas.after:
                Line(circle=(self.center_x, self.center_y, 20))

        self.canvas.ask_update()

    def on_touch_down(self, touch):
        print("touch@: " + str(touch))
        if not self.collide_point(touch.x, touch.y):
            return False
        print("yip: " + self)
        self.selected = not self.selected
        self.refresh = not self.refresh  # force a redraw
        return True

class GameNumber(SelectedObject):
    pass

class Operator(SelectedObject):
    pass

class GameApp(App):
    numberArr = ListProperty([])
    operatorArr = ListProperty([])

    def build(self):
        f = FloatLayout()

        #populate numberArr and operatorArr
        self.buildLevel()

        for number in self.numberArr:
            numberItem = GameNumber(text = str(number))
            f.add_widget(numberItem)

        for operator in self.operatorArr:
            f.add_widget(Operator(text = operator))

        return f
È stato utile?

Soluzione

The problem here is that you have not set sizes to the labels. So each label takes up as much space as it can and the last label being on top, it gets the circle.

You need to pass each GameNumber and Operator some sort of size_hint and/or size. For example, if you want each label to be 10 by 10, you can do something like this: numberItem = GameNumber(text=str(number), size_hint=(None, None), size=(10, 10)). You can set their size relative to the window size by for example setting size_hint=(0.1, 0.1).

Remember that size_hint is always (1, 1) by default, so you need to change it something else if you want your widgets to be smaller than the space of the container and set size_hint=(None, None) if you want to set a fixed size yourself.

If you want to position the labels randomly around the screen, take a look at pos_hint, which is more convenient than playing with the size of the window directly. Also, remember that there's a chance that multiple labels might get on top of each other or at the very borders of the window or even outside if you are not careful.

EDIT: To help you find the source of these kind of problems (that usually relate to layout issues), take a look at Kivy Widget Area Display

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top