使用自定义小部件 Kivy

3 投票
1 回答
12744 浏览
提问于 2025-04-18 00:55

我正在尝试用一些自定义的控件来构建一个kivy应用。不过,每次我尝试使用这些控件时,它们在我的布局中总是无法正常工作。比如,使用一个普通的按钮:

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"

这个按钮的表现是我预期的,它基本上占据了整个窗口。然而,当我试着用我的自定义按钮替换这个普通按钮时,

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:

它只出现在窗口的左下角,并且没有像按钮那样的行为。我到底漏掉了什么呢?

另外,真的有必要用这种方式来创建一个自定义按钮吗?kivy的教程是用这种方法来制作他们的自定义按钮,但我难道不能用这样的方式

Button:
    on_press: root.do_action()

让每个按钮的行为都不一样吗?

1 个回答

9

你的实际问题是,虽然你的 MyWidget 被放在了 kv 文件中的 BoxLayout 里,但它的子 BoxLayout 并没有设置为和 MyWidget 一样的大小,所以它就保持了默认的大小和位置,也就是屏幕左下角的 (100, 100)

你可以通过给它加上额外的 size: root.size 规则来解决这个问题,就像你在 <RootWidget> 规则中做的那样。其实通常来说,直接使用一个 BoxLayout(也就是让它继承 BoxLayout 而不是 Widget)会更简单,这样就能自动调整大小和位置了。

另外,正如 Joran 所说,如果你只是想在按钮被按下时做点什么,你可以使用第二种方法……这正是你想要做的!我不知道你在看哪个例子,但通常情况下,你不需要像你那样复杂的布局。

你可能还会感兴趣的是,在最新的版本(1.8)中,按钮的行为已经被抽象成了一个 ButtonBehavior 类,这个类负责检测触摸并适当地处理 on_press 等事件。这个行为不是一个小部件,所以你可以把它和任何其他小部件结合起来,制作出任何东西作为按钮!

撰写回答