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

Python 动态更改kivy中标签的背景,python,kivy,Python,Kivy,我试图用这个简单的程序动态地改变Kivy中标签的背景色。它的目的是产生一个由红细胞和黑细胞组成的网格。然而,我得到的只是位置(7,0)上的一个红细胞(我正在打印位置) 有没有关于如何获得红色/黑色棋盘格的想法?问题是,在实际构建应用程序之前,每个标签的位置是(0,0),大小是(100100)。因此,所有画布绘制都是在这些位置和大小上完成的。您可以通过等待直到指定位置和大小之后再执行棋盘效果来获得棋盘效果。我用一个时钟来做这件事。计划一次: from kivy.app import App fro

我试图用这个简单的程序动态地改变Kivy中标签的背景色。它的目的是产生一个由红细胞和黑细胞组成的网格。然而,我得到的只是位置(7,0)上的一个红细胞(我正在打印位置)


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

问题是,在实际构建应用程序之前,每个标签的位置是(0,0),大小是(100100)。因此,所有画布绘制都是在这些位置和大小上完成的。您可以通过等待直到指定位置和大小之后再执行棋盘效果来获得棋盘效果。我用一个
时钟来做这件事。计划一次

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Color, Rectangle
from kivy.clock import Clock
from kivy.core.window import Window

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))
                l.rowcol = (i,j)
                self.add_widget(l)



class GridApp(App):

    def build(self):
        self.g = MyGrid(8,8)
        Window.bind(size=self.checkerboard)
        return self.g

    def checkerboard(self, *args):
        for l in self.g.children:
            count = l.rowcol[0] + l.rowcol[1]
            if count % 2:
                l.set_bgcolor(1, 0, 0, 1)
            else:
                l.set_bgcolor(0, 0, 0, 1 )


if __name__=="__main__":
    app = GridApp()
    Clock.schedule_once(app.checkerboard, 1)
    app.run()

问题是,在实际构建应用程序之前,每个标签的位置都是(0,0),大小都是(100100)。因此,所有画布绘制都是在这些位置和大小上完成的。您可以通过等待直到指定位置和大小之后再执行棋盘效果来获得棋盘效果。我用一个
时钟来做这件事。计划一次

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.graphics import Color, Rectangle
from kivy.clock import Clock
from kivy.core.window import Window

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))
                l.rowcol = (i,j)
                self.add_widget(l)



class GridApp(App):

    def build(self):
        self.g = MyGrid(8,8)
        Window.bind(size=self.checkerboard)
        return self.g

    def checkerboard(self, *args):
        for l in self.g.children:
            count = l.rowcol[0] + l.rowcol[1]
            if count % 2:
                l.set_bgcolor(1, 0, 0, 1)
            else:
                l.set_bgcolor(0, 0, 0, 1 )


if __name__=="__main__":
    app = GridApp()
    Clock.schedule_once(app.checkerboard, 1)
    app.run()

如果使用以下方法打印
self.pos

with self.canvas.after:
    [...]
    print(self.pos)
    [...]
仅获得值
[0,0]
,这导致得出结论:所有矩形都是在该位置绘制的,因此它们是重叠的,这就是您观察到的

例如,为了验证这一点,我们将一个参数more传递给函数集_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)
我们得到以下结果:

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

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

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

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


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

如果使用以下方式打印
self.pos

with self.canvas.after:
    [...]
    print(self.pos)
    [...]
仅获得值
[0,0]
,这导致得出结论:所有矩形都是在该位置绘制的,因此它们是重叠的,这就是您观察到的

例如,为了验证这一点,我们将一个参数more传递给函数集_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)
我们得到以下结果:

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

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

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

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


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

在创建后立即尝试打印
l.pos
。你会发现位置永远不会改变。它总是
0,0
。这就是为什么在左下角只有一个正方形(即
0,0
pos)。看看这个答案,它可能会帮助您:在创建
l.pos
后立即打印它。你会发现位置永远不会改变。它总是
0,0
。这就是为什么在左下角只有一个正方形(即
0,0
pos)。看看这个答案,它可能会帮助你:如果我执行你的代码并更改窗口的大小,你会得到以下结果:这是一个不合适的效果。这是另一个问题,但可以通过调用
app.build()
方法中的
window.bind(size=self.checkboard)
来解决。我编辑了我的答案以处理大小更改。如果我执行您的代码并更改窗口的大小,您会得到以下结果:这是一个不适当的效果。这是另一个问题,但可以通过调用
app.build()
方法中的
window.bind(size=self.checkboard)
来修复。我已经编辑了我的答案来处理大小的变化。这在kivy 2.0.0中非常有用。好奇为什么小部件在调整大小时会自动调整背景,直到改变背景。它是否将kv lang中定义的初始
矩形
绑定到自动调整事件大小?这在kivy 2.0.0中非常有用。好奇为什么小部件在调整大小时会自动调整背景,直到改变背景。是否将kv lang中定义的初始
矩形
绑定到自动调整事件大小?