【问题标题】:Kivy Canvas redrawing after touch event触摸事件后重绘 Kivy 画布
【发布时间】:2016-07-09 01:29:07
【问题描述】:



我想做一个小游戏,但我需要一些帮助...
我是 python 和 kivy 的新手。我正在使用 python 3.4 和 kivy 1.8.0。

游戏将包含一些可拖动和/或消失的绘制元素:
- 如果你点击一个点,你可以拖动它
- 如果你点击任何地方,一个点就会消失

我试图让它消失的部分,但我卡住了。 我在画布上制作了一个带有一些点的虚拟代码,您可以在其中看到我想如何解决问题:
--> 画一些点
--> 删除/重新定位点之一
--> 清除画布
--> 重绘

不知怎的,我无法重绘它。但我设法清理了画布......
你能帮我吗?
另外我想获得帮助/想法如何使它可拖动......

谢谢,这是我的代码:

from kivy.app import App
from kivy.graphics import Ellipse
from kivy.uix.boxlayout import BoxLayout
import random

class CustomLayout(BoxLayout):

    def __init__(self, **kwargs):
        super(CustomLayout, self).__init__(**kwargs)
        self.a = []
        self.points_pos()
        with self.canvas.after:
            self.draw_points()

    def points_pos(self):
        i=0
        x = random.sample(range(800), 10)
        y = random.sample(range(640), 10)
        for i in range(10):
            pos = [0,0]
            pos[0]=x[i]
            pos[1]=y[i]
            self.a.append(pos)
        print(self.a)

    def draw_points(self):
        i = 0
        for i in range(len(self.a)):
            self.circle = Ellipse(
                size = (25,25),
                pos =  (self.a[i][0],self.a[i][1])
                )

    def random_remove(self):
        point = self.a[random.randint(0,len(self.a)-1)]
        self.a.remove(point)


    def update(self):
        self.parent.canvas.clear()
        with self.canvas:
            self.draw_points()

    def on_touch_down(self, touch):
        self.random_remove()
        self.update()

class MainApp(App):

    def build(self):
        root = CustomLayout()
        return root

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

【问题讨论】:

  • 在您的 random_remove 方法之外,我没有看到任何对 edge 的引用。
  • 你说得对,我重新编辑了代码。现在它会随机抽取一些点。

标签: python kivy


【解决方案1】:
def update(self):
    self.parent.canvas.clear()
    with self.canvas:
        self.draw_points()

您清除了 父母的 画布,其中包括 BoxLayout 的画布。之后,无论您在 BoxLayout 上绘制了多少东西,它们都不会显示出来。

要解决此问题,您可能只想简单地执行self.canvas.clear(),但实际上这非常低效并且不是使用 kivy 画布的好方法(尽管它适用于少量指令)。使用self.canvas.remove(...) 保留对所有画布说明的引用并仅删除您不再需要的特定说明会更好。

【讨论】:

  • 我已经尝试使用“slf.canvas.clear()”代替。到现在为止,如果我单击,画布会变黑,但现在我在单击后看到相同的 10 个点。
  • 在您的帮助下,我设法解决了我的问题。但是,使用您给出的解决方案,问题并没有解决。我想给你的答案+1,但我没有这方面的声誉。
【解决方案2】:

由于这个问题得到了更多的意见,我除外,我在这里留下一个工作示例:

from kivy.app import App
from kivy.logger import Logger
from kivy.graphics import Color, Ellipse, Line
from kivy.uix.boxlayout import BoxLayout


class CustomLayout(BoxLayout):

    def __init__(self, **kwargs):
        super(CustomLayout, self).__init__(**kwargs)

        self.canvas_edge = {}
        self.canvas_nodes = {}
        self.nodesize = [25, 25]

        self.grabbed = {}

        #declare a canvas
        with self.canvas.after:
            pass

        self.define_nodes()
        self.canvas.add(self.canvas_nodes[0])
        self.canvas.add(self.canvas_nodes[1])
        self.define_edge()
        self.canvas.add(self.canvas_edge)



    def define_nodes(self):
        """define all the node canvas elements as a list"""

        self.canvas_nodes[0] = Ellipse(
            size = self.nodesize,
            pos =  [100,100]
            )

        self.canvas_nodes[1] = Ellipse(
            size = self.nodesize,
            pos =  [200,200]
            )

    def define_edge(self):
        """define all the edge canvas elements as a list"""


        self.canvas_edge = Line(
            points =  [
                self.canvas_nodes[0].pos[0] + self.nodesize[0] / 2,
                self.canvas_nodes[0].pos[1] + self.nodesize[1] / 2,
                self.canvas_nodes[1].pos[0] + self.nodesize[0] / 2,
                self.canvas_nodes[1].pos[1] + self.nodesize[1] / 2
                ],
            joint = 'round',
            cap = 'round',
            width = 3
            )


    def on_touch_down(self, touch):

        for key, value in self.canvas_nodes.items():
            if (value.pos[0] - self.nodesize[0]) <= touch.pos[0] <= (value.pos[0] + self.nodesize[0]):
                if (value.pos[1] - self.nodesize[1]) <= touch.pos[1] <= (value.pos[1] + self.nodesize[1]):
                    touch.grab(self)
                    self.grabbed = self.canvas_nodes[key]
                    return True

    def on_touch_move(self, touch):

        if touch.grab_current is self:
            self.grabbed.pos = [touch.pos[0] - self.nodesize[0] / 2, touch.pos[1] - self.nodesize[1] / 2]
            self.canvas.clear()
            self.canvas.add(self.canvas_nodes[0])
            self.canvas.add(self.canvas_nodes[1])
            self.define_edge()
            self.canvas.add(self.canvas_edge)
        else:
            # it's a normal touch
            pass

    def on_touch_up(self, touch):
        if touch.grab_current is self:
            # I receive my grabbed touch, I must ungrab it!
            touch.ungrab(self)
        else:
            # it's a normal touch
            pass

class MainApp(App):

    def build(self):
        root = CustomLayout()
        return root

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-03
    • 2023-03-28
    • 1970-01-01
    相关资源
    最近更新 更多