简体   繁体   中英

How to update the on_touch_move and on_touch_down methods of a Widget in kivy

I am currently working on creating a paint app and I am using a Widget canvas for that purpose. Basically I have defined methods to create straight lines and curve_line. But the problem is I can't switch between these two methods. meaning I have two buttons to trigger these methods and each method bind the widget with on_touch_down and on_touch_move methods. My problem is first time as soon as the app starts running and for example I clicked button with name f hand it works fine and after that once i clicked the next button the widget bind itself with both methods creating a mess.... now i want that the widget should bind itself with only one method at a time .. how can i achieve this..

my python code is here

import kivy
from kivy.uix.widget import Widget
from kivy.uix.widget import Canvas
from kivy.graphics import Color
from kivy.graphics import Line
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from kivy.uix.button import Button

class Main(FloatLayout):


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

        self.my_widget = Widget(size_hint= (0.6,0.6),pos_hint = {'x':0.5,'top' : 0.8})
        self.add_widget(self.my_widget)

        self.free_hand = Button(text='f_hand',pos_hint = {'x':0.04,'top':0.2},size_hint = (0.12,0.12))
        self.add_widget(self.free_hand)
        self.free_hand.bind(on_press = self._free_hand)

        self._hand = Button(text='s_hand', pos_hint={'x': 0.04, 'top': 0.6}, size_hint=(0.12, 0.12))
        self.add_widget(self._hand)
        self._hand.bind(on_press=self._straight_lines)


    def _free_hand(self,instance):


        def on_touch_downah(self,touch):
            self.line = Line(points = (touch.x,touch.y),width = 5)
            self.canvas.add(self.line)
            '''self.line_list.append(self.line)
            print(self.line_list)'''
        
        def on_touch_moveah(self,touch):
            self.line.points += touch.x,touch.y

        self.my_widget.bind(on_touch_down=on_touch_downah)
        self.my_widget.bind(on_touch_move=on_touch_moveah)

    def _straight_lines(self,instance):

        def on_touch_downeh(self, touch):
            self.x_ = touch.x
            self.y_ = touch.y
            self.lines = Line(points=(touch.x,touch.y),width = 5)
            self.canvas.add(self.lines)

        def on_touch_moveeh(self, touch):
            self.x2 = self.x_ + 0.1
            self.y2 = self.y_ + 0.1
            self.lines.points = (self.x_,self.y_,self.x2,self.y2,touch.x,touch.y)

        self.my_widget.bind(on_touch_down=on_touch_downeh)
        self.my_widget.bind(on_touch_move=on_touch_moveeh)


'''
    def undo_1(self):
        self.i -= 1
        k = self.line_list[self.i]
        self.canvas.remove(k)
'''

class Myapp(App):
    def build(self):
        return Main()

Myapp().run()

Any help is greatly appreciated .

Expanding on the suggestion from @inclement, here is a modified version of your code where just two methods are bound to on_touch_down and on_touch_move . The methods triggered by the Buttons just set the mode for the drawing, and the bound methods choose what to do based on the current mode:

from kivy.uix.widget import Widget
from kivy.graphics import Line
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from kivy.uix.button import Button

class Main(FloatLayout):


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

        self.my_widget = Widget(size_hint= (0.6,0.6),pos_hint = {'x':0.5,'top' : 0.8})
        self.add_widget(self.my_widget)

        self.free_hand = Button(text='f_hand',pos_hint = {'x':0.04,'top':0.2},size_hint = (0.12,0.12))
        self.add_widget(self.free_hand)
        self.free_hand.bind(on_press = self._free_hand)

        self._hand = Button(text='s_hand', pos_hint={'x': 0.04, 'top': 0.6}, size_hint=(0.12, 0.12))
        self.add_widget(self._hand)
        self._hand.bind(on_press=self._straight_lines)

        self.mode = None  # could be "free_hand" or "straight_lines"
        self.my_widget.bind(on_touch_down=self.on_touch_downh)
        self.my_widget.bind(on_touch_move=self.on_touch_moveh)


    def _free_hand(self,instance):
        self.mode = "free_hand"

    def _straight_lines(self,instance):
        self.mode = "straight_lines"

    def on_touch_downh(self, widget, touch):
        if self.mode == "free_hand":
            self.free_hand_touch(touch)
        elif self.mode == "straight_lines":
            self.straight_lines_touch(touch)

    def on_touch_moveh(self, widget, touch):
        if self.mode == "free_hand":
            self.free_hand_move(touch)
        elif self.mode == "straight_lines":
            self.straight_lines_move(touch)

    def free_hand_touch(self,touch):
        self.line = Line(points = (touch.x,touch.y),width = 5)
        self.canvas.add(self.line)
        '''self.line_list.append(self.line)
        print(self.line_list)'''

    def free_hand_move(self,touch):
        self.line.points += touch.x,touch.y

    def straight_lines_touch(self, touch):
        self.x_ = touch.x
        self.y_ = touch.y
        self.lines = Line(points=(touch.x,touch.y),width = 5)
        self.canvas.add(self.lines)

    def straight_lines_move(self, touch):
        self.x2 = self.x_ + 0.1
        self.y2 = self.y_ + 0.1
        self.lines.points = (self.x_,self.y_,self.x2,self.y2,touch.x,touch.y)

'''
    def undo_1(self):
        self.i -= 1
        k = self.line_list[self.i]
        self.canvas.remove(k)
'''

class Myapp(App):
    def build(self):
        return Main()

Myapp().run()

Note that in your original code, you were binding more methods every time one of the Buttons was pressed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM