mouseEvents.py 13.4 KB
Newer Older
1
2
3
4
5
6
from pyqtgraph.Point import Point
from pyqtgraph.Qt import QtCore, QtGui
import weakref
import pyqtgraph.ptime as ptime

class MouseDragEvent:
Luke Campagnola's avatar
Luke Campagnola committed
7
8
9
10
11
12
13
    """
    Instances of this class are delivered to items in a :class:`GraphicsScene <pyqtgraph.GraphicsScene>` via their mouseDragEvent() method when the item is being mouse-dragged. 
    
    """
    
    
    
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    def __init__(self, moveEvent, pressEvent, lastEvent, start=False, finish=False):
        self.start = start
        self.finish = finish
        self.accepted = False
        self.currentItem = None
        self._buttonDownScenePos = {}
        self._buttonDownScreenPos = {}
        for btn in [QtCore.Qt.LeftButton, QtCore.Qt.MidButton, QtCore.Qt.RightButton]:
            self._buttonDownScenePos[int(btn)] = moveEvent.buttonDownScenePos(btn)
            self._buttonDownScreenPos[int(btn)] = moveEvent.buttonDownScreenPos(btn)
        self._scenePos = moveEvent.scenePos()
        self._screenPos = moveEvent.screenPos()
        if lastEvent is None:
            self._lastScenePos = pressEvent.scenePos()
            self._lastScreenPos = pressEvent.screenPos()
        else:
            self._lastScenePos = lastEvent.scenePos()
            self._lastScreenPos = lastEvent.screenPos()
        self._buttons = moveEvent.buttons()
        self._button = pressEvent.button()
        self._modifiers = moveEvent.modifiers()
Luke Campagnola's avatar
Luke Campagnola committed
35
        self.acceptedItem = None
36
37
        
    def accept(self):
Luke Campagnola's avatar
Luke Campagnola committed
38
        """An item should call this method if it can handle the event. This will prevent the event being delivered to any other items."""
39
40
41
42
        self.accepted = True
        self.acceptedItem = self.currentItem
        
    def ignore(self):
Luke Campagnola's avatar
Luke Campagnola committed
43
        """An item should call this method if it cannot handle the event. This will allow the event to be delivered to other items."""
44
45
46
47
48
49
        self.accepted = False
    
    def isAccepted(self):
        return self.accepted
    
    def scenePos(self):
Luke Campagnola's avatar
Luke Campagnola committed
50
        """Return the current scene position of the mouse."""
51
52
53
        return Point(self._scenePos)
    
    def screenPos(self):
Luke Campagnola's avatar
Luke Campagnola committed
54
        """Return the current screen position (pixels relative to widget) of the mouse."""
55
56
57
        return Point(self._screenPos)
    
    def buttonDownScenePos(self, btn=None):
Luke Campagnola's avatar
Luke Campagnola committed
58
59
60
61
        """
        Return the scene position of the mouse at the time *btn* was pressed.
        If *btn* is omitted, then the button that initiated the drag is assumed.
        """
62
63
64
65
66
        if btn is None:
            btn = self.button()
        return Point(self._buttonDownScenePos[int(btn)])
    
    def buttonDownScreenPos(self, btn=None):
Luke Campagnola's avatar
Luke Campagnola committed
67
68
69
70
        """
        Return the screen position (pixels relative to widget) of the mouse at the time *btn* was pressed.
        If *btn* is omitted, then the button that initiated the drag is assumed.
        """
71
72
73
74
75
        if btn is None:
            btn = self.button()
        return Point(self._buttonDownScreenPos[int(btn)])
    
    def lastScenePos(self):
Luke Campagnola's avatar
Luke Campagnola committed
76
77
78
        """
        Return the scene position of the mouse immediately prior to this event.
        """
79
80
81
        return Point(self._lastScenePos)
    
    def lastScreenPos(self):
Luke Campagnola's avatar
Luke Campagnola committed
82
83
84
        """
        Return the screen position of the mouse immediately prior to this event.
        """
