def start(self): if config['disable_animations']: return self.setVisible(True) self.raise_() end = self.abspos(self.gui.jobs_button) end = QPointF( end.x() + self.gui.jobs_button.width()/3.0, end.y()+20) start = QPointF(end.x(), end.y() - 0.5*self.height()) self.path = QPainterPath(QPointF(start)) self.path.lineTo(end) self.path.closeSubpath() self.animation.setStartValue(self.rect_at(0.0)) self.animation.setEndValue(self.rect_at(1.0)) self.animation.setDirection(self.animation.Backward) num_keys = 100 for i in xrange(1, num_keys): i /= num_keys self.animation.setKeyValueAt(i, self.rect_at(i)) self.animation.start()
def start(self): if config['disable_animations']: return self.setVisible(True) self.raise_() end = self.abspos(self.gui.jobs_button) end = QPointF(end.x() + self.gui.jobs_button.width()/3.0, end.y()+20) start = QPointF(end.x(), end.y() - 0.5*self.height()) self.path = QPainterPath(QPointF(start)) self.path.lineTo(end) self.path.closeSubpath() self.animation.setStartValue(self.rect_at(0.0)) self.animation.setEndValue(self.rect_at(1.0)) self.animation.setDirection(self.animation.Backward) num_keys = 100 for i in range(1, num_keys): i /= num_keys self.animation.setKeyValueAt(i, self.rect_at(i)) self.animation.start()
def addToMap(self, iso: QPointF) -> None: self._delOldBlocks() self.x = round(iso.x()) self.y = round(iso.y()) self._addNewBlocks()
def addToMap(self, iso: QPointF) -> None: self._delFromMap() self.x = round(iso.x()) self.y = round(iso.y()) self._addToMap()
def __calculate_arrow(self, branch_middle: QPointF, middle_angle: QPointF, arrow_height: int, arrow_length: int, side_spline_depth: int, back_spline_depth: int) -> QPainterPath: """ Calculate the QPainterPath of an arrow consisting of three Bézier curves """ # Calculate the edge positions of the triangle head_edge_not_rotated = QPointF(branch_middle.x() + (arrow_length / 2), branch_middle.y()) head_edge = rotate_pointF(branch_middle, head_edge_not_rotated, middle_angle) top_edge = rotate_pointF(branch_middle, QPointF(head_edge_not_rotated.x() - arrow_length, head_edge_not_rotated.y() - arrow_height), middle_angle) bottom_edge = rotate_pointF(branch_middle, QPointF(head_edge_not_rotated.x() - arrow_length, head_edge_not_rotated.y() + arrow_height), middle_angle) # Calculate the angle of the top of the arrow arrow_top_angle = math.tanh(arrow_height / arrow_length) # Calculate the position of the splines for the sides # The splines are positioned at the middle of the sides # with a defined right-angled spacing arrow_side_length = math.sqrt(math.pow(arrow_length, 2) + math.pow(arrow_height, 2)) side_spline_angle = math.tanh(side_spline_depth / (arrow_side_length / 2)) side_spline_length = (arrow_side_length / 2) / math.cos( side_spline_angle) # Rotate point arround heade_edge for reaching the calculated position # then rotate it around the arrow angle top_spline = rotate_pointF(branch_middle, rotate_pointF( head_edge_not_rotated, QPointF(head_edge_not_rotated.x() - side_spline_length, head_edge_not_rotated.y()), arrow_top_angle - side_spline_angle), middle_angle) bottom_spline = rotate_pointF(branch_middle, rotate_pointF( head_edge_not_rotated, QPointF(head_edge_not_rotated.x() - side_spline_length, head_edge_not_rotated.y()), -(arrow_top_angle - side_spline_angle)), middle_angle) back_spline = rotate_pointF(branch_middle, QPointF(head_edge_not_rotated.x() - arrow_length + back_spline_depth, head_edge_not_rotated.y()), middle_angle) # Build path for drawing arrow arrow = QPainterPath() arrow.moveTo(head_edge) arrow.cubicTo(top_spline, top_spline, top_edge) arrow.cubicTo(back_spline, back_spline, bottom_edge) arrow.cubicTo(bottom_spline, bottom_spline, head_edge) return arrow
class TinderUI(QWidget, UI): def __init__(self, parent=None): super().__init__(parent) self._position = QPointF(0, 0) self._opacity = 1.0 self._scale = 4.5 self.setMinimumSize(600, 600) self._image = None self._show_title_card = True self._load_title_card() self.grabGesture( QGestureRecognizer.registerRecognizer(PanGestureRecognizer())) @pyqtProperty("QPointF") def position(self): return self._position @position.setter def position(self, pos): self._position = pos self.update() @pyqtProperty("float") def opacity(self): return self._opacity @opacity.setter def opacity(self, opacity): self._opacity = opacity self.update() @pyqtProperty("float") def scale(self): return self._scale @scale.setter def scale(self, scale): self._scale = scale self.update() @property def rotation(self): pic = [self.position.x(), -self.position.y()] pivot = [0, -self.height()] v1 = np.subtract(pic, pivot) v2 = np.subtract([0, 0], pivot) a = np.arccos( np.divide(np.abs(np.dot(v1, v2)), (np.linalg.norm(v1) * np.linalg.norm(v2)))) if self.position.x() < 0: return -a * 10 return a * 10 def _load_title_card(self): title_card = QImage(Defaults.title_card_file_path) self.title_image = Image(None, None) self.title_image.q_image = title_card def event(self, event): if event.type() == QEvent.Gesture and event.gesture(Qt.PanGesture): self._pan_triggered(event.gesture(Qt.PanGesture)) else: super().event(event) return True def wheelEvent(self, e): self.scale -= e.pixelDelta().y() * 0.01 if self.scale < 0.1: self.scale = 0.1 def paintEvent(self, event): painter = self._setup_painter() self._paint_circles(painter) self._paint_icons(painter) self._paint_image(painter) def _setup_painter(self): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.translate(self.width() / 2, self.height() / 2) painter.setPen(Defaults.pen) return painter def _paint_circles(self, painter): painter.save() if self.position.x() > 0: painter.setBrush(Defaults.single_color) painter.drawEllipse(QPointF(self.width() / 2, 0), (self.width() / 4) * (self.position.x() / (self.width() / 2)) / 2, self.height() / 2 + self.height() * 0.1) else: painter.setBrush(Defaults.multi_color) painter.drawEllipse(QPointF(-self.width() / 2, 0), (self.width() / 4) * (self.position.x() / (self.width() / 2)) / 2, self.height() / 2 + self.height() * 0.1) if self.position.y() < 0: painter.setBrush(Defaults.skip_color) painter.drawEllipse(QPointF(0, -self.height() / 2), self.width() / 2 + self.width() * 0.1, (self.height() / 4) * (-self.position.y() / (self.height() / 2)) / 2) else: painter.setBrush(Defaults.skip_color) painter.drawEllipse(QPointF(0, self.height() / 2), self.width() / 2 + self.width() * 0.1, (self.height() / 4) * (-self.position.y() / (self.height() / 2)) / 2) painter.restore() def _paint_icons(self, painter): size = 60 res = 256 margin = 10 opacity = 130 / 255 * (1 - np.linalg.norm( [self.position.x(), self.position.y()]) / np.linalg.norm( [self.width() / 2, self.height() / 2])) painter.setOpacity(opacity) painter.save() painter.translate(self.width() / 2 - size / 2 - margin, 0) if self.position.x() > 0: painter.translate(-self.position.x() * 0.1, 0) painter.setOpacity(opacity + 130 / 255 * self.position.x() / (self.width() / 2)) painter.translate(-size / 2, -size / 2) painter.scale(size / res, size / res) painter.drawImage(0, 0, QImage(Defaults.check_icon_path)) painter.restore() painter.save() painter.translate(-self.width() / 2 + size / 2 + margin, 0) if self.position.x() < 0: painter.translate(-self.position.x() * 0.1, 0) painter.setOpacity(opacity + 130 / 255 * -self.position.x() / (self.width() / 2)) painter.translate(-size / 2, -size / 2) painter.scale(size / res, size / res) painter.drawImage(0, 0, QImage(Defaults.cross_icon_path)) painter.restore() painter.save() painter.translate(0, -self.height() / 2 + size / 2 + margin) if self.position.y() < 0: painter.translate(0, -self.position.y() * 0.1) painter.setOpacity(opacity + 130 / 255 * -self.position.y() / (self.height() / 2)) painter.translate(-size / 2, -size / 2) painter.scale(size / res, size / res) painter.drawImage(0, 0, QImage(Defaults.clock_icon_path)) painter.restore() painter.save() painter.translate(0, self.height() / 2 - size / 2 - margin) if self.position.y() > 0: painter.translate(0, -self.position.y() * 0.1) painter.setOpacity(opacity + 130 / 255 * self.position.y() / (self.height() / 2)) painter.translate(-size / 2, -size / 2) painter.scale(size / res, size / res) painter.drawImage(0, 0, QImage(Defaults.clock_icon_path)) painter.restore() def _paint_image(self, painter): painter.save() iw = self._image.width or 250 ih = self._image.height or 250 # setting painter up to right location and orientation to draw painter.translate(self.position.x(), self.position.y()) painter.rotate(self.rotation) painter.scale(self.scale, self.scale) painter.translate(-iw / 2, -ih / 2) painter.setOpacity(self.opacity) # drawing a shadow painter.setBrush(QColor(0, 0, 0, 10)) painter.drawRect(2, 2, iw, ih) # drawing the image (or a rectangle if there is no image) if not self._image: painter.setBrush(QColor(150, 150, 150)) painter.drawRect(0, 0, iw, ih) else: if self._show_title_card: painter.scale(100 / 1024, 100 / 1024) painter.drawImage(0, 0, self.title_image.q_image) else: # painter.setCompositionMode(QPainter.CompositionMode_Source) # painter.setBrush(QColor(0, 0, 0)) # painter.drawRoundedRect(0, 0, iw, ih, 2, 2) # painter.setCompositionMode(QPainter.CompositionMode_DestinationOver) painter.drawImage(0, 0, self._image.q_image) painter.restore() def _reset(self, was_classified): if was_classified: self._show_title_card = False self.position = QPointF(0, 0) self.animation1 = QPropertyAnimation(self, b'opacity') self.animation1.setStartValue(0) self.animation1.setEndValue(1) self.animation1.setDuration(75) self.animation1.start() self.animation2 = QPropertyAnimation(self, b'scale') self.animation2.setStartValue(self.scale - 1) self.animation2.setEndValue(self.scale) self.animation2.setDuration(75) self.animation2.start() else: self.animation3 = QPropertyAnimation(self, b'position') self.animation3.setStartValue(self.position) self.animation3.setEndValue(QPointF(0, 0)) self.animation3.setEasingCurve(QEasingCurve.OutBack) self.animation3.setDuration( (np.linalg.norm([self.position.x(), self.position.y()]) / np.linalg.norm([self.width(), self.height()])) * 500) self.animation3.start() def _pan_triggered(self, pan_gesture): delta = pan_gesture.delta() self.position += delta * Defaults.sensibility if pan_gesture.state() == Qt.GestureFinished: self._reset(self._check_if_classified()) def _check_if_classified(self): if self.position.x() > self.width() / 2 - self.width() * 0.1: if not self._show_title_card: self._classify_single() return True elif self.position.x() < -self.width() / 2 + self.width() * 0.1: if not self._show_title_card: self._classify_multi() return True elif self.position.y() < -self.height() / 2 + self.height( ) * 0.1 or self.position.y() > self.height() / 2 - self.height() * 0.1: if not self._show_title_card: self._classify_skip() return True return False def show_image(self, image, cmap=Defaults.cmap, interpolation='gaussian'): if not image.q_image: PlotService().convert_to_image(image) self._image = image self.update() def connect_single_classification_listener(self, action): self._classify_single = action def connect_skip_classification_listener(self, action): self._classify_skip = action def connect_multi_classification_listener(self, action): self._classify_multi = action