kivy python3检测鼠标滚轮

时间:2018-04-18 09:29:45

标签: python kivy

你好我想在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

2 个答案:

答案 0 :(得分: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")

答案 1 :(得分:1)

按钮事件:on_press或on_release

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

事件:on_touch_down

使用 on_touch_down 事件,使用我们的小部件检查 touch collision ,并检查按钮配置文件 。如果按钮配置文件,请检查鼠标按钮单击,或鼠标滚轮滚动 scrollup scrolldown < / em>的)。如果单击了按钮,请抓住触摸事件,增加触摸事件计数器,然后开始重复缩放。

事件: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()

输出

Img01 - AppStartup Img02 - Left Mouse Button Clicked Img03 - Right Mouse Button Clicked Img04 - Mouse Wheel ScrollDown Img05 - Mouse Wheel ScrollUp