85
86
87
        return Point(self._lastScreenPos)
    
    def buttons(self):
Luke Campagnola's avatar
Luke Campagnola committed
88
89
90
91
        """
        Return the buttons currently pressed on the mouse.
        (see QGraphicsSceneMouseEvent::buttons in the Qt documentation)
        """
92
93
94
        return self._buttons
        
    def button(self):
Luke Campagnola's avatar
Luke Campagnola committed
95
96
97
98
        """Return the button that initiated the drag (may be different from the buttons currently pressed)
        (see QGraphicsSceneMouseEvent::button in the Qt documentation)
        
        """
99
100
101
        return self._button
        
    def pos(self):
Luke Campagnola's avatar
Luke Campagnola committed
102
103
104
105
        """
        Return the current position of the mouse in the coordinate system of the item
        that the event was delivered to.
        """
106
107
108
        return Point(self.currentItem.mapFromScene(self._scenePos))
    
    def lastPos(self):
Luke Campagnola's avatar
Luke Campagnola committed
109
110
111
112
        """
        Return the previous position of the mouse in the coordinate system of the item
        that the event was delivered to.
        """
113
114
115
        return Point(self.currentItem.mapFromScene(self._lastScenePos))
        
    def buttonDownPos(self, btn=None):
Luke Campagnola's avatar
Luke Campagnola committed
116
117
118
119
        """
        Return the position of the mouse at the time the drag was initiated
        in the coordinate system of the item that the event was delivered to.
        """
120
121
122
123
124
        if btn is None:
            btn = self.button()
        return Point(self.currentItem.mapFromScene(self._buttonDownScenePos[int(btn)]))
    
    def isStart(self):
Luke Campagnola's avatar
Luke Campagnola committed
125
        """Returns True if this event is the first since a drag was initiated."""
126
127
128
        return self.start
        
    def isFinish(self):
Luke Campagnola's avatar
Luke Campagnola committed
129
130
        """Returns False if this is the last event in a drag. Note that this
        event will have the same position as the previous one."""
131
132
133
134
135
136
137
138
        return self.finish

    def __repr__(self):
        lp = self.lastPos()
        p = self.pos()
        return "<MouseDragEvent (%g,%g)->(%g,%g) buttons=%d start=%s finish=%s>" % (lp.x(), lp.y(), p.x(), p.y(), int(self.buttons()), str(self.isStart()), str(self.isFinish()))
        
    def modifiers(self):
Luke Campagnola's avatar
Luke Campagnola committed
139
140
141
142
        """Return any keyboard modifiers currently pressed.
        (see QGraphicsSceneMouseEvent::modifiers in the Qt documentation)
        
        """
143
144
145
146
147
        return self._modifiers



class MouseClickEvent:
Luke Campagnola's avatar
Luke Campagnola committed
148
149
150
151
152
153
    """
    Instances of this class are delivered to items in a :class:`GraphicsScene <pyqtgraph.GraphicsScene>` via their mouseClickEvent() method when the item is clicked. 
    
    
    """
    
154
155
156
157
158
159
160
161
162
163
    def __init__(self, pressEvent, double=False):
        self.accepted = False
        self.currentItem = None
        self._double = double
        self._scenePos = pressEvent.scenePos()
        self._screenPos = pressEvent.screenPos()
        self._button = pressEvent.button()
        self._buttons = pressEvent.buttons()
        self._modifiers = pressEvent.modifiers()
        self._time = ptime.time()
Luke Campagnola's avatar
Luke Campagnola committed
164
        self.acceptedItem = None
165
166
        
    def accept(self):
Luke Campagnola's avatar
Luke Campagnola committed
167
        """An item should call this method if it can handle the event. This will prevent the event being delivered to any other items."""
168
169
170
171
        self.accepted = True
        self.acceptedItem = self.currentItem
        
    def ignore(self):
Luke Campagnola's avatar
Luke Campagnola committed
172
        """An item should call this method if it cannot handle the event. This will allow the event to be delivered to other items."""
