Kivy 创建小部件的新实例

3 投票
2 回答
1987 浏览
提问于 2025-04-28 01:12

我刚接触Kivy不久,有一些关于小部件(widgets)的问题。

几个月前我开始玩Kivy,读了一些文档,但可能有很多东西没弄明白。

我想知道是否可以创建多个相同类型的小部件实例,并且每个实例都有自己的属性?

我的目标是有几个矩形,可以独立地调整大小和拖动。

我正在上Java课,所以我会用我在那门课上学到的东西来做比较:

比如说,我有一个基本的rect.java类,它需要两个变量来表示宽度和高度。

在我的主.java代码文件中,我会写类似这样的代码来创建几个矩形类的实例:

rect s1 = new rect(2,3); // width & height
rect s2 = new rect(5,4);

这样,s1.height和s2.height就会有不同的值。

在Kivy中能做到类似的事情吗?目前我在我的.kv文件中设置了很多具有相同属性的类:

<rect1>:

    canvas:
        Color:
            rgba: 1, 0, 1, 0.5
        Rectangle:
            pos: root.center_x - root.width/2,root.center_y - root.height/2
            size: self.size
<rect2>:

    canvas:
        Color:
            rgba: 1, 1, 0, 0.5
        Rectangle:
            pos: root.center_x - root.width/2,root.center_y - root.height/2
            size: self.size

<rect3>:

    canvas:
        Color:
            rgba: 0, 1, 0, 0.5
        Rectangle:
            pos: root.center_x - root.width/2,root.center_y - root.height/2
            size: self.size

我在.py文件中写了代码,让它可以调整大小和拖动。现在,我复制并修改了代码,以便与每个额外的类一起使用。

目前,如果我使用:

Window.add_widget(rect1)

它会在旧的实例上直接创建一个新实例,但它们仍然共享相同的坐标和其他属性。如果我用鼠标拖动,所有这个类的实例都会跟着同样的坐标走。我的目标是有多个矩形,可以独立地调整大小和拖动。

暂无标签

2 个回答

1

你用尖括号(<, >)定义的每个条目都是类的声明,而不是类的实例。如果你想在kv文件中创建一个类的实例,并且想要不同的属性,就直接用没有尖括号的名字。

这里有一些基于你提供的代码片段的可运行代码:

<MovableRect>: 
    size: 50, 50
    canvas:
        Color:
            rgba: root.color
        Rectangle:
            size: self.size
            pos: self.pos

<MyRoot@Widget>: 
    MovableRect: 
        id: rect1
        color: 1, 0, 1, 0.5
        pos: 5, 5

    MovableRect:
        id: rect2
        color: 1, 1, 0, 0.5
        pos: 130, 130

    MovableRect:
        id: rect3
        color: 0, 1, 0, 0.5
        pos: 250, 250    

# instantiation of root widget
MyRoot: 

这是python文件(没有你提到的移动功能,因为你没有列出它):

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

class MovableRect(Widget):
    color = ListProperty([1, 0, 1, 0.5])

class Test1App(App):
    def build(self):
        pass

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

如果你想要更完整的例子,可以参考YouTube上很棒的kivy速成课程系列。有一个例子和你想做的非常相似: https://www.youtube.com/watch?v=ChmfVOu9aIc

1

一个Window里应该只有一个小部件,也就是应用的根部件。最好的做法是通过在App.build()中返回根部件的实例,或者在你应用的kv文件中直接包含一个根部件,让这个部件自动添加进来。

在这种情况下,使用FloatLayout会是最合适的选择。

另外,你还可以使用Scatter小部件来处理一些变换,比如移动、调整大小和旋转,这样可能会比自己手动去做更简单。只需要把每个小部件放在一个Scatter里,或者让你的小部件继承Scatter

撰写回答