def __init__(self, parent=None, title='', animationDuration=300): """ References: # Adapted from c++ version http://stackoverflow.com/questions/32476006/how-to-make-an-expandable-collapsable-section-widget-in-qt """ super(Spoiler, self).__init__(parent=parent) self.animationDuration = 300 self.toggleAnimation = QtCore.QParallelAnimationGroup() self.contentArea = QtWidgets.QScrollArea() self.headerLine = QtWidgets.QFrame() self.toggleButton = QtWidgets.QToolButton() self.mainLayout = QtWidgets.QGridLayout() toggleButton = self.toggleButton toggleButton.setStyleSheet("QToolButton { border: none; }") toggleButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) toggleButton.setArrowType(QtCore.Qt.RightArrow) toggleButton.setText(str(title)) toggleButton.setCheckable(True) toggleButton.setChecked(False) headerLine = self.headerLine headerLine.setFrameShape(QtWidgets.QFrame.HLine) headerLine.setFrameShadow(QtWidgets.QFrame.Sunken) headerLine.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum) self.contentArea.setStyleSheet("QScrollArea { background-color: white; border: none; }") self.contentArea.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) # start out collapsed self.contentArea.setMaximumHeight(0) self.contentArea.setMinimumHeight(0) # let the entire widget grow and shrink with its content toggleAnimation = self.toggleAnimation toggleAnimation.addAnimation(QtCore.QPropertyAnimation(self, b"minimumHeight")) toggleAnimation.addAnimation(QtCore.QPropertyAnimation(self, b"maximumHeight")) toggleAnimation.addAnimation(QtCore.QPropertyAnimation(self.contentArea, b"maximumHeight")) # don't waste space mainLayout = self.mainLayout mainLayout.setVerticalSpacing(0) mainLayout.setContentsMargins(0, 0, 0, 0) row = 0 mainLayout.addWidget(self.toggleButton, row, 0, 1, 1, QtCore.Qt.AlignLeft) mainLayout.addWidget(self.headerLine, row, 2, 1, 1) row += 1 mainLayout.addWidget(self.contentArea, row, 0, 1, 3) self.setLayout(self.mainLayout) def start_animation(checked): arrow_type = QtCore.Qt.DownArrow if checked else QtCore.Qt.RightArrow direction = QtCore.QAbstractAnimation.Forward if checked else QtCore.QAbstractAnimation.Backward toggleButton.setArrowType(arrow_type) self.toggleAnimation.setDirection(direction) self.toggleAnimation.start() self.toggleButton.clicked.connect(start_animation)
def toggle(self, widget, visible): """ desc: Toggles the visibility of a widget with a smooth animation. arguments: widget: A QWidget. visible: A boolean indicating the visibility of the widget. """ if visible and widget.isVisible() and \ widget.maximumHeight() == widget.bestHeight: return if not visible and \ (not widget.isVisible() or widget.maximumHeight() == 0): return if not visible: widget.setMaximumHeight(0) else: widget.setMaximumHeight(widget.bestHeight) widget.show() a = QtCore.QPropertyAnimation(widget, QtCore.QByteArray().append('maximumHeight'), widget) if not visible: a.setStartValue(widget.bestHeight) a.setEndValue(0) else: a.setStartValue(0) a.setEndValue(widget.bestHeight) a.setDuration(100) a.start()
def __init_graphic_effects(self): """ Initializes graphic effects. """ # Opacityeffect for fade in/out self.opacityEffect = QtWidgets.QGraphicsOpacityEffect(self) # Fade in animation self.fadeInAnimation = QtCore.QPropertyAnimation( self.opacityEffect, safe_encode("opacity")) self.fadeInAnimation.setStartValue(0.0) self.fadeInAnimation.setEndValue(1.0) # Fade out animation self.fadeOutAnimation = QtCore.QPropertyAnimation( self.opacityEffect, safe_encode("opacity")) self.fadeOutAnimation.setStartValue(1.0) self.fadeOutAnimation.setEndValue(0.0)
def mouseReleaseEvent(self, event): super().mouseReleaseEvent(event) if event.button() == QtCore.Qt.LeftButton: anim = QtCore.QPropertyAnimation(self, b'thumb_position', self) anim.setDuration(200) anim.setStartValue(self._thumb_position) anim.setEndValue(self._thumb_end) anim.start()
def showEvent(self, ev): super().showEvent(ev) if self.__animation is None: self.__animation = QtCore.QPropertyAnimation( self, b'indicator_position', self) self.__animation.setDuration(self._cycle_time_ms) self.__animation.setStartValue(0) self.__animation.setEndValue(-5760) self.__animation.setLoopCount(-1) self.__animation.start()
def frame_eventFilter(self, object, event): if event.type() == QtCore.QEvent.HoverEnter: self.anim = QtCore.QPropertyAnimation(self.label, b"geometry") self.anim.setDuration(100) self.anim.setStartValue( QtCore.QRect(0, 0, self.base_size, self.base_size * 0.2)) self.anim.setEndValue( QtCore.QRect(0, 0, self.base_size, self.base_size - self.top_bar_widget.height())) self.anim.start() elif event.type() == QtCore.QEvent.HoverLeave: self.anim = QtCore.QPropertyAnimation(self.label, b"geometry") self.anim.setDuration(100) self.anim.setStartValue( QtCore.QRect(0, 0, self.base_size, self.base_size - self.top_bar_widget.height())) self.anim.setEndValue( QtCore.QRect(0, 0, self.base_size, self.base_size * 0.2)) self.anim.start() return super(QtWidgets.QPushButton, self.frame).eventFilter(object, event)
def __init__(self, title="", parent=None): super(CollapsibleBox, self).__init__(parent) self.toggle_button = QtWidgets.QToolButton( text=title, checkable=True, checked=False ) self.toggle_button.setStyleSheet("QToolButton { border: none; }") self.toggle_button.setToolButtonStyle( QtCore.Qt.ToolButtonTextBesideIcon ) self.toggle_button.setArrowType(QtCore.Qt.RightArrow) self.toggle_button.pressed.connect(self.on_pressed) self.toggle_animation = QtCore.QParallelAnimationGroup(self) self.content_area = QtWidgets.QScrollArea( maximumHeight=0, minimumHeight=0 ) self.content_area.setSizePolicy( QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed ) self.content_area.setFrameShape(QtWidgets.QFrame.NoFrame) lay = QtWidgets.QVBoxLayout(self) lay.setSpacing(0) lay.setContentsMargins(0, 0, 0, 0) lay.addWidget(self.toggle_button) lay.addWidget(self.content_area) self.toggle_animation.addAnimation( QtCore.QPropertyAnimation(self, b"minimumHeight") ) self.toggle_animation.addAnimation( QtCore.QPropertyAnimation(self, b"maximumHeight") ) self.toggle_animation.addAnimation( QtCore.QPropertyAnimation(self.content_area, b"maximumHeight") )
def _animate(self, closing=False, duration=100): bh = self.bar.height() start_value = QtCore.QSize(0, bh) end_width = self._get_optimal_width() end_value = QtCore.QSize(end_width, bh) if closing: start_value = QtCore.QSize(self.width(), bh) end_value = QtCore.QSize(0, bh) self._animation = QtCore.QPropertyAnimation(self, b"size") self._animation.setStartValue(start_value) self._animation.setEndValue(end_value) self._animation.setDuration(duration) self._animation.start()
def popup(self): """popup and animate""" self.button.setDown(True) rect = self.button.rect() bottom_left = rect.bottomLeft() g = self.button.mapToGlobal(bottom_left) x, y = g.x(), g.y() size = self.sizeHint() width = rect.width() self.setGeometry(x, y, width, 0) start = QtCore.QRect(x, y, width, 0) stop = QtCore.QRect(x, y, size.width(), size.height()) self.animation = QtCore.QPropertyAnimation(self, "geometry".encode('utf-8')) self.animation.setDuration(ANIMATION_SPEED) self.animation.setEasingCurve(QtCore.QEasingCurve.InOutQuint) self.animation.setStartValue(start) self.animation.setEndValue(stop) self.show() self.animation.start()