173
174
175
176
177
178
        self.accepted = False
    
    def isAccepted(self):
        return self.accepted
    
    def scenePos(self):
Luke Campagnola's avatar
Luke Campagnola committed
179
        """Return the current scene position of the mouse."""
180
181
182
        return Point(self._scenePos)
    
    def screenPos(self):
Luke Campagnola's avatar
Luke Campagnola committed
183
        """Return the current screen position (pixels relative to widget) of the mouse."""
184
185
186
        return Point(self._screenPos)
    
    def buttons(self):
Luke Campagnola's avatar
Luke Campagnola committed
187
188
189
190
        """
        Return the buttons currently pressed on the mouse.
        (see QGraphicsSceneMouseEvent::buttons in the Qt documentation)
        """
191
192
193
        return self._buttons
    
    def button(self):
Luke Campagnola's avatar
Luke Campagnola committed
194
195
196
        """Return the mouse button that generated the click event.
        (see QGraphicsSceneMouseEvent::button in the Qt documentation)
        """
197
198
199
        return self._button
    
    def double(self):
Luke Campagnola's avatar
Luke Campagnola committed
200
        """Return True if this is a double-click."""
201
202
203
        return self._double

    def pos(self):
Luke Campagnola's avatar
Luke Campagnola committed
204
205
206
207
        """
        Return the current position of the mouse in the coordinate system of the item
        that the event was delivered to.
        """
208
209
210
        return Point(self.currentItem.mapFromScene(self._scenePos))
    
    def lastPos(self):
Luke Campagnola's avatar
Luke Campagnola committed
211
212
213
214
        """
        Return the previous position of the mouse in the coordinate system of the item
        that the event was delivered to.
        """
215
216
217
        return Point(self.currentItem.mapFromScene(self._lastScenePos))
        
    def modifiers(self):
Luke Campagnola's avatar
Luke Campagnola committed
218
219
220
        """Return any keyboard modifiers currently pressed.
        (see QGraphicsSceneMouseEvent::modifiers in the Qt documentation)        
        """
221
222
223
224
225
226
227
228
229
230
231
232
233
        return self._modifiers

    def __repr__(self):
        p = self.pos()
        return "<MouseClickEvent (%g,%g) button=%d>" % (p.x(), p.y(), int(self.button()))
        
    def time(self):
        return self._time



class HoverEvent:
    """
Luke Campagnola's avatar
Luke Campagnola committed
234
    Instances of this class are delivered to items in a :class:`GraphicsScene <pyqtgraph.GraphicsScene>` via their hoverEvent() method when the mouse is hovering over the item.
235
    This event class both informs items that the mouse cursor is nearby and allows items to 
Luke Campagnola's avatar
Luke Campagnola committed
236
    communicate with one another about whether each item will accept *potential* mouse events. 
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
    
    It is common for multiple overlapping items to receive hover events and respond by changing 
    their appearance. This can be misleading to the user since, in general, only one item will
    respond to mouse events. To avoid this, items make calls to event.acceptClicks(button) 
    and/or acceptDrags(button).
    
    Each item may make multiple calls to acceptClicks/Drags, each time for a different button. 
    If the method returns True, then the item is guaranteed to be
    the recipient of the claimed event IF the user presses the specified mouse button before
    moving. If claimEvent returns False, then this item is guaranteed NOT to get the specified
    event (because another has already claimed it) and the item should change its appearance 
    accordingly.
    
    event.isEnter() returns True if the mouse has just entered the item's shape;
    event.isExit() returns True if the mouse has just left.
    """
    def __init__(self, moveEvent, acceptable):
        self.enter = False
        self.acceptable = acceptable
        self.exit = False
        self.__clickItems = weakref.WeakValueDictionary()
        self.__dragItems = weakref.WeakValueDictionary()
        self.currentItem = None
        if moveEvent is not None:
            self._scenePos = moveEvent.scenePos()
            self._screenPos = moveEvent.screenPos()
            self._lastScenePos = moveEvent.lastScenePos()
            self._lastScreenPos = moveEvent.lastScreenPos()
            self._buttons = moveEvent.buttons()
            self._modifiers = moveEvent.modifiers()
        else:
            self.exit = True
            
        
        
    def isEnter(self):
