def __init__(self, parent=None): super(JoyPad, self).__init__(parent=parent) self._x = 0 self._y = 0 self._bounds = QRectF() self._knop_bounds = QRectF() self._last_pos = QPoint() self._knop_pressed = False self._return_animation = QParallelAnimationGroup(self) self._x_anim = QPropertyAnimation(self, 'x') self._y_anim = QPropertyAnimation(self, 'y') self._alignment = Qt.AlignTop | Qt.AlignLeft self._x_anim.setEndValue(0.0) self._x_anim.setDuration(400) self._x_anim.setEasingCurve(QEasingCurve.OutSine) self._y_anim.setEndValue(0.0) self._y_anim.setDuration(400) self._y_anim.setEasingCurve(QEasingCurve.OutSine) self._return_animation.addAnimation(self._x_anim) self._return_animation.addAnimation(self._y_anim)
def slide_in_index(self, next, force=False): """ Slides to the given widget index :param next: int, index of the widget to slide """ now = self.currentIndex() if (self._active_state or next == now) and not force: return self._active_state = True width, height = self.frameRect().width(), self.frameRect().height() next %= self.count() if next > now: if self._vertical: offset_x, offset_y = 0, height else: offset_x, offset_y = width, 0 else: if self._vertical: offset_x, offset_y = 0, -height else: offset_x, offset_y = -width, 0 self.widget(next).setGeometry(0, 0, width, height) pnow, pnext = self.widget(now).pos(), self.widget(next).pos() self._point_now = pnow self.widget(next).move(pnext.x() + offset_x, pnext.y() + offset_y) self.widget(next).show() self.widget(next).raise_() self._current_widget = self.widget(next) anim_now = QPropertyAnimation(self.widget(now), b'pos') anim_now.setDuration(self._speed) anim_now.setStartValue(pnow) anim_now.setEndValue(QPoint(pnow.x() - offset_x, pnow.y() - offset_y)) anim_now.setEasingCurve(self._animation_type) anim_next = QPropertyAnimation(self.widget(next), b'pos') anim_next.setDuration(self._speed) anim_next.setStartValue( QPoint(offset_x + pnext.x(), offset_y + pnext.y())) anim_next.setEndValue(pnext) anim_next.setEasingCurve(self._animation_type) self._anim_group = QParallelAnimationGroup() self._anim_group.addAnimation(anim_now) self._anim_group.addAnimation(anim_next) self._anim_group.finished.connect(self._animation_done_slot) self._anim_group.start() self._next = next self._now = now
def __init__(self, title='', animation_duration=300, parent=None): super(ExpandableLine, self).__init__(parent=parent) self._animation_duration = animation_duration base_layout = layouts.GridLayout(margins=(0, 0, 0, 0)) base_layout.setVerticalSpacing(0) self.setLayout(base_layout) self.expand_btn = QToolButton() self.expand_btn.setText(str(title)) self.expand_btn.setStyleSheet('QToolButton { border : none; }') self.expand_btn.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.expand_btn.setArrowType(Qt.ArrowType.RightArrow) self.expand_btn.setCheckable(True) self.expand_btn.setChecked(True) header_line = QFrame() header_line.setFrameShape(QFrame.HLine) header_line.setFrameShadow(QFrame.Sunken) header_line.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) self.content_area = QScrollArea() self.content_area.setStyleSheet('QScrollArea { border: none;}') self.content_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.content_area.setMaximumHeight(0) self.content_area.setMinimumHeight(0) self.toggle_anim = QParallelAnimationGroup() self.toggle_anim.addAnimation(QPropertyAnimation(self, 'minimumHeight')) self.toggle_anim.addAnimation(QPropertyAnimation(self, 'maximumHeight')) self.toggle_anim.addAnimation(QPropertyAnimation(self.content_area, 'maximumHeight')) row = 0 base_layout.addWidget(self.expand_btn, row, 0, 1, 1, Qt.AlignLeft) base_layout.addWidget(header_line, row, 2, 1, 1) row += 1 base_layout.addWidget(self.content_area, row, 0, 1, 3) def expand_view(checked): arrow_type = Qt.DownArrow if checked else Qt.RightArrow direction = QAbstractAnimation.Forward if checked else QAbstractAnimation.Backward self.expand_btn.setArrowType(arrow_type) self.toggle_anim.setDirection(direction) self.toggle_anim.start() # === SIGNALS === # self.expand_btn.toggled.connect(expand_view) expand_view(True)
def animate_expand(self, value): size_animation = QPropertyAnimation(self, b'geometry') geometry = self.geometry() width = geometry.width() x, y, _, _ = geometry.getCoords() size_start = QRect(x, y, width, int(not value) * self.INTERP_HEIGHT) size_end = QRect(x, y, width, value * 150) size_animation.setStartValue(size_start) size_animation.setEndValue(size_end) size_animation.setDuration(200) size_anim_curve = QEasingCurve() size_anim_curve.setType( QEasingCurve.InQuad) if value else size_anim_curve.setType( QEasingCurve.OutQuad) size_animation.setEasingCurve(size_anim_curve) opacity_animation = QPropertyAnimation(self._main_widget_proxy, b'opacity') opacity_animation.setStartValue(not (value)) opacity_animation.setEndValue(value) opacity_animation.setDuration(100) opacity_anim_curve = QEasingCurve() opacity_anim_curve.setType( QEasingCurve.InQuad) if value else opacity_anim_curve.setType( QEasingCurve.OutQuad) opacity_animation.setEasingCurve(opacity_anim_curve) # We must store the animation objects as a member variables. Otherwise the animation object could be deleted # once the function is completed. In that case, the animation will not work. self._animation = QSequentialAnimationGroup() if value: self._main_widget_proxy.setOpacity(0) self._animation.addAnimation(size_animation) self._animation.addAnimation(opacity_animation) else: self._main_widget_proxy.setOpacity(1) self._animation.addAnimation(opacity_animation) self._animation.addAnimation(size_animation) # When animating geometry property, the parent layout is not updated automatically. # We force the resize of the layout by calling a signal each time the size animation value changes. size_animation.valueChanged.connect(self._on_force_resize) self._animation.finished.connect(self._animation.clear) if not value: self._animation.finished.connect(self._on_delete_widget) self._animation.start(QAbstractAnimation.DeleteWhenStopped)
def fade_animation(start=0, end=1, duration=300, object=None, on_finished=None): """ Fade animation for widgets :param start: int, animation start value :param end: int, animation end value :param duration: int, duration of the effect :param object: variant, QDialog || QMainWindow :param on_finished: variant, function to call when the animation is finished :return: QPropertyAnimation """ anim_curve = QEasingCurve() anim_curve.setType(QEasingCurve.OutQuint) if start == 'current': start = object.opacity() if end == 'current': end = object.opacity() animation = QPropertyAnimation(object, b'opacity', object) animation.setEasingCurve(anim_curve) animation.setDuration(duration) animation.setStartValue(start) animation.setEndValue(end) animation.start() if on_finished: animation.finished.connect(on_finished)
def slide_window(start=-100, end=0, duration=300, object=None, on_finished=None): """ Slide animation for windows :param start: int, animation start value :param end: int, animation end value :param duration: int, duration of the effect :param object: variant, QDialog || QMainWindow :param on_finished: variant, function to call when the animation is finished :return: QPropertyAnimation """ pos = object.pos() animation = QPropertyAnimation(object, b'pos', object) animation.setDuration(duration) anim_curve = QEasingCurve() if start >= end: anim_curve.setType(QEasingCurve.OutExpo) else: anim_curve.setType(QEasingCurve.InOutExpo) animation.setEasingCurve(anim_curve) animation.setStartValue(QPoint(pos.x(), pos.y() + start)) animation.setEndValue(QPoint(pos.x(), pos.y() + end)) animation.start() if on_finished: animation.finished.connect(on_finished) return animation
def _animate_expand(self, value): size_anim = QPropertyAnimation(self, 'geometry') geometry = self.geometry() width = geometry.width() x, y, _, _ = geometry.getCoords() size_start = QRect(x, y, width, int(not (value)) * 150) size_end = QRect(x, y, width, value * 150) size_anim.setStartValue(size_start) size_anim.setEndValue(size_end) size_anim.setDuration(300) size_anim_curve = QEasingCurve() if value: size_anim_curve.setType(QEasingCurve.InQuad) else: size_anim_curve.setType(QEasingCurve.OutQuad) size_anim.setEasingCurve(size_anim_curve) # =================================================== Animation Sequence self._animation = QSequentialAnimationGroup() self._animation.addAnimation(size_anim) size_anim.valueChanged.connect(self._force_resize) if not value: self._animation.finished.connect(self.delete_widget) self._animation.start(QAbstractAnimation.DeleteWhenStopped)
def __init__(self, target, duration, parent=None): super(OpacityEffect, self).__init__(parent=parent) self._target = target self._duration = duration self._animation = QPropertyAnimation(self._target, "opacity") self._animation.setStartValue(0.0) self._animation.setEndValue(0.0)
def __init__(self, text, duration=None, theme_type=None, closable=False, parent=None): self._text = text self._duration = duration self._theme_type = theme_type self._closable = closable super(PopupMessage, self).__init__(parent=parent) self.setAttribute(Qt.WA_TranslucentBackground) close_timer = QTimer(self) close_timer.setSingleShot(True) close_timer.timeout.connect(self.close) close_timer.timeout.connect(self.closed) close_timer.setInterval( (duration or self.DEFAULT_CONFIG['duration']) * 1000) anim_timer = QTimer(self) anim_timer.timeout.connect(self._on_fade_out) anim_timer.setInterval((duration or self.DEFAULT_CONFIG['duration']) * 1000 - 300) close_timer.start() anim_timer.start() self._pos_anim = QPropertyAnimation(self) self._pos_anim.setTargetObject(self) self._pos_anim.setEasingCurve(QEasingCurve.OutCubic) self._pos_anim.setDuration(300) self._pos_anim.setPropertyName(b'pos') self._opacity_anim = QPropertyAnimation() self._opacity_anim.setTargetObject(self) self._opacity_anim.setEasingCurve(QEasingCurve.OutCubic) self._opacity_anim.setDuration(300) self._opacity_anim.setPropertyName(b'windowOpacity') self._opacity_anim.setStartValue(0.0) self._opacity_anim.setEndValue(1.0) self._set_proper_position(parent) self._fade_in()
def __init__(self, title, position=SliderPanelPositions.RIGHT, closable=True, parent=None): self._title = title self._position = position self._closable = closable self._is_first_close = True super(SliderPanel, self).__init__(parent) self.setObjectName('sliderPanel') self.setWindowFlags(Qt.Popup) self.setAttribute(Qt.WA_StyledBackground) self._close_timer = QTimer(self) self._close_timer.setInterval(300) self._close_timer.setSingleShot(True) self._close_timer.timeout.connect(self.close) self._close_timer.timeout.connect(self.closed.emit) self._pos_anim = QPropertyAnimation(self) self._pos_anim.setTargetObject(self) self._pos_anim.setEasingCurve(QEasingCurve.OutCubic) self._pos_anim.setDuration(300) self._pos_anim.setPropertyName(b'pos') self._opacity_anim = QPropertyAnimation() self._opacity_anim.setTargetObject(self) self._opacity_anim.setDuration(300) self._opacity_anim.setEasingCurve(QEasingCurve.OutCubic) self._opacity_anim.setPropertyName(b'windowOpacity') self._opacity_anim.setStartValue(0.0) self._opacity_anim.setEndValue(1.0)
def __init__(self, size=None, color=None, speed=1, parent=None): super(CircleLoading, self).__init__(parent=parent) size = size or self.theme_default_size() self.setFixedSize(QSize(size, size)) self._rotation = 0 self._loading_pixmap = resources.pixmap( 'loading', extension='svg', color=color or self.accent_color()).scaledToWidth(size, Qt.SmoothTransformation) self._loading_anim = QPropertyAnimation() self._loading_anim.setTargetObject(self) self._loading_anim.setDuration(1000 * (1 / speed)) self._loading_anim.setPropertyName('rotation') self._loading_anim.setStartValue(0) self._loading_anim.setEndValue(360) self._loading_anim.setLoopCount(-1) self._loading_anim.start()
def property_animation(start=[0, 0], end=[30, 0], duration=300, object=None, property='iconSize', on_finished=None): """ Functions that returns a ready to use QPropertyAnimation :param start: int, animation start value :param end: int, animation end value :param duration: int, duration of the effect :param object: variant, QDialog || QMainWindow :param property: str, object property to animate :param on_finished: variant, function to call when the animation is finished :return: QPropertyAnimation """ animation = QPropertyAnimation(object, property, object) anim_curve = QEasingCurve() anim_curve.setType(QEasingCurve.InOutQuint) animation.setEasingCurve(anim_curve) animation.setDuration(duration) animation.setStartValue(start) animation.setEndValue(end) animation.start() return animation
def fade_out_widget(widget, duration=200, on_finished=None): """ Fade out animation effect for widgets :param widget: QWidget, widget to apply effect :param duration: int, duration of the effect :param on_finished: variant, function to call when the animation is finished :return: QPropertyAnimation """ effect = QGraphicsOpacityEffect(widget) widget.setGraphicsEffect(effect) animation = QPropertyAnimation(effect, b'opacity') animation.setDuration(duration) animation.setStartValue(1.0) animation.setEndValue(0.0) animation.setEasingCurve(QEasingCurve.InOutCubic) animation.start() if on_finished: animation.finished.connect(on_finished) widget._fade_out_ = animation return animation
def ui(self): super(BaseToast, self).ui() self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog | Qt.WA_TranslucentBackground | Qt.WA_DeleteOnClose) self.setAttribute(Qt.WA_StyledBackground) self.setFixedSize(QSize(120, 120)) icon_layout = layouts.HorizontalLayout() icon_layout.addStretch() widget_theme = self.theme() if self._toast_type == self.ToastTypes.LOADING: icon_layout.addWidget( loading.CircleLoading(size=widget_theme.huge, color=widget_theme.text_color_inverse)) else: icon_label = avatar.Avatar() icon_label.theme_size = 60 icon_label.image = resources.pixmap( self._toast_type or self.ToastTypes.INFO, color=widget_theme.text_color_inverse) icon_layout.addWidget(icon_label) icon_layout.addStretch() content_label = label.BaseLabel() content_label.setText(self._text or '') content_label.setAlignment(Qt.AlignCenter) self.main_layout.addStretch() self.main_layout.addLayout(icon_layout) self.main_layout.addSpacing(10) self.main_layout.addWidget(content_label) self.main_layout.addStretch() close_timer = QTimer(self) close_timer.setSingleShot(True) close_timer.timeout.connect(self.close) close_timer.timeout.connect(self.toastClosed.emit) close_timer.setInterval( (self._duration or self.DEFAULT_CONFIG.get('duration', 2)) * 1000) anim_timer = QTimer(self) anim_timer.timeout.connect(self._fade_out) anim_timer.setInterval( (self._duration or self.DEFAULT_CONFIG.get('duration', 2)) * 1000 - 300) self._opacity_anim = QPropertyAnimation() self._opacity_anim.setTargetObject(self) self._opacity_anim.setDuration(300) self._opacity_anim.setEasingCurve(QEasingCurve.OutCubic) self._opacity_anim.setPropertyName('windowOpacity') self._opacity_anim.setStartValue(0.0) self._opacity_anim.setEndValue(0.9) close_timer.start() anim_timer.start() self._get_center_position(self._parent) self._fade_in()