【问题标题】:kivy not adding/placing widgets properly when adding in for-loop在for循环中添加时,kivy没有正确添加/放置小部件
【发布时间】:2019-04-14 01:45:55
【问题描述】:

我想在屏幕上放置 6 个块(小部件)。我首先更新块的“pos”属性,然后尝试将它们一一添加到屏幕上。问题是最后一个块根本没有放置,所有其他块都在它们的邻居位置,而不是给他们的位置。

我尝试了多种变体,例如在初始化时使用 kwarg 设置位置,但没有奏效。似乎我没有得到任何东西,所以我寻求帮助。有人可以告诉我为什么这不起作用吗?

class Block(Widget):

    def __init__(self, red, green, blue, **kwargs):
        super(Block, self).__init__(**kwargs)
        self.canvas.add(Color(red, green, blue, 1))


class GameEnvironment(Widget):

    def __init__(self, **kwargs):
        super(GameEnvironment, self).__init__(**kwargs)
        self.blocks = self.create_blocks()
        self.position_blocks()
        self.add_blocks()

    def create_blocks(self):
        red_block = Block(1, 0, 0)
        blue_block = Block(0, 0, 1)
        green_block = Block(0, 1, 0)
        black_block = Block(0, 0, 0)
        orange_block = Block(1, .55, 0)
        celeste_block = Block(.5, 1, .83)
        return [red_block, blue_block, green_block, black_block, orange_block, celeste_block]

    def position_blocks(self):
        x = 0
        for block in self.blocks:
            block.pos = [x, 0]
            print("position:", block.pos)
            x += 100


    def add_blocks(self):
        for block in self.blocks:
            print("drawing block")
            self.add_widget(block)

class BlocksGameApp(App):
    def build(self):
        game_environment = GameEnvironment()
        return game_environment


BlocksGameApp().run()

.kv:

<GameEnvironment>:
    canvas:
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            pos: self.pos
            size: self.size

<Block>:
    width: 100
    height: self.width
    canvas:
        Rectangle:
            pos: self.pos
            size: self.size

预期:6 个彼此相邻的矩形,左下角为红色。

结果:5 个矩形,第一个矩形位于位置 100, 0。

【问题讨论】:

    标签: python kivy


    【解决方案1】:

    问题 1

    所以颜色是在组之后添加的,但为什么不是全部 那么矩形是白色的呢?

    注意事项

    group这个词表示Color、Rectangles、Triangles、Lines、Ellipse等图形指令。

    回答 1

    参照本应用,构造函数的过程分为两步。

    第 1 步:实例化 - Block(...)

    每个块实例化时,都有一个图形指令为Rectangle的模板,组成一个组。

    模态视图
    Block:
        width: 100
        height: self.width
        canvas:
            Rectangle:
                pos: self.pos
                size: self.size
    

    第 2 步:添加颜色(...)

    实例化一个块后,添加到组中的下一条图形指令是Color。当 canvas 中省略关键字 afterbefore 时,它会应用默认值 after

    模态视图
    Block:
        width: 100
        height: self.width
        canvas:
            Rectangle:
                pos: self.pos
                size: self.size
            Color:
                rgba: 1, 0, 0, 1    # red colour
    

    总结

    因此,所有块都不是白色的,因为Color 指令是在组Rectangle 之后添加的。第一个块是白色的,因为最后执行的Color 指令来自根小部件GameEnvironment。 第二个块是红色的,因为之前执行的 Color 指令是红色的。第三块是蓝色的,因为之前执行的Color指令是蓝色的,以此类推。

    以下示例说明了与您的程序等效的情况,但背景颜色为黑色,每个块都是手动添加的,小部件的默认大小为 100 x 100(size: 100, 100size_hint: 1, 1)。

    canvas.py

    from kivy.base import runTouchApp
    from kivy.lang import Builder
    
    runTouchApp(Builder.load_string("""
    Widget:
        canvas:
            Color:
                rgba: 0, 0, 0, 1    # black background colour 
            Rectangle:
                pos: self.pos
                size: self.size       
    
        Widget:
            pos: 0, 0
            canvas:
                Rectangle:
                    pos: self.pos
                    size: self.size
                Color:
                    rgba: 1, 0, 0, 1    # red colour
    
        Widget:
            pos: 100, 0
            canvas:
                Rectangle:
                    pos: self.pos
                    size: self.size
                Color:
                    rgba: 0, 0, 1, 1    # blue colour
    
        Widget:
            pos: 200, 0
            canvas:
                Rectangle:
                    pos: self.pos
                    size: self.size
                Color:
                    rgba: 0, 1, 0, 1    # green colour
    
        Widget:
            pos: 300, 0
            canvas:
                Rectangle:
                    pos: self.pos
                    size: self.size
                Color:
                    rgba: 0, 0, 0, 1    # black colour
    
        Widget:
            pos: 400, 0
            canvas:
                Rectangle:
                    pos: self.pos
                    size: self.size
                Color:
                    rgba: 1, 0.55, 0, 1    # orange colour
    
        Widget:
            pos: 500, 0
            canvas:
                Rectangle:
                    pos: self.pos
                    size: self.size
                Color:
                    rgba: 0.5, 1, 0.83, 1    # celeste colour
    
    """))
    

    回答 1 演示

    问题 2

    颜色不是添加到每个块对象本身吗?

    回答 2

    图形指令Color 被添加到每个块对象,但颜色不会立即应用,因为canvas 中省略了关键字before,它应用默认值after

    因此,当且仅当该小部件没有指定图形指令Color 时,颜色才会应用于下一个实例化小部件。

    问题

    最后一个块根本没有放置,所有其他块都在它们的 邻居的位置,而不是给他们的位置

    根本原因

    运行您的应用程序,确实添加了 6 个块。但是第一个块是白色的,因为最后执行的Color 指令来自根小部件GameEnvironment。第二块是红色的。第三块是蓝色的,以此类推。 Color 被添加到after 组中。

    解决方案

    将关键字before 添加到self.canvas.add(Color(...))

    片段

    class Block(Widget):
    
        def __init__(self, red, green, blue, **kwargs):
            super(Block, self).__init__(**kwargs)
            self.canvas.before.add(Color(red, green, blue, 1))
    

    Kivy Canvas » before

    before
    

    用于获取“之前”组的属性。

    输出

    【讨论】:

    • 这解决了,谢谢。后续问题:所以颜色是在组之后添加的,但为什么不是所有的矩形都是白色的?颜色不是添加到每个块对象本身吗?一个块对象获得添加到不同对象的颜色似乎有点令人困惑。
    • 非常感谢!很好的解释!
    • 不客气!请随时为我的答案投票。谢谢。
    【解决方案2】:

    Color 添加到Canvas 之后会将其添加到Rectangle 之后,因此不会影响当前的Rectangle。相反,将Color 添加到kv 中的Block 为:

    <Block>:
        width: 100
        height: self.width
        canvas:
            Color:
                rgba: self.r, self.g, self.b, 1
            Rectangle:
                pos: self.pos
                size: self.size
    

    然后将rgb 属性添加到Block 类:

    class Block(Widget):
        r = NumericProperty(1)
        g = NumericProperty(1)
        b = NumericProperty(1)
    
        def __init__(self, red, green, blue, **kwargs):
            super(Block, self).__init__(**kwargs)
            self.r = red
            self.g = green
            self.b = blue
    

    我认为这会解决它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-12
      • 1970-01-01
      • 2020-03-11
      • 2019-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多