Luke Campagnola's avatar
Luke Campagnola committed
273
        """Returns True if the mouse has just entered the item's shape"""
274
275
276
        return self.enter
        
    def isExit(self):
Luke Campagnola's avatar
Luke Campagnola committed
277
        """Returns True if the mouse has just exited the item's shape"""
278
279
280
        return self.exit
        
    def acceptClicks(self, button):
Luke Campagnola's avatar
Luke Campagnola committed
281
282
283
284
285
286
287
        """Inform the scene that the item (that the event was delivered to)
        would accept a mouse click event if the user were to click before
        moving the mouse again.
        
        Returns True if the request is successful, otherwise returns False (indicating
        that some other item would receive an incoming click).
        """
288
289
290
291
292
293
294
295
        if not self.acceptable:
            return False
        if button not in self.__clickItems:
            self.__clickItems[button] = self.currentItem
            return True
        return False
        
    def acceptDrags(self, button):
Luke Campagnola's avatar
Luke Campagnola committed
296
297
298
299
300
301
302
        """Inform the scene that the item (that the event was delivered to)
        would accept a mouse drag event if the user were to drag before
        the next hover event.
        
        Returns True if the request is successful, otherwise returns False (indicating
        that some other item would receive an incoming drag event).
        """
303
304
305
306
307
308
309
310
        if not self.acceptable:
            return False
        if button not in self.__dragItems:
            self.__dragItems[button] = self.currentItem
            return True
        return False
        
    def scenePos(self):
Luke Campagnola's avatar
Luke Campagnola committed
311
        """Return the current scene position of the mouse."""
312
313
314
        return Point(self._scenePos)
    
    def screenPos(self):
Luke Campagnola's avatar
Luke Campagnola committed
315
        """Return the current screen position of the mouse."""
316
317
318
        return Point(self._screenPos)
    
    def lastScenePos(self):
Luke Campagnola's avatar
Luke Campagnola committed
319
        """Return the previous scene position of the mouse."""
320
321
322
        return Point(self._lastScenePos)
    
    def lastScreenPos(self):
Luke Campagnola's avatar
Luke Campagnola committed
323
        """Return the previous screen position of the mouse."""
324
325
326
        return Point(self._lastScreenPos)
    
    def buttons(self):
Luke Campagnola's avatar
Luke Campagnola committed
327
328
329
330
        """
        Return the buttons currently pressed on the mouse.
        (see QGraphicsSceneMouseEvent::buttons in the Qt documentation)
        """
331
332
333
        return self._buttons
        
    def pos(self):
Luke Campagnola's avatar
Luke Campagnola committed
334
335
336
337
        """
        Return the current position of the mouse in the coordinate system of the item
        that the event was delivered to.
        """
338
339
340
        return Point(self.currentItem.mapFromScene(self._scenePos))
    
    def lastPos(self):
Luke Campagnola's avatar
Luke Campagnola committed
341
342
343
344
        """
        Return the previous position of the mouse in the coordinate system of the item
        that the event was delivered to.
        """
345
346
347
348
349
350
351
352
        return Point(self.currentItem.mapFromScene(self._lastScenePos))

    def __repr__(self):
        lp = self.lastPos()
        p = self.pos()
        return "<HoverEvent (%g,%g)->(%g,%g) buttons=%d enter=%s exit=%s>" % (lp.x(), lp.y(), p.x(), p.y(), int(self.buttons()), str(self.isEnter()), str(self.isExit()))
        
    def modifiers(self):
Luke Campagnola's avatar
Luke Campagnola committed
353
354
355
        """Return any keyboard modifiers currently pressed.
        (see QGraphicsSceneMouseEvent::modifiers in the Qt documentation)        
        """
356
357
358
359
360
361
362
363
364
365
        return self._modifiers
    
    def clickItems(self):
        return self.__clickItems
        
    def dragItems(self):
        return self.__dragItems