python-3.x Kivy:如何将同时触摸限制为一次?

xhv8bpkk  于 2022-12-01  发布在  Python
关注(0)|答案(2)|浏览(135)

我使用的是Kivy 1.9.1和Python 3.5.2。如果在第一个触摸事件完成处理之前触发了多个触摸事件,我的应用程序就会中断。(类似于HTML5引擎Phaser中的max_pointers属性)或者过滤触摸事件并只处理第一个。触摸事件不保存关于其自身的信息。
我不认为我的代码的细节是相关的,但安全总比遗憾好:

def on_touch_down(self, touch):
        x, y = touch.x, touch.y
        x -= self.img_board.pos[0]
        y -= self.img_board.pos[1]
        if not (0 <= x <= self.img_board.size[0] and
                0 <= y <= self.img_board.size[1]):
            touch.ud['piece'] = None
            return

        file = int(x / self.square_size)
        rank = int(y / self.square_size)
        self.select((file, rank))
        piece = Board.instance.at_square(self.selected)
        touch.ud['piece'] = piece
        if piece:
            self.canvas.remove(piece.rect)
            self.canvas.after.add(piece.rect)

    def on_touch_move(self, touch):
        piece = touch.ud['piece']
        if piece:
            if Board.instance.to_move == piece.color:
                piece.rect.pos = (touch.x - piece.rect.size[0]/2,
                                  touch.y - piece.rect.size[1]/2)

    def on_touch_up(self, touch):
        piece = touch.ud['piece']
        if piece:
            self.canvas.after.remove(piece.rect)
            self.canvas.add(piece.rect)
            if Board.instance.to_move != piece.color:
                return

            x, y = touch.x, touch.y
            x -= self.img_board.pos[0]
            y -= self.img_board.pos[1]
            if not (0 <= x <= self.img_board.size[0] and
                    0 <= y <= self.img_board.size[1]):
                self.update_geometry()
                return

            dest = Board.an_from_tup( (int(x / self.square_size),
                                       int(y / self.square_size)) )
            if dest in piece.get_valid_moves():
                Board.instance.move(piece.position,dest)
                self.select(dest)
            self.update_geometry()
mctunoxg

mctunoxg1#

我可以通过创建一个TouchHandler小部件来实现这一点:

class TouchHandler(Widget):
    """ Non-display widget to handle touch order """
    instance = None

    def __init__(self):
        super().__init__()
        TouchHandler.instance = self
        self.active = None

然后在调用MyApp().run()之前覆盖Window的on_motion方法:

if __name__ == '__main__':
    # Ignore new touches before first touch has resolved
    TouchHandler()
    def on_motion(self, etype, me):
        if 'pos' in me.profile:
            if etype == 'begin':
                if not TouchHandler.instance.active:
                    TouchHandler.instance.active = me

    Window.bind(on_motion=on_motion)

    Window.size = (500,500)
    MyApp().run()

要实现这一点,您需要非常小心地管理您的触摸事件,并在对任何将使用触摸的小部件完成on_touch_up方法中的触摸操作后,将TouchHandler.instance.active重置为None

def on_touch_up(self, touch):
    if touch != TouchHandler.instance.active:
        return True # Signals Kivy to kill the event
    piece = touch.ud['piece']
    if piece:
        # ...
        self.update_geometry()
    TouchHandler.instance.active = None
wgx48brx

wgx48brx2#

这是一个答案,但我有点害怕它,我很确定这是一个糟糕的编程实践,但:
我用touch_counter = 0创建了一个全局变量,然后在on_touch_down中引用了这个全局变量,然后在+= 1中引用了它,在on_touch_up中引用了-= 1。在on_touch_move中,我检查了touch_counter == 1是否正确,然后只需要一次触摸就可以执行我希望它执行的操作。
这适用于Multitouch_sim,我意识到这可能会弄乱实际上的多点触摸设备,但到目前为止一切顺利。

相关问题