Skip to content

Instantly share code, notes, and snippets.

@Patitotective
Last active September 12, 2021 19:39
Show Gist options
  • Save Patitotective/0a9cd57dfeb448fd77c148bd9b7b2ed8 to your computer and use it in GitHub Desktop.
Save Patitotective/0a9cd57dfeb448fd77c148bd9b7b2ed8 to your computer and use it in GitHub Desktop.
Collapsible widget using PyQt5.
import sys
from PyQt5.QtWidgets import QFrame, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QPushButton, QApplication, QMainWindow
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
import collapsible_widget_resources
VERTICAL_ARROW_PATH = ":/vertical_arrow_collapsible.png"
HORIZONTAL_ARROW_PATH = ":/horizontal_arrow_collapsible.png"
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setStyleSheet("background-color: #dcdee0;")
self.setCentralWidget(MainWidget())
self.show()
class MainWidget(QWidget):
def __init__(self):
super().__init__()
self.setLayout(QVBoxLayout())
self.layout().setSpacing(0)
# The below line will make that when you collapse a widget
# and uncollapse it kept it's position (at the top).
self.layout().setAlignment(Qt.AlignTop)
collapsible_widget2 = CollapsibleWidget(title="Nested collapsible widget")
collapsible_widget2.addWidget(QPushButton('c'))
collapsible_widget2.addWidget(QPushButton('d'))
collapsible_widget2.addWidget(QPushButton('e'))
collapsible_widget1 = CollapsibleWidget(title="Collapsible ")
collapsible_widget1.addWidget(QPushButton('a'))
collapsible_widget1.addWidget(QPushButton('b'))
collapsible_widget1.addWidget(collapsible_widget2)
self.layout().addWidget(collapsible_widget1)
class CollapsibleWidget(QWidget):
def __init__(self, parent=None, title=None):
super().__init__()
self.is_collasped = True
self.title_frame = self.CollapseButton(title, self.is_collasped)
self.title_frame.clicked.connect(self.toggle_collapsed)
self.setLayout(QVBoxLayout())
self.layout().addWidget(self.title_frame)
self.layout().addWidget(self.init_content())
def init_content(self):
self.content = QWidget()
self.content_layout = QVBoxLayout()
self.content.setLayout(self.content_layout)
self.content.setVisible(not self.is_collasped)
return self.content
def addWidget(self, widget):
self.content_layout.addWidget(widget)
def toggle_collapsed(self):
self.content.setVisible(self.is_collasped)
self.is_collasped = not self.is_collasped
self.title_frame.update_arrow(self.is_collasped)
class CollapseButton(QPushButton):
def __init__(self, title="", is_collasped=True, parent=None):
super().__init__()
self.setText(title)
self.update_arrow()
self.setStyleSheet(
"""
*{
padding: 3px 5px 3px 5px;
text-align: left;
border: none;
background-color: #dcdee0;
}
*:hover {
background-color: #c7cccf;
}
"""
)
def update_arrow(self, is_collasped=True):
if is_collasped:
self.setIcon(QIcon(HORIZONTAL_ARROW_PATH))
elif not is_collasped:
self.setIcon(QIcon(VERTICAL_ARROW_PATH))
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = MainWindow()
sys.exit(app.exec_())
# -*- coding: utf-8 -*-
# Resource object code
#
# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore
qt_resource_data = b"\
\x00\x00\x01\x05\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x0a\x00\x00\x00\x0c\x08\x06\x00\x00\x00\x5b\x6b\x2c\xa0\
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x03\x41\x00\x00\x03\x41\
\x01\xf4\xad\x15\xed\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x00\x92\x49\x44\
\x41\x54\x18\x95\x63\x68\x6a\xef\xd9\xdc\xd0\xde\xaf\xc4\x40\x00\
\x30\x31\x30\xfc\xf7\x61\x62\xf8\x73\xa5\xb1\xbd\xbb\xa1\xa1\xa1\
\x81\x03\x8f\x42\x06\x06\x06\x06\x06\x4e\x46\x06\x86\x7a\x26\x76\
\xae\xab\x8d\x1d\xdd\xbe\xf8\x14\x42\x01\xa3\x12\xe3\x7f\x86\x4d\
\xd8\x9c\x83\xa6\x10\x06\x30\x9d\xc3\xd8\xd4\xde\xfd\x1f\xbf\x37\
\xfe\xdf\xfb\xcf\xc8\x58\x80\xc3\x44\x82\x6e\x44\x01\xdf\xff\x33\
\x30\x34\xfe\xfb\xf9\x4d\xbb\xbe\xa2\x74\x33\x0b\x76\x35\x8c\x5b\
\xfe\x31\x30\xe7\x37\x54\x16\xde\x83\x89\xa0\x29\x84\xb8\xa7\xbe\
\xa2\x64\x33\x2e\xab\x51\xac\xc1\x66\x07\x0b\x36\x6b\xb0\x01\x00\
\x91\xc1\x3e\x36\x80\xc9\x33\x6d\x00\x00\x00\x00\x49\x45\x4e\x44\
\xae\x42\x60\x82\
\x00\x00\x01\x06\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x0c\x00\x00\x00\x0a\x08\x06\x00\x00\x00\x80\x2c\xbf\xfa\
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x03\x41\x00\x00\x03\x41\
\x01\xf4\xad\x15\xed\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x00\x93\x49\x44\
\x41\x54\x18\x95\x8d\x90\x31\x0e\x83\x30\x14\x43\x5f\x02\x52\xa7\
\xde\xac\xf4\x2a\x40\xa4\x0e\x59\xaa\xd0\xa5\x44\xf4\x36\xb9\x4f\
\x6e\x51\x41\x07\x92\x2e\x45\x40\x45\x04\xde\xbe\x6c\x7f\xcb\x16\
\x8f\xe7\xcb\x41\xbc\x70\x0c\x4e\x06\xb2\x12\x18\x0e\x88\xfb\x40\
\x5e\x49\xa3\x6b\x1f\xc1\xee\xa9\x05\x58\xa3\x6b\x2f\x01\xce\xa7\
\xcc\x42\xf4\x69\x79\xf4\xe3\xe7\x6d\x01\x24\x80\x52\xaa\x8f\x42\
\x54\xc9\xef\x91\xd2\x18\x33\xfc\x92\x66\x24\x06\x70\x77\x7d\xbb\
\x4e\x87\x5c\x32\x1b\x03\xf4\x81\x7c\x95\xbc\x32\xfc\x0f\x30\x15\
\x4d\x1a\x60\x39\xc0\x5c\x74\x17\x4d\xdb\x15\x4d\xdb\x15\x5b\xdc\
\x17\x1e\xf1\x3c\x40\x7b\xf0\x04\x56\x00\x00\x00\x00\x49\x45\x4e\
\x44\xae\x42\x60\x82\
"
qt_resource_name = b"\
\x00\x20\
\x01\xe2\x83\x87\
\x00\x68\
\x00\x6f\x00\x72\x00\x69\x00\x7a\x00\x6f\x00\x6e\x00\x74\x00\x61\x00\x6c\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\
\x00\x63\x00\x6f\x00\x6c\x00\x6c\x00\x61\x00\x70\x00\x73\x00\x69\x00\x62\x00\x6c\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x1e\
\x02\x1a\xb7\x87\
\x00\x76\
\x00\x65\x00\x72\x00\x74\x00\x69\x00\x63\x00\x61\x00\x6c\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x63\x00\x6f\
\x00\x6c\x00\x6c\x00\x61\x00\x70\x00\x73\x00\x69\x00\x62\x00\x6c\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
"
qt_resource_struct_v1 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x00\x46\x00\x00\x00\x00\x00\x01\x00\x00\x01\x09\
"
qt_resource_struct_v2 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x7b\xdb\x45\x59\x4c\
\x00\x00\x00\x46\x00\x00\x00\x00\x00\x01\x00\x00\x01\x09\
\x00\x00\x01\x7b\xdb\x45\x95\x3c\
"
qt_version = [int(v) for v in QtCore.qVersion().split('.')]
if qt_version < [5, 8, 0]:
rcc_version = 1
qt_resource_struct = qt_resource_struct_v1
else:
rcc_version = 2
qt_resource_struct = qt_resource_struct_v2
def qInitResources():
QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources():
QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources()
@Patitotective
Copy link
Author

Patitotective commented Sep 12, 2021

Remember to download both files collapsible_widget.py and collapsible_widget_resources.py.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment