I'm trying to build a kivy app using some custom widgets. However whenever I try to use them they never work with my layout. Using a normal button:

import kivy
kivy.require('1.8.0')

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ListProperty

class RootWidget(Widget):pass

class myApp(App):

    def build(self):
        global rw
        rw  = RootWidget()
        return rw

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

#:kivy 1.8.0

<RootWidget>:

    BoxLayout:
        size: root.size
        orientation: 'horizontal'
        spacing: 10
        padding: 10

        Button:
            id: abut
            text: "Custom Button"

This works as expected, my Button basically takes up the entire window. However when I try replacing the Button with my custom button

import kivy
kivy.require('1.8.0')

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ListProperty

class MyWidget(Widget):

     pressed = ListProperty([0, 0])

     def on_touch_down(self, touch):
         if self.collide_point(*touch.pos):
             self.pressed = touch.pos
             return True
         return super(MyWidget, self).on_touch_down(touch)

     def on_pressed(self, instance, pos):
         print ('pressed at {pos}'.format(pos=pos))

class RootWidget(Widget):pass

class someApp(App):

    def build(self):
        global rw
        rw  = RootWidget()
        return rw

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

#:kivy 1.8.0

<MyWidget>:
    BoxLayout:
        orientation: 'horizontal'
        spacing: 10

        Button:
            id: abut
            text: "Custom Button"        

<RootWidget>:

    BoxLayout:
        size: root.size
        orientation: 'horizontal'
        spacing: 10
        padding: 10

        MyWidget:

it only appears in the bottom left-hand corner of the window and doesn't behave like a button. What am I missing?

Furthermore, is it even necessary to create a custom button this way? The kivy tutorials used this sort of method to make their custom button but can't I just do something like this

Button:
    on_press: root.do_action()

to make each button behave differently?

有帮助吗?

解决方案

Your actual problem is that although your MyWidget is placed in a BoxLayout in the kv file, its child BoxLayout does not have its size set to the MyWidget size, and therefore just maintains the default size and position of (100, 100) in the bottom left of the screen.

You can fix this by giving it the extra size: root.size rule as you did within the <RootWidget> rule, or actually normally it's easier to just use a BoxLayout (i.e. subclass BoxLayout instead of Widget) which of course gives you the automatic resizing/positioning for free.

Also, as Joran said, if you just want to do something when the button is pressed you can use the second method...that's what you're intended to do! I don't know what example you are looking at, but you wouldn't normally need a complex arrangement like yours.

You might also be interested to know that in the most recent release (1.8) the button behavior has been abstracted to a ButtonBehavior class that handles detecting touches and dispatching on_press etc. appropriately. The Behavior isn't a widget, so you can subclass it with any other widget to make anything into a button!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top