Skip to content

Instantly share code, notes, and snippets.

@davidlatwe
Created June 23, 2021 08:32
Show Gist options
  • Save davidlatwe/b6dbc5144b360f51eddb8443705b5e1e to your computer and use it in GitHub Desktop.
Save davidlatwe/b6dbc5144b360f51eddb8443705b5e1e to your computer and use it in GitHub Desktop.
Qt widget: Page sliding
import os
import sys
from Qt5 import QtCore, QtWidgets
from . import widgets
class Foo(QtWidgets.QWidget):
bar_clicked = QtCore.Signal()
def __init__(self, parent=None):
super(Foo, self).__init__(parent=parent)
btn = QtWidgets.QPushButton("Bar")
btn.clicked.connect(self.bar_clicked.emit)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(btn)
class Bar(QtWidgets.QWidget):
foo_clicked = QtCore.Signal()
def __init__(self, parent=None):
super(Bar, self).__init__(parent=parent)
btn = QtWidgets.QPushButton("Foo")
btn.clicked.connect(self.foo_clicked.emit)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(btn)
class Window(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent=parent)
foo = view.Foo()
bar = view.Bar()
slider = widgets.SlidePageWidget()
slider.addWidget(foo)
slider.addWidget(bar)
foo.bar_clicked.connect(lambda: self.set_page(1))
bar.foo_clicked.connect(lambda: self.set_page(0))
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(slider)
self.slider = slider
self._page = 0
def set_page(self, page):
current = self.slider.currentIndex()
if current == page and self._page == page:
return
direction = "right" if page > current else "left"
self._page = page
self.slider.slide_view(page, direction=direction)
def init():
if sys.platform == "darwin":
os.environ["QT_MAC_WANTS_LAYER"] = "1" # MacOS BigSur
qapp = QtWidgets.QApplication.instance() or QtWidgets.QApplication([])
window = Window()
return qapp, window
def main():
qapp, window = init()
window.show()
return qapp.exec_()
from Qt5 import QtCore, QtWidgets
class SlidePageWidget(QtWidgets.QStackedWidget):
"""Stacked widget that nicely slides between its pages"""
directions = {
"left": QtCore.QPoint(-1, 0),
"right": QtCore.QPoint(1, 0),
"up": QtCore.QPoint(0, 1),
"down": QtCore.QPoint(0, -1)
}
def slide_view(self, index, direction="right"):
if self.currentIndex() == index:
return
offset_direction = self.directions.get(direction)
if offset_direction is None:
print("BUG: invalid slide direction: {}".format(direction))
return
width = self.frameRect().width()
height = self.frameRect().height()
offset = QtCore.QPoint(
offset_direction.x() * width,
offset_direction.y() * height
)
new_page = self.widget(index)
new_page.setGeometry(0, 0, width, height)
curr_pos = new_page.pos()
new_page.move(curr_pos + offset)
new_page.show()
new_page.raise_()
current_page = self.currentWidget()
b_pos = QtCore.QByteArray(b"pos")
anim_old = QtCore.QPropertyAnimation(current_page, b_pos, self)
anim_old.setDuration(250)
anim_old.setStartValue(curr_pos)
anim_old.setEndValue(curr_pos - offset)
anim_old.setEasingCurve(QtCore.QEasingCurve.OutQuad)
anim_new = QtCore.QPropertyAnimation(new_page, b_pos, self)
anim_new.setDuration(250)
anim_new.setStartValue(curr_pos + offset)
anim_new.setEndValue(curr_pos)
anim_new.setEasingCurve(QtCore.QEasingCurve.OutQuad)
anim_group = QtCore.QParallelAnimationGroup(self)
anim_group.addAnimation(anim_old)
anim_group.addAnimation(anim_new)
def slide_finished():
self.setCurrentWidget(new_page)
anim_group.finished.connect(slide_finished)
anim_group.start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment