Kivy Python 右键单击

5
我正在使用Kivy和Button小部件制作扫雷游戏。我希望能够根据鼠标点击是左键还是右键来执行不同的操作。有人可以帮助我吗?
下面是我的Cell类和导入的模块。
请注意,当按下按钮时,将调用Cell.onPressed()函数。
import kivy
from kivy.config import Config

Config.set('input', 'mouse', 'mouse,disable_multitouch')

from random import randint
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.anchorlayout import AnchorLayout

width = 10
height = 10
bombs = 5
size = 60

class Cell():  

  def __init__(self):
    self.isBomb = False
    self.isVisible = False
    self.neighbors = None
    self.location = []
    self.button = Button(size = (size, size), size_hint = (None, None))
    self.button.bind(on_press = self.onPressed)

  def build(self, x, y):
    self.location = [x, y]
    self.count_neighbors()

  def onPressed(self, instance):
    #if left_click == True:    
    self.isVisible = True
    self.button.text = str(self.neighbors)
    if self.neighbors == 0:
      for i in range(-1, 2):
        for j in range(-1, 2):
          if (0 <= self.location[0] + i < width) and (0 <= self.location[1] + j < height):
            if grid[self.location[0] + i][self.location[1] + j].isVisible == False:
              grid[self.location[0] + i][self.location[1] + j].onPressed(instance)    
    #if right_click == True:
      #Toggle state


  def count_neighbors(self):
    if self.isBomb == False:
      count = 0
      for i in range(-1, 2):
        for j in range(-1, 2):
          if (0 <= self.location[0] + i < width) and (0 <= self.location[1] + j < height):
            if grid[self.location[0] + i][self.location[1] + j].isBomb == True:
              count += 1
      self.neighbors = count

class TestApp(App):

  def build(self):
    root = AnchorLayout(anchor_x = 'center', anchor_y = 'center')
    grid_root = RelativeLayout(size = (width * size, height * size), size_hint = (None, None))
    layout = []
    for i in range(height):
      layout.append(BoxLayout(orientation='horizontal', size_hint = (.8, .8), pos = (0, (height - 1) * size - i * size)))
      for j in range(width):    
        layout[i].add_widget(grid[j][i].button)    
      grid_root.add_widget(layout[i])
    root.add_widget(grid_root)
    return root


def init_grid():
  global grid
  grid = [[Cell() for x in range(width)] for y in range(height)]
  for _ in range(bombs):
    while True:
      x = randint(0, height - 1)
      y = randint(0, width - 1)
      if grid[x][y].isBomb == False:
        grid[x][y].isBomb = True
        break  
  for i in range(width):
    for j in range(height):
      grid[j][i].build(j, i)


if __name__ == '__main__':
  init_grid()
  TestApp().run()
3个回答

8

您应该绑定on_touch_down而不是on_press,以便您可以使用touch参数:

...
self.button.bind(on_touch_down = self.onPressed)
...

def onPressed(self, instance, touch):
    if touch.button == 'right':
        print("right mouse clicked")
    ...

我进行了编辑以包含整个程序。你的答案对我没有用,我要么得到一个“参数太多”错误,要么是“touch未定义”。你需要导入哪个模块,以及如何最好地实现它? - Damon Palovaara
抱歉,我犯了一个编辑错误,在绑定中应该使用on_touch_down而不是on_press,很快更新。请再尝试第二个示例。 - hurturk
@DamonPalovaara,你需要做的就是更新绑定行并将onPressed函数替换为上面的函数。我会清除第一段代码以避免混淆。确实,当你像那样绑定时它们会发生碰撞。 - hurturk
我无法让它工作,最终我创建了一个从Widget继承的类class TouchInput(Widget): def on_touch_down(self, touch): global mouse mouse = touch.button然后我创建了一个实例并将其添加到我的根widget中。所以现在每次点击按钮时,它只检查鼠标的状态。 def onPressed(self, instance): if mouse == 'left': print('左键!') if mouse == 'right': print('右键!') - Damon Palovaara
就我测试过的情况来看,它是可以工作的,但我希望有一个更好的解决方案。我对Kivy还很陌生,只是开始使用它为我的扫雷游戏制作GUI界面。 - Damon Palovaara
显示剩余2条评论

1
我已经做出了一些工作,但是它有点“hackish”。 我创建了一个从Widget继承的新类,只是简单地更改了一个名为“mouse”的全局变量。
class TouchInput(Widget):

  def on_touch_down(self, touch):
    global mouse
    mouse = touch.button

我创建了一个TouchInput()的实例,并将其添加到我的根布局中。
class TestApp(App):

  def build(self):
    root = AnchorLayout(anchor_x = 'center', anchor_y = 'center')
    root_input = TouchInput()
    grid_root = RelativeLayout(size = (width * size, height * size), size_hint = (None, None))
    layout = []
    for i in range(height):
      layout.append(BoxLayout(orientation='horizontal', size_hint = (.8, .8), pos = (0, (height - 1) * size - i * size)))
      for j in range(width):    
        layout[i].add_widget(grid[j][i].button)    
      grid_root.add_widget(layout[i])
    root.add_widget(grid_root)
    root.add_widget(root_input)
    return(root)

现在,每当按下按钮时,它都可以检查是左键还是右键。
def onPressed(self, instance):
  if mouse == 'left':
    print('Left!')
  if mouse == 'right':
    print('Right!')

1
在我看来,这比已接受的解决方案更好。当我使用已接受的解决方案时,由于某种原因似乎会调用其上面所有小部件的函数。 - qr7NmUTjF6vbA4n8V3J9
2
除非 on_touch_down 方法返回 True(表示触摸已被处理),否则触摸事件将传播到其他小部件。通常只需在底部添加 return True 即可解决此问题。 - jjc385

0
我通过创建一个新的类来判断哪个按钮被按下了。
from kivy.uix.button import Button 
class ClickableButton(Button):
    def __init__(self,**kwargs):
        super(Button, self).__init__(**kwargs)
        self.mouse_button = None #mouse_button records what button is pressed
        self.bind(on_touch_down = self.callback_touch_down) #set up a function to be called on mouse events
    def callback_touch_down(self, instance, touch):
        self.mouse_button = touch.button #record what button is clicked on touch down on mouse events

ClickableButton类继承自Button,因此它可以像普通的Kivy按钮一样使用,如下所示:
from kivy.app import App
def callback(instance):
    print('The <%s> button is being pressed' % instance.mouse_button)

class MyApp(App):  
    def build(self):  
        return ClickableButton(text = "ClickableButton",on_press = callback)

if __name__ == '__main__':
    root = MyApp().run()

现在程序知道了哪个特定的kivy按钮被按下以及点击了哪个鼠标按钮。此外,Button.on_touch_down()函数不会冒泡到多个实例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接