【问题标题】:Kivy Python Right ClickKivy Python 右键单击
【发布时间】:2017-06-12 05:24:50
【问题描述】:

我正在使用 Kivy 使用按钮小部件制作扫雷游戏。我希望能够根据鼠标单击是鼠标左键单击还是鼠标右键单击来执行不同的操作。有谁能够帮我?

下面是我的 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()

【问题讨论】:

    标签: python kivy minesweeper


    【解决方案1】:

    您应该绑定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")
        ...
    

    【讨论】:

    • 我进行了编辑以包含整个程序。您的回答对我不起作用,我要么收到“参数过多”错误,要么收到“未定义触摸”。你必须导入什么模块,我将如何最好地实现它?
    • 对不起,我编辑出错了,它应该是on_touch_down in bind 而不是on_press,很快就会更新。请再试第二个例子。
    • 我不明白为什么一个按钮不能简单地检测左键还是右键。从我正在阅读的内容来看,我需要使用来自 kivy 的小部件模块,上面写着“Widget.on_touch_down()、Widget.on_touch_move()、Widget.on_touch_up() 不会发生任何类型的冲突。如果你想知道触摸是否在您的小部件内部,请使用 Widget.collide_point()。”我现在基本上必须重新考虑我的整个计划。
    • @DamonPalovaara,您只需更新绑定行并将onPressed 函数替换为上述函数即可。我将清除第一个代码以防止混淆。事实上,当你这样绑定时,它们会发生碰撞。
    • 我无法让它工作,我最终做的是创建一个继承自 Widget 类 TouchInput(Widget): def on_touch_down(self, touch): global mouse mouse = touch.button 然后我创建了它的一个实例并将其添加到我的根小部件中。所以现在每次点击一个按钮只是检查鼠标的状态。 def onPressed(self, instance): if mouse == 'left': print('Left!') if mouse == 'right': print('Right!')
    【解决方案2】:

    我得到了一些工作,但它有点 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!')
    

    【讨论】:

    • 在我看来比公认的解决方案要好。当我使用公认的解决方案时,它似乎出于某种原因调用了它上面的所有小部件的函数。
    • @qr7NmUTjF6vbA4n8V3J9 除非on_touch_down 方法返回True(表示触摸已被处理),否则触摸事件会传播到其他小部件。通常只需在底部添加return True 即可解决此问题。
    【解决方案3】:

    我可以通过创建一个新类来判断按下了什么按钮,如下所示:

    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 Button 一样使用,如下所示:

    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() 函数也不会冒泡到多个实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-08
      • 2019-04-12
      • 2021-04-12
      • 1970-01-01
      • 2012-11-06
      • 2019-11-05
      • 1970-01-01
      • 2011-01-11
      相关资源
      最近更新 更多