Skip to content

Instantly share code, notes, and snippets.

@stdk
Created October 16, 2013 22:15
Show Gist options
  • Save stdk/7015871 to your computer and use it in GitHub Desktop.
Save stdk/7015871 to your computer and use it in GitHub Desktop.
Now pythonic!
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MouseGestureRecognizer(QGestureRecognizer):
Up = 0
Down = 1
Left = 2
Right = 3
AnyHorizontal = 4
AnyVertical = 5
NoMatch = 6
def __init__(self, directions=None, minimum_movement=5, minimum_match=0.9, gesture_button=Qt.RightButton):
QGestureRecognizer.__init__(self)
self._directions = directions if directions else []
self._minimum_movement = minimum_movement
self._minimum_match = minimum_match
self._gesture_button = gesture_button
self._minimum_movement2 = self._minimum_movement ** 2
self._tracing = False
self._positions = []
def recognize(self, gesture, watched, event):
result = QGestureRecognizer.Ignore
if event.type() == QEvent.MouseButtonPress and event.button() == self._gesture_button:
result = QGestureRecognizer.MayBeGesture
self._tracing = True
self._positions = [event.pos()]
elif event.type() == QEvent.MouseMove and self._tracing:
x, y = event.pos().x(), event.pos().y()
dx = x - self._positions[-1].x()
dy = y - self._positions[-1].y()
if dx ** 2 + dy ** 2 >= self._minimum_movement:
result = QGestureRecognizer.MayBeGesture
self._positions.append(event.pos())
elif event.type() == QEvent.MouseButtonRelease and event.button() == self._gesture_button and self._tracing:
self._tracing = False
if event.pos() != self._positions[-1]:
self._positions.append(event.pos())
directions = MouseGestureRecognizer.simplify(
MouseGestureRecognizer.limit_directions(self._positions)
)
min_length = MouseGestureRecognizer.calc_length(directions) * self._minimum_match
while len(directions) > 0 and MouseGestureRecognizer.calc_length(directions) > min_length:
if len(self._directions) == len(directions):
match = True
for i, di in enumerate(self._directions):
if not match:
break
pi = directions[i]
print pi
if di == MouseGestureRecognizer.Up:
if pi.y() >= 0:
match = False
elif di == MouseGestureRecognizer.Down:
if pi.y() <= 0:
match = False
elif di == MouseGestureRecognizer.Left:
if pi.x() >= 0:
match = False
elif di == MouseGestureRecognizer.Right:
if pi.x() <= 0:
match = False
elif di == MouseGestureRecognizer.AnyHorizontal:
if pi.x() == 0:
match = False
elif di == MouseGestureRecognizer.AnyVertical:
if pi.y() == 0:
match = False
elif di == MouseGestureRecognizer.NoMatch:
match = False
if match:
return QGestureRecognizer.FinishGesture
directions = MouseGestureRecognizer.simplify(
MouseGestureRecognizer.remove_shortest(directions)
)
print self._directions, directions
else:
result = QGestureRecognizer.CancelGesture
return result
def reset(self, state):
self._positions = []
QGestureRecognizer.reset(self, state)
@staticmethod
def limit_directions(positions):
res = []
first_time = True
for ii in positions:
if first_time:
last_x = ii.x()
last_y = ii.y()
first_time = False
else:
dx = ii.x() - last_x
dy = ii.y() - last_y
if dy > 0:
if dx > dy or -dx > dy:
dy = 0
else:
dx = 0
else:
if dx > -dy or -dx > -dy:
dy = 0
else:
dx = 0
res.append(QPoint(dx, dy))
last_x = ii.x()
last_y = ii.y()
return res
@staticmethod
def simplify(positions):
res = []
last_dx = 0
last_dy = 0
first_time = True
for ii in positions:
if first_time:
last_dx = ii.x()
last_dy = ii.y()
first_time = False
else:
joined = False
if (last_dx > 0 and ii.x() > 0) or (last_dx < 0 and ii.x() < 0):
last_dx += ii.x()
joined = True
if (last_dy > 0 and ii.y() > 0) or (last_dy < 0 and ii.y() < 0):
last_dy += ii.y()
joined = True
if not joined:
res.append(QPoint(last_dx, last_dy))
last_dx = ii.x()
last_dy = ii.y()
if last_dx != 0 or last_dy != 0:
res.append(QPoint(last_dx, last_dy))
return res
@staticmethod
def remove_shortest(positions):
res = []
first_time = True
for ii in positions:
if first_time:
shortest_so_far = ii.x() ** 2 + ii.y() ** 2
shortest = ii
first_time = False
else:
if (ii.x() ** 2 + ii.y() ** 2) < shortest_so_far:
shortest_so_far = ii.x() ** 2 + ii.y() ** 2
shortest = ii
for ii in positions:
if ii != shortest:
res.append(ii)
return res
@staticmethod
def calc_length(positions):
res = 0
for ii in positions:
if ii.x() > 0:
res += ii.x()
elif ii.x() < 0:
res -= ii.x()
elif ii.y() > 0:
res += ii.y()
else:
res -= ii.y()
return res
class Widget(QWidget):
gestured = pyqtSignal(int)
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.recognizer = MouseGestureRecognizer([MouseGestureRecognizer.Up, MouseGestureRecognizer.Left])
self.recognizer_type = QGestureRecognizer.registerRecognizer(self.recognizer)
self.grabGesture(self.recognizer_type)
self.cancel_recognizer = MouseGestureRecognizer([
MouseGestureRecognizer.Up,
MouseGestureRecognizer.Down,
MouseGestureRecognizer.Up])
self.cancel_type = QGestureRecognizer.registerRecognizer(self.cancel_recognizer)
self.grabGesture(self.cancel_type)
vl = QVBoxLayout(self)
self._checkboxes = []
for i in range(5):
self._checkboxes.append(QCheckBox("No. %d" % (i + 1), self))
vl.addWidget(self._checkboxes[i])
hl = QHBoxLayout()
hl.addWidget(QPushButton("Check", self, clicked=self.set_all))
hl.addWidget(QPushButton("Clear", self, clicked=self.clear_all))
vl.addLayout(hl)
def event(self, e):
if e.type() == QEvent.Gesture:
print 11111111111111
for g in e.gestures():
if not g.state() == Qt.GestureFinished:
continue
if g.gestureType() == self.recognizer_type:
self.set_all()
e.setAccepted(g, True)
return True
elif g.gestureType() == self.cancel_type:
self.clear_all()
e.setAccepted(g, True)
return True
else:
continue
return QWidget.event(self, e)
def clear_all(self):
for cb in self._checkboxes:
cb.setChecked(False)
def set_all(self):
for cb in self._checkboxes:
cb.setChecked(True)
if __name__ == "__main__":
from sys import argv, exit
a = QApplication(argv)
w = Widget()
w.show()
w.raise_()
exit(a.exec_())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment