在添加for循环时,kivy无法正确添加/放置小部件

时间:2019-04-12 22:40:24

标签: python kivy

我想在屏幕上放置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。

2 个答案:

答案 0 :(得分:0)

Color之后将Canvas添加到Rectangle,因此它不会影响当前的Rectangle。相反,应在Color中的Block上添加kv,如下:

<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

我认为这可以解决。

答案 1 :(得分:0)

问题1

  

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

注释

group 一词表示诸如颜色,矩形,三角形,直线,椭圆形等图形指示。

答案1

参考此应用程序,构造函数的过程分为两个步骤。

步骤1:实例化-阻止(...)

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

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

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

实例化一个块后,添加到该组的下一条图形指令为Color。如果after中省略了关键字beforecanvas,则会应用默认值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个演示

canvas without before

问题2

  

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

答案2

图形指令Color被添加到每个块对象,但是由于before中省略了关键字canvas,因此颜色没有立即应用,它应用了默认值{{ 1}}。

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

问题

  

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

根本原因

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

解决方案

将关键字Color添加到before

摘要

self.canvas.add(Color(...))

Kivy Canvas » before

class Block(Widget):

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

获得“之前”分组的属性。

输出

Result