【问题标题】:Python Kivy Canvas wont UpdatePython Kivy Canvas 不会更新
【发布时间】:2014-12-30 21:27:30
【问题描述】:

我正在使用 64x64 瓷砖创建一个“地图编辑器”。当我单击并更改位置的磁贴时,我需要我的画布更新。我最初将画布设置为

with self.canvas:
    Rectangle(source = 'image.png')

在一个班级,然后在我的 touch_down 班级我打电话

with self.canvas:
    Rectangle(source = 'newImage.png')

在我更改图像以更新它之后。

我已经能够让它更新,但我每次都必须创建一个新图像,它似乎不会更新,因为我已经用那个特定的源图像添加了那个矩形,并且没有看到图像已经变了吗?

回应 Ryan P

还是什么都没有。我试过这个

Class mypaintwidget(Widget): #This is added as a widget to my layout
    def on_touch_down(self, touch):
        with self.canvas:
            self.rect = Rectangle(source = 'image.png')
        tilepng = pil.open('64x64tile.png') #pil is Python Image Library
        tilemap = pil.open('image.png')       
        tilemap.paste(tilepng,location)
        tilemap.save('newimage.png')
        self.rect.source = 'newimage.png'

它只会更新一次。然后什么都没有(但仍会保存该图像,但不会显示给我。

【问题讨论】:

    标签: python canvas kivy


    【解决方案1】:

    你需要修改Rectangle指令(或者删除替换,但修改更容易):

    with self.canvas:
        self.rect = Rectangle(source='image.png')
    

    然后:

    self.rect.source = 'newImage.png'
    

    至于问题的第二部分,问题是图像在 Kivy 中加载时被缓存。因此,当您保存 newimage.png 并再次重新加载时,Kivy 知道您已经加载了 newimage.png。对于 Kivy 应用来说,这并不是一个好的设计。

    此外,在on_touch_down 中创建Rectangle 意味着每次按下小部件时都会创建一个新的Rectangle,因此您只需添加越来越多不必要的绘图指令。

    您可能还注意到,当您将多个这些小部件添加到布局时,它们都以窗口的完整大小呈现在同一个位置。小部件不限于在其区域内绘制,并且可以在应用程序内的任何位置绘制。您需要通过传递sizepos 参数来确保Rectangle 指令知道在哪里绘制。

    最后,您可以只显示一张图片,而不是保存图片。这将更有效率,并且不需要使用唯一的文件名或弄乱缓存系统。

    您绝对应该看看Kivy language (kv),因为它更容易用于设计小部件和布局您的应用程序。

    这是使用 kv 执行此操作的示例:

    <TileWidget>:
        tilesource: ''
    
        canvas:
            Color:
                rgba: 1, 1, 1, 1
            Rectangle:
                size: self.size
                pos: self.pos
                source: 'image.png'
            Color:
                a: 1 if self.tilesource else 0
            Rectangle:
                size: self.size
                pos: self.pos
                source: self.tilesource
    

    现在我将解释这一切的作用。

    <TileWidget>:
    

    这是一个类规则,因为名称被&lt;&gt; 包围。它将适用于TileWidget 的所有实例。

        tilesource: ''
    

    我们是setting the value of the propertytilesource。但是tilesource 不是Widget 类的属性!不用担心。在 kv 中,当您像这样为不存在的属性赋值时,该属性将自动创建。由于我们分配给属性的值是一个字符串,Kivy 会意识到我们希望这是一个StringProperty

    通过创建这个属性,我们可以从外部影响这个小部件。稍后我们将使用此属性的值来显示图像。

        canvas:
    

    就像在 Python 中使用 with self.canvas: 一样。

            Color:
                rgba: 1, 1, 1, 1
    

    canvas 块内,我们可以添加绘图指令。我们从Color instruction 开始,因为您不知道当前设置的颜色。这种颜色会为我们显示的图像着色,我们不想要任何颜色,所以我们使用全白色。

            Rectangle:
                size: self.size
                pos: self.pos
                source: 'image.png'
    

    现在我们要渲染第一张图片。我们确保Rectangle 的大小和位置与小部件匹配。在 kv 中,这样做会自动创建一个绑定。如果小部件四处移动,它的大小将会改变,Rectangle 将自行更新以匹配。

            Color:
                a: 1 if self.tilesource else 0
    

    这一次,我们知道颜色设置为什么。但是,在设置图像之前,我们不想绘制任何其他内容。在 kv 中,属性将接受任何 Python 值。这意味着您可以像这样使用ternary expressions,也可以使用函数调用或算术等。因此,如果self.tilesource 的计算结果为False(如空字符串,我们在上面设置的默认值),那么a 的属性颜色(alpha 分量)将设置为 0,否则为 1。

            Rectangle:
                size: self.size
                pos: self.pos
                source: self.tilesource
    

    最后,我们渲染选中的图像。

    现在,要创建小部件本身,我们只需要一点 Python:

    class TileWidget(Widget):
        def on_touch_down(self, touch):
            if self.collide_point(*touch.pos):
                self.tilesource = '64x64tile.png'
                return True
            return super(TileWidget, self).on_touch_down(touch)
    

    在处理触摸时使用collide_point 很重要。就像小部件可以在应用程序的任何位置绘制一样,它们也可以在应用程序的任何位置处理触摸。这可以确保在操作之前触摸实际上是在我们的小部件的范围内。 collide_point 块中,我们将返回 True 以让 Kivy 知道我们已经处理了这个触摸并且没有其他东西应该处理它。否则,我们调用super() 让默认处理程序接管。

    【讨论】:

    • 我似乎无法在与 with self.canvas 不同的类中使用 self.rect.source = 'newImage.png':self.rect = Rectangle( source = 'image.png') 我得到一个错误 AttributeError: 'class' object has no attribute 'rect'
    • 在这种情况下,部分问题是您试图将第二个 Rectangle 添加到不同的画布。您需要参考原始小部件来更改其上的 Rectangle。
    • 我无法在这些 cmets 中很好地显示代码,我将把它添加到我的问题中
    • 感谢您抽出宝贵时间详细回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 2014-08-09
    • 2021-04-15
    相关资源
    最近更新 更多