Why do I need to create a new instance of a Line instead of simply update or add and remove it in Kivy

强颜欢笑 提交于 2020-01-16 06:51:07

问题


I am attempting to draw a line with the mouse by dragging from one point to another point of the window. I also want to represent the line while I am dragging. Like drawing a line in an old MS PaintBrush.

My problem is that I have only been able to achieve this by constantly removing the old Line and adding a new Vertex Instruction to the canvas. However, I cannot update existing instructions. Not even adding and removing the same instruction. It has to be a new instance of Line. You can see the result that I want by running the following code. If you try to run it with the commented lines it doesn't work any more.

from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.graphics import Line

class MyCanvas(RelativeLayout):
    def on_touch_down(self, touch):
        with self.canvas:
            self.line = Line(points=[touch.x,touch.y,touch.x+1,touch.y+1])
        self.bind(on_touch_move=self.update_line, on_touch_up=self.end_line)
        return True

    def update_line(self, instance, touch):
        self.line.points[2] = touch.x
        self.line.points[3] = touch.y
        self.canvas.remove(self.line)
#        self.canvas.add(self.line) # - this doesn't work
#        self.canvas.ask_update()   # - not even using this
        with self.canvas:
            self.line = Line(points=self.line.points) # this works

    def end_line(self, instance, touch):
        self.unbind(on_touch_move=self.update_line)
        self.unbind(on_touch_up=self.end_line)
        self.line.points[2] = touch.x
        self.line.points[3] = touch.y
        self.canvas.remove(self.line)
#        self.canvas.add(self.line) # - this doesn't work
#        self.canvas.ask_update()   #- not even using this
        self.canvas.add(Line(points=self.line.points))  # this way works

class ExampleApp(App):
    def build(self):
        return MyCanvas()

ExampleApp().run()

I also tried using Kivy properties as suggested in this other question with the Color instruction. It didn't work and there is another question related to it.


回答1:


I am struggling with the same problem. I started from the 6_button.py example from the kivy/guide/firstwidget directory

I found something that works (using pop twice to remove the last x,y pair from points) But I think it is very awkward, see my code below. I hope someone can tel us how to 'update' properly.

based on 6_button.py

from random import random
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.graphics import Color, Ellipse, Line


class MyPaintWidget(Widget):

    def on_touch_down(self, touch):
        color = (random(), 1, 1)
        with self.canvas:
            Color(*color, mode='hsv')
            d = 10.
            Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
            touch.ud['line'] = Line(points=(touch.x, touch.y, touch.x+30, touch.y))
            #print(dir(touch.ud['line']))

    def on_touch_move(self, touch):
        #touch.ud['line'].points += [touch.x, touch.y]
        touch.ud['line'].points.pop()                     #
        touch.ud['line'].points.pop()                     # works but is awkward
        touch.ud['line'].points += [touch.x, touch.y]     #

        #touch.ud['line'].points[2:4] = [touch.x, touch.y] 
        #self.canvas.ask_update()              # no error but didnt work
        #touch.ud['line'].ask_update()         # didnt work
        #print(touch.ud['line'].points)
        #touch.ud['line'].needs_redraw()       # error 'bool not callable'
        #touch.ud['line'].needs_redraw = True  # error 'not writable'
        #touch.ud['line'].needs_redraw         #no error but doesnt work


class MyPaintApp(App):

    def build(self):
        parent = Widget()
        painter = MyPaintWidget()
        clearbtn = Button(text='Clear')
        parent.add_widget(painter)
        parent.add_widget(clearbtn)

        def clear_canvas(obj):
            painter.canvas.clear()
        clearbtn.bind(on_release=clear_canvas)

        return parent


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


来源:https://stackoverflow.com/questions/17130388/why-do-i-need-to-create-a-new-instance-of-a-line-instead-of-simply-update-or-add

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!