【问题标题】:kivy python3 detect mousewheelkivy python3检测鼠标滚轮
【发布时间】:2018-09-28 11:34:06
【问题描述】:

您好,我想在 kivy 的图表中创建缩放效果(我在 windows 上的 python 3.6 64bits 中使用 kivy 1.10)

我想在我的图表小部件中检测鼠标滚轮事件,但我找不到如何执行此操作。

我的代码:

import itertools
from math import sin, cos, pi
from random import randrange
from kivy.utils import get_color_from_hex as rgb
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from graph import Graph,MeshLinePlot

from kivy.uix.popup import Popup
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.stacklayout import StackLayout




class Visu(GridLayout):
    def __init__(self, **kwargs):
        super(Visu, self).__init__(**kwargs)
        self.cols = 2
        self.row = 2

        b = BoxLayout(orientation='vertical', on_press=self.zoom)


        graph = Graph(xlabel='X', ylabel='Y', x_ticks_minor=5,
        x_ticks_major=25, y_ticks_major=1,
        y_grid_label=True, x_grid_label=True, padding=5,
        x_grid=True, y_grid=True, xmin=-0, xmax=50, ymin=-1, ymax=1)


        #graph.add_x_axis(0,10)

        plot1 = MeshLinePlot(color=[1, 0, 0, 1])
        plot1.points = [(x, sin(x / 10.)) for x in range(0, 65000)]
        graph.add_plot(plot1)
        plot2 = MeshLinePlot(color=[1, 0, 0, 1])
        plot2.points = [(x, sin(x / 10.)) for x in range(65000, 120000)]
        graph.add_plot(plot2)

        b.add_widget(graph)
        graph.xmax=1000
        graph.xmax=40

        self.add_widget(b)

    def zoom(self):
        print("if mousewheel i change graph.xmin and graph.xmax")



class MyApp(App):
    def build(self):
        return Visu()


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

我使用此代码 https://github.com/kivy-garden/garden.graph/blob/master/init.py 用于使用 kivy 创建图表,但使用此代码我无法放大我的图表。

我想检测鼠标滚轮并运行我的函数 self.zoom

【问题讨论】:

    标签: python kivy


    【解决方案1】:

    你要实现on_touch_down事件,通过is_mouse_scrollingbutton查看是否有滚动条以及滚动条是什么类型。

    class Visu(GridLayout):
        def __init__(self, **kwargs):
            ...
    
        def on_touch_down(self, touch):
            if touch.is_mouse_scrolling:
                if touch.button == 'scrolldown':
                    print('down')
                elif touch.button == 'scrollup':
                    print('up')
             GridLayout.on_touch_down(self, touch)
    
        def zoom(self):
            print("if mousewheel i change graph.xmin and graph.xmax")
    

    【讨论】:

      【解决方案2】:

      按钮事件:on_press 或 on_release

      on_presson_release 事件可绑定到 Button 小部件。我们可以使用on_touch_down来模拟on_press事件,使用on_touch_up来模拟on_release事件。

      事件:on_touch_down

      使用 on_touch_down 事件,检查 touch 与我们的小部件的 碰撞,并检查 按钮配置文件 .如果按钮配置文件,检查鼠标按钮点击,或鼠标滚轮滚动scrollupscrolldown)。如果单击按钮,则抓取触摸事件,增加触摸事件计数器,然后开始重复缩放。

      事件:on_touch_up

      使用on_touch_up事件,检查触摸事件是否被抓取,如果被抓取则取消抓取触摸事件,减少触摸事件计数器,如果触摸事件计数器为零,则停止重复缩放。

      片段

      def on_touch_down(self, touch):
          if self.collide_point(*touch.pos):
              if 'button' in touch.profile:
                  if touch.button in ("right", "left"):
                      ...
                      dist = 1 if touch.button == 'left' else -1
                      touch.grab(self)
                      self._touch_count += 1
                      ...
                      return True
                  elif touch.is_mouse_scrolling:
                      dist = 1 if touch.button == 'scrollup' else -1
                      ...
                      return True
          return super(..., self).on_touch_down(touch)
      
      def on_touch_up(self, touch):
          if touch.grab_current == self:
              touch.ungrab(self)
              self._touch_count -= 1
              if self._touch_count == 0:
                  print("\tanimate to the closest zoom")
              return True
          return super(RootWidget, self).on_touch_up(touch)
      

      Programming Guide » Input management » Touch event basics

      默认情况下,触摸事件被调度到所有当前显示的 小部件。这意味着无论是否发生,小部件都会接收到触摸事件 是否在他们的物理区域内。

      为了提供最大的灵活性,Kivy 调度 所有小部件的事件,并让它们决定如何对它们做出反应。 如果您只想响应小部件内的触摸事件,您 只需检查碰撞。

      Motion Event » Profiles

      配置文件值:按钮
      描述:鼠标按钮(‘左’, 'right'、'middle'、'scrollup' 或 'scrolldown')。通过访问 按钮属性。

      is_mouse_scrolling
      如果触摸是鼠标滚轮滚动,则返回 True

      示例

      main.py

      ​​>
      from math import sin
      from kivy.garden.graph import Graph, MeshLinePlot
      
      from kivy.app import App
      from kivy.uix.boxlayout import BoxLayout
      from kivy.properties import NumericProperty
      
      
      class RootWidget(BoxLayout):
          _touch_count = NumericProperty(0)
      
          def __init__(self, **kwargs):
              super(RootWidget, self).__init__(**kwargs)
      
              self.graph = Graph(xlabel='X', ylabel='Y', x_ticks_minor=5,
                                 x_ticks_major=25, y_ticks_major=1,
                                 y_grid_label=True, x_grid_label=True, padding=5,
                                 x_grid=True, y_grid=True, xmin=-0, xmax=100, ymin=-1, ymax=1)
      
              plot = MeshLinePlot(color=[1, 0, 0, 1])
              plot.points = [(x, sin(x / 10.)) for x in range(0, 101)]
              self.graph.add_plot(plot)
              self.add_widget(self.graph)
      
          def on_touch_down(self, touch):
              """
              If the touch falls inside of our widget, we check button profile. If mouse button click, we set dist to 1 for
              left mouse button clicked else -1 for right mouse button clicked. If not mouse button click, we check for mouse
              wheel scrolling. If mouse is scrolling, we set dist to 1 if scrollup else -1 for scrolldown. If mouse button 
              clicked or mouse wheel scrolling, we return True, indicating that we have consumed the touch and don’t want it
              to propagate any further.
      
              Finally, if the touch falls outside our widget, not mouse button clicked (left / right button clicked), or not
              mouse wheel scrolling, we call the original event using super(…) and return the result. This allows the touch 
              event propagation to continue as it would normally have occurred.
      
              :param touch:
              :return:
      """
      
              print("\non_touch_down:")
      
              if self.collide_point(*touch.pos):
                  if 'button' in touch.profile:
                      if touch.button in ("right", "left"):
                          print("\t", touch.button, "mouse clicked")
                          print("\ttouch.pos =", touch.pos)
                          dist = 1 if touch.button == 'left' else -1
                          self.zoom(dist)
                          return True
                      elif touch.is_mouse_scrolling:
                          print("\tmouse wheel", touch.button)
                          print("\ttouch.pos =", touch.pos)
                          dist = 1 if touch.button == 'scrollup' else -1
                          self.zoom(dist)
                          return True
              return super(RootWidget, self).on_touch_down(touch)
      
          def on_touch_up(self, touch):
              print("\non_touch_up:")
              if touch.grab_current == self:
                  print("\ttouch.button is", touch.button)
                  print("\ttouch.pos is", touch.pos)
                  touch.ungrab(self)
                  self._touch_count -= 1
                  if self._touch_count == 0:
                      # TODO
                      print("\tanimate to the closest zoom")
                  return True
              return super(RootWidget, self).on_touch_up(touch)
      
          def zoom(self, dist):
              self.graph.xmax += dist * 10
              self.graph.xmin += dist
      
      
      class GraphDemo(App):
      
          def build(self):
              return RootWidget()
      
      
      if __name__ == "__main__":
          GraphDemo().run()
      

      输出

      【讨论】:

      • 感谢您的帮助,您的解决方案工作!我找到了鼠标事件kivy.org/docs/api-kivy.input.motionevent.html 的文档@ 通过缩放,当我按下鼠标左键时我想在我的图表中移动,但我不想为“按下鼠标左键”找到事件我有这个代码: if touch.is_touch: if touch.button=="left": print(touch.x) print(touch.y) 我检测到左键单击但不是“按下左键时”
      • on_presson_release 事件只能绑定到 Button 小部件。因此,我们无法从 BoxLayout 中检测到 on_press 事件。我们将使用 on_touch_down 事件来检测 鼠标按钮点击 以模拟 on_press 事件。我更新了我的帖子,检测鼠标按钮点击。
      • 感谢您的帮助,我误会了我的问题我可以检测到左键或右键单击,但我想检测事件,因为左键单击保持重复缩放功能
      • 使用 on_touch_downon_touch_up 事件来检测按钮点击的释放。详情请参阅我更新的帖子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多