简体   繁体   English

Kivy:如何将同时触摸限制为一个?

[英]Kivy: How To Limit Simultaneous Touches to One?

I am using Kivy 1.9.1 and Python 3.5.2.我正在使用 Kivy 1.9.1 和 Python 3.5.2。 My application breaks when more than one touch event is fired before the first has finished processing.当在第一个完成处理之前触发多个触摸事件时,我的应用程序中断。 I'm looking for some way to either restrict the number of touch events at a given time to one (something like the max_pointers attribute in the HTML5 engine Phaser) or to filter the touch events and only process the first.我正在寻找某种方法来将给定时间的触摸事件数量限制为一个(类似于 HTML5 引擎 Phaser 中的 max_pointers 属性)或过滤触摸事件并仅处理第一个事件。 As far as I'm aware, the touch event doesn't hold this information about itself.据我所知,触摸事件不包含有关自身的信息。

I don't believe the specifics of my code are relevant, but better safe than sorry:我不相信我的代码的细节是相关的,但安全总比后悔好:

    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()

I was able to implement this by creating a TouchHandler widget: 我能够通过创建一个TouchHandler小部件来实现这一点:

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

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

Then overriding Window 's on_motion method prior to calling MyApp().run() : 然后在调用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()

For this to work, you need to manage your touch events very carefully and reset TouchHandler.instance.active to None when you're done with the touch in the on_touch_up method for any widget that will use the touch: 对于这个工作,你需要非常仔细地管理你的触摸事件和复位TouchHandler.instance.activeNone当你与在触摸完成on_touch_up为将使用触摸任何控件的方法:

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

This is an answer, but I'm kind of afraid of it, I'm pretty sure it's bad programming practice but:这是一个答案,但我有点害怕,我很确定这是不好的编程习惯但是:

I created a global variable with touch_counter = 0 , then in on_touch_down I referenced the global variable and then += 1 it, and in on_touch_up I -= 1 it.我用touch_counter = 0创建了一个全局变量,然后在on_touch_down中引用了全局变量然后+= 1它,在on_touch_up中我-= 1它。 In on_touch_move I check if the touch_counter == 1 and then performed what I wanted it to do with only one touch.on_touch_move ,我检查是否touch_counter == 1然后执行我想要它做的事情,只需轻轻一按。

This works with multitouch_sim, I realize this might mess up with actually multitouch devices, but so far so good.这适用于 multitouch_sim,我意识到这可能会混淆实际的多点触控设备,但到目前为止还不错。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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