Created
October 16, 2013 22:15
-
-
Save stdk/7015871 to your computer and use it in GitHub Desktop.
Now pythonic!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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