在kivy中动态更改标签的背景

时间:2018-02-09 22:33:10

标签: python kivy

我正在尝试使用这个简单的程序动态更改Kivy中Label的背景颜色。它旨在产生红色和黑色细胞的网格。但是,我得到的只是位置(7,0)的红色单元格(我正在打印位置)。

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Color, Rectangle

class LabelX(Label):
    def set_bgcolor(self,r,b,g,o,*args):
        self.canvas.after.clear()
        with self.canvas.after:
            Color(r,g,b,o)
            Rectangle(pos=self.pos,size=self.size)


class MyGrid(GridLayout):

    def __init__(self,cols,rows,**kwargs):
        super(MyGrid,self).__init__(**kwargs)
        self.cols = cols
        for i in range(rows):
            for j in range(cols):
                l = LabelX(text=str(i)+","+str(j))
                if (i*rows+j)%2:
                    l.set_bgcolor(1,0,0,1)
                else:
                    l.set_bgcolor(0,0,0,1)
                self.add_widget(l)



class GridApp(App):

    def build(self):
        g = MyGrid(8,8)
        return g

if __name__=="__main__":
    GridApp().run()

关于如何获得红色/黑色棋盘的任何想法?

2 个答案:

答案 0 :(得分:1)

问题是每个标签位置都是(0,0),大小是(100,100),直到实际构建应用程序。所以你所有的画布都是在这些位置和尺寸上完成的。您可以通过等待分配位置和大小,然后执行棋盘效果来获得棋盘效果。我使用array([[4, 2], [2, 3], [7, 4]]) array([[ 1., 4., 2., 16., 8., 4.], [ 1., 2., 3., 4., 6., 9.], [ 1., 7., 4., 49., 28., 16.]])

执行此操作
Clock.schedule_once

答案 1 :(得分:1)

如果使用以下内容打印self.pos

with self.canvas.after:
    [...]
    print(self.pos)
    [...]

只获得了值[0, 0],并得出所有矩形都在该位置绘制的结论,因此它们是叠加的,这就是你所观察到的。

例如,为了验证这一点,我们将一个参数更多地传递给函数set_bgcolor(),它将作为循环的索引,我们将它用作参数来定位位置:

    def set_bgcolor(self, r, b, g, o, i):
        [..]
            Rectangle(pos=[100*i, 100*i],size=self.size)

class MyGrid(GridLayout):
    def __init__(self,cols,rows,**kwargs):
        [...]
                if (i*rows+j)%2:
                    l.set_bgcolor(1,0,0,1, i)
                else:
                    l.set_bgcolor(0,0,0,1, i)
                self.add_widget(l)

我们得到以下信息:

enter image description here

如果我们改变窗口的大小,矩形也不会改变:

enter image description here

因此,如果您希望Rectangle是Label的底部,Rectangle的位置和大小应该与Label相同,因此您必须使用Label和Rectangle之间的两个属性进行绑定。你还必须使用canvas.before而不是canvas.after否则Rectangle将被绘制在Label的顶部。

class LabelX(Label):
    def set_bgcolor(self,r,b,g,o):
        self.canvas.before.clear()
        with self.canvas.before:
            Color(r,g,b,o)
            self.rect = Rectangle(pos=self.pos,size=self.size)

        self.bind(pos=self.update_rect,
                  size=self.update_rect)

    def update_rect(self, *args):
        self.rect.pos = self.pos
        self.rect.size = self.size

enter image description here

enter image description here

enter image description here

我的解决方案的优势在于它独立于外部窗口小部件或布局,因为矩形的位置和大小仅取决于标签。