【问题标题】:How to detect both left and right mouse click at the same time in Pygame如何在 Pygame 中同时检测鼠标左键和右键
【发布时间】:2023-03-20 06:33:01
【问题描述】:

我使用 python-2.7 和 pygame 来构建一个扫雷器。它几乎完成了,只剩下一个重要的功能需要实现。当同时按下鼠标左键和右键时,它会扫描周围的块并做一些事情。但我不知道如何同时检测两次点击。 在 pygame 的网站上,有

注意,在 X11 上,一些 XServer 使用中间按钮模拟。当您同时单击按钮 1 和 3 时,会发出 2 按钮事件。

但这对我来说不起作用。

【问题讨论】:

  • 您在左键仍然按下时检测到右键单击,反之亦然。您必须在每次向下/向上时保存按钮的状态才能做到这一点。
  • 是左右同时单击吗?还是你压制他们?

标签: python python-2.7 pygame


【解决方案1】:

您可以为文档中概述的场景编写代码(在按钮 1 和 3 按下时触发按钮 2 中键鼠标)。

mouse_pressed = pygame.mouse.get_pressed()
if (mouse_pressed[0] and mouse_pressed[2]) or mouse_pressed[1]:
    print("left and right clicked")

请记住,使用 pygame.mouse.get_pressed() 通常会非常快地触发,这意味着您在 if 语句中的任何代码都会在您释放鼠标键之前发生几次。这是因为 get_pressed() 始终返回所有鼠标按钮的状态。如果您想跟踪被按住的按钮,这种方法很好。

我会将解决方案编码到 pygame.event.get() 中。这只会在事件发生时触发,因此只会触发一次:

left_mouse_down = False
right_mouse_down = False
while True:
    for event in pygame.event.get():
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                left_mouse_down = True
                if right_mouse_down:
                    print("perform action")
                else:
                    print("action for single left click")
            if event.button == 3:
                right_mouse_down = True
                if left_mouse_down:
                    print("perform action")
                else:
                    print("action for single right click")
        elif event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                left_mouse_down = False
            if event.button == 3:
                 right_mouse_down = False

更新 - 模拟第三次鼠标点击双键鼠标

上述代码有效,但如果您接受单个右或左动作也会触发这一事实,但在组合(左/右)动作之前。如果这适用于您的游戏设计,那就试试吧。如果这是不可接受的,那么以下方法将起作用(虽然更深入一点):

left_mouse_down = False
right_mouse_down = False
left_click_frame = 0  # keeps track of how long the left button has been down
right_click_frame = 0  # keeps track of how long the right button has been down
left_right_action_once = True  # perform the combo action only once
left_action_once = True  # perform the left action only once
right_action_once = True  # perform the right action only once
max_frame = 2  # The frames to wait to see if the other mouse button is pressed (can be tinkered with)
performing_left_right_action = False  # prevents the off chance one of the single button actions running on top of the combo action
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    mouse_pressed = pygame.mouse.get_pressed()
    if mouse_pressed[0]:  # left click
        left_click_frame += 1
        left_mouse_down = True
    else:
        left_action_once = True
        left_mouse_down = False
        left_click_frame = 0

    if mouse_pressed[2]:  # right click
        right_click_frame += 1
        right_mouse_down = True
    else:
        right_action_once = True
        right_mouse_down = False
        right_click_frame = 0

    if not mouse_pressed[0] and not mouse_pressed[2]:
        left_right_action_once = True
        performing_left_right_action = False

    if left_mouse_down and right_mouse_down and abs(left_click_frame - right_click_frame) <= max_frame:
        if left_right_action_once:
            print("performing right/left action")
            left_right_action_once = False
            performing_left_right_action = True
    elif left_mouse_down and left_click_frame > max_frame and not performing_left_right_action and not right_mouse_down:
        if left_action_once:
            print("perform single left click action")
            left_action_once = False
    elif right_mouse_down and right_click_frame > max_frame and not performing_left_right_action and not left_mouse_down:
        if right_action_once:
            print("perform single right click action")
            right_action_once = False

这个问题的难点在于一次只能发生一个事件,所以你必须有一种方法知道左键被按下,直到你确定右键也不会被按下时才评估它。您可以通过跟踪帧来完成此操作,如果左右发生在一定数量的帧(max_frames)内,那么您可以单击右键/左键。否则你有左有右。

action_once 变量很重要,因为 pygame.mouse.get_pressed() 每次通过游戏循环时都会检查每个鼠标按钮的状态,因此您需要一个标志来防止您的操作在按住按钮时多次运行(即使在短暂的点击期间)。游戏循环比鼠标点击更快。

因此涵盖了所有三种情况:左单、右单、左右组合。换句话说,它模拟了在两键鼠标上的“第三次”鼠标点击......虽然解决方案相当笨拙

【讨论】:

  • 非常感谢。我想检测左右的单击而不是按住。看来您的代码可以完美地检测到这种情况。但我也希望在只有左键或右键的情况下执行其他操作。我觉得除了点击场景之外,这些都不能说清楚吗?
  • 你指的是击键之类的东西吗?还是只需单击左键?
  • @orangedietc 我编辑了我的代码以考虑单次左击和单次右击操作。要读取击键,您只需执行以下操作:elif event.type == pygame.KEYDOWN
  • 我指的是鼠标点击。我认为这行不通。如果我同时点击左右,'for event in pygame.event.get():' 一次只接受一个事件(比如先左键点击),需要进入下一个循环检测到右键单击并执行两次单击操作,但它真正要做的是触发一次左键单击操作,对吧?
  • 是的,我明白你现在在说什么了。该代码不知道您按下另一个鼠标按钮的意图,因此默认为单击
【解决方案2】:

如果您只希望代码在按下两个按钮后执行一次,只需在运行代码后将 right_mouse_downleft_mouse_down 设置为 False

left_mouse_down = False
right_mouse_down = False
while True:
    for event in pygame.event.get():
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                left_mouse_down = True
                if right_mouse_down:
                    print("perform action")
                    right_mouse_down = False
                    left_mouse_down = True
            if event.button == 3:
                right_mouse_down = False
                if left_mouse_down:
                    print("perform action")
                    right_mouse_down = False
                    left_mouse_down = False
        elif event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                left_mouse_down = False
            if event.button == 3:
                 right_mouse_down = False

现在,在您移除并重新单击两个鼠标按钮之前,此代码将永远不会再次运行。我建议在任何时候使用pygame.mouse.get_pressed() 来检查按钮的状态,这样如果您只希望代码在第一次发生时您可以设置一个标志。

done_the_thing = False
while not done: # Main game loop
    buttons = pygame.mouse.get_pressed()

    if buttons[0] and buttons[2] and not done_the_thing:
        do_the_thing() # This is just your function
        done_the_thing = True

    if not buttons[0] and not buttons[2]:
        done_the_thing = False

这将提供更大的灵活性,因此如果您想添加更多每帧都会发生的鼠标事件或更改您当前正在执行的操作,您可以将所有这些事件放在一起并保持干净。

【讨论】:

    【解决方案3】:

    您应该同时测试pygame.mouse.get_pressed()[0](鼠标左键)和pygame.mouse.get_pressed()[2](鼠标右键)的值。

    http://www.pygame.org/docs/ref/mouse.html#pygame.mouse.get_pressed

    此测试应与pygame.event.get() for 循环处于同一级别,并且不包含在此循环中。您可以测试此脚本以了解我的意思:

    import pygame
    from pygame.locals import *
    pygame.init()
    screen = pygame.display.set_mode((800, 500), RESIZABLE)
    running = True
    while(running):
        mousebuttons = pygame.mouse.get_pressed()
        if mousebuttons[0] == 1 and mousebuttons[2] == 1:
            print("Both left and rigth mouse buttons are pressed.")
        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
    

    【讨论】:

    • 我使用 'pygame.event.get()' 一次接受一个事件,因为如果没有,我不能让它工作,一个右键单击放置一个标志,另一个取消标志。我假设在这种情况下,'pygame.mouse.get_pressed()' 中总是只有一个布尔值是真的?
    • 您应该将pygame.mouse.get_pressed() 部分放在pygame.event.get() for 循环之外...我目前正在办公室工作,今晚给我一些时间,我会告诉你一些通过编辑我上面的答案来做你想做的简单代码;)
    • 这里有更多细节。该脚本在家中完美运行。如果我让你开心,别忘了验证这个答案。享受吧!
    猜你喜欢
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    相关资源
    最近更新 更多