Kivy 矩形重绘,self.pos 和 self.size 为 (0,0)

Posted

技术标签:

【中文标题】Kivy 矩形重绘,self.pos 和 self.size 为 (0,0)【英文标题】:Kivy rectangle redraw, self.pos and self.size are (0,0) 【发布时间】:2017-06-21 10:02:13 【问题描述】:

我正在使用循环来创建 27 个标签实例。这些标签需要使用它们的 Label.text 方法进行编号 - 我已经做到了。

我还需要能够使用 python 函数(基于其他输入)为这些标签(画布矩形)重新着色。 这是行不通的部分

基本上,GridLayout 的 init 方法创建了 29 个 custButton() 标签实例。此循环还为按钮重新编号(label.text),但 one 标签的重新着色不起作用。

我已经隔离了 self.pos 和 self.size 在 xBackground_Color 函数中都返回 (0,0) - 这就是为什么 new 矩形在旧矩形之后没有绘制清除(清除工作)。

为什么 self.pos 和 self.size 在 python 端不起作用?

我已经尝试了很多东西!如果可以的话,请帮忙。

这里是 kvMain.kv :

#:kivy 1.0.9

FloatLayout:
    canvas:
        Color:
            rgba: (64/255, 64/255, 64/255, 1) #Whole screen background
        Rectangle:
            pos: self.pos
            size: self.size
    BoxLayout:
        orientation: 'vertical'
        padding: 10
        FloatLayout: #Dummy widget
        myGrid:


<myGrid>:
    cols: 9
    spacing: 3
    padding: 3
    canvas.before:
        Color:
            rgba: (216/255, 216/255, 216/255, 1)
        Rectangle:
            pos: self.pos
            size: self.size

<custButtom>:
    canvas.before:
        Color:
            rgba: (191/255, 191/255, 191/255, 1)
        Rectangle:
            pos: self.pos
            size: self.size
    font_size: 14
    color: (90/255, 90/255, 90/255, 1)
    text: 'Er' #Don't ever want to see this text. Will set each label in loop
    size: self.texture_size

这里是 main.py:

from kivy.app import App
from kivy.lang import Builder

from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label

from kivy.graphics.vertex_instructions import Rectangle, Line
from kivy.graphics.context_instructions import Color

IN_Labels = 

class custButtom(Label):
    def __init__(self, **kwargs):
        super(custButtom, self).__init__(**kwargs)

    def xtext(self, newText):
        self.text = newText
        self.size = self.texture_size

    def xbackground_color(self, newR, newG, newB, newA):
        print('IN_Labels[14] pos ('+ str(IN_Labels[14].pos[0]) + ',' + str(IN_Labels[14].pos[1]) + ')   size ('+ str(IN_Labels[14].size[0]) + ',' + str(IN_Labels[14].size[1]) + ')')
        print('self pos ('+ str(self.pos[0]) + ',' + str(self.pos[1]) + ')   size ('+ str(self.size[0]) + ',' + str(self.size[1]) + ')')
        self.canvas.before.clear()

        with self.canvas.before:
            Color(newR, newG, newB, newA)
            #Problem is that self.size and self.pos are both (0,0)
            Rectangle(size=self.size, pos=self.pos)


class myGrid(GridLayout):
    def __init__(self, **kwargs):
        super(myGrid, self).__init__(**kwargs)

        for i in range(0, 27, 1):
            IN_Labels[i] = custButtom()
            self.add_widget(IN_Labels[i])
            #CAN change text, needs more work to get it right
            IN_Labels[i].xtext(str(i))

        # I need to be able to change backgroundcolor programatically
        IN_Labels[14].xbackground_color(1,0,0,1)

class MainApp(App):
    def build(self):
        return kvMain

kvMain = Builder.load_file("kvMain.kv")

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

【问题讨论】:

【参考方案1】:

找到了!我认为问题在于标签在被要求输入 self.size 和 self.pos 时实际上并没有 size 和 pos。

绑定一个函数来调整大小和重新定位它可以解决这个问题。

感谢 Alexander Taylor 出色的 YouTube 视频和我找到答案的博客:https://blog.kivy.org/2014/10/updating-canvas-instructions-declared-in-python/

kvMain.kv 变为:

#:kivy 1.0.9

FloatLayout:
    canvas:
        Color:
            rgba: (64/255, 64/255, 64/255, 1) #Whole screen background
        Rectangle:
            pos: self.pos
            size: self.size
    BoxLayout:
        orientation: 'vertical'
        padding: 10
        FloatLayout: #Dummy widget
        myGrid:


<myGrid>:
    cols: 9
    spacing: 3
    padding: 3
    canvas.before:
        Color:
            rgba: (216/255, 216/255, 216/255, 1)
        Rectangle:
            pos: self.pos
            size: self.size

<custButtom>:
    #CANVAS INSTRUCTION MOVED TO PYTHON INIT
    font_size: 14
    color: (90/255, 90/255, 90/255, 1)
    text: 'Er' #Don't ever want to see this text. Will set each label in loop
    size: self.texture_size

main.py 变成:

from kivy.app import App
from kivy.lang import Builder

from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label

from kivy.graphics.vertex_instructions import Rectangle, Line
from kivy.graphics.context_instructions import Color

IN_Labels = 

class custButtom(Label):
    def __init__(self, **kwargs):
        super(custButtom, self).__init__(**kwargs)

        with self.canvas.before:
            Color(191/255, 191/255, 191/255, 1)
            self.rect = Rectangle(pos=self.pos, size=self.size)

        #Ensure that everytime the Rectangle is updated, it's repositioned correctly
        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

    def xtext(self, newText):
        self.text = newText
        self.size = self.texture_size

    def xbackground_color(self, newR, newG, newB, newA):
        print('IN_Labels[14] pos ('+ str(IN_Labels[14].pos[0]) + ',' + str(IN_Labels[14].pos[1]) + ')   size ('+ str(IN_Labels[14].size[0]) + ',' + str(IN_Labels[14].size[1]) + ')')
        print('self pos ('+ str(self.pos[0]) + ',' + str(self.pos[1]) + ')   size ('+ str(self.size[0]) + ',' + str(self.size[1]) + ')')
        self.canvas.before.clear()

        with self.canvas.before:
            Color(newR, newG, newB, newA)
            self.rect = Rectangle(size=self.size, pos=self.pos)


class myGrid(GridLayout):
    def __init__(self, **kwargs):
        super(myGrid, self).__init__(**kwargs)

        for i in range(0, 27, 1):
            IN_Labels[i] = custButtom()
            self.add_widget(IN_Labels[i])
            #CAN change text, needs more work to get it right
            IN_Labels[i].xtext(str(i))

        # I need to be able to change backgroundcolor programatically
        IN_Labels[14].xbackground_color(1,0,0,1)

class MainApp(App):
    def build(self):
        return kvMain

kvMain = Builder.load_file("kvMain.kv")

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

【讨论】:

以上是关于Kivy 矩形重绘,self.pos 和 self.size 为 (0,0)的主要内容,如果未能解决你的问题,请参考以下文章

Kivy - 在文本周围绘制矩形

Python,pyqt5

python数据结构与算法

更改背景画布 kivy

Kivy 矩形源没有更新?

如何及时重绘画布?