I'm trying to create a collapsible side panel similar to the one in Qt Designer (See attached screenshot). They appear to be QListViews placed in some sort of collapsible widget.
I googled for "Qt collapsible panel" and it seems that there is no standard component for this, or at least not under that name. So, does anyone know whether any standard Qt component has the same behavior? If not, can anyone suggests how I can go about building it?
Thanks.
Try putting the button you want to hide and unhide in another layout. In that layout along with the button put a spacer. Call Button hide and spacer will take over. Spacer takes over hidden button's space.
Widgets are the primary elements for creating user interfaces in Qt. Widgets can display data and status information, receive user input, and provide a container for other widgets that should be grouped together. A widget that is not embedded in a parent widget is called a window.
Once you have add your layout with at least one widget in it, select your window and click the "Update" button of QtDesigner. The interface will be resized at the most optimized size and your layout will fit the whole window. Then when resizing the window, the layout will be resized in the same way.
I decided to follow the general approach laid out in the link provided by Joey.
Specifically, I created a widget for each collapsible list. This widget consists of a QPushButton at the top and a QListView at the bottom.
Then, I wired the button clicked signal to a handler to toggle the geometry of the QListView between having height of 0 when it is hidden and its original height when it reappears.
I find that this approach is much simpler compared to customizing the paint event as suggested by Claudio. Furthermore, I can use QAnimationProperty to animate the change in geometry to make the list appear to "slide" in and out of view.
But anyway thanks for the replies!
I created the collapsible panel. Here's the Code:
import os
import sys
from pathlib import Path
from PySide2.QtWidgets import QPushButton, QVBoxLayout, QApplication ,QListWidget, QListView, QLabel, QWidget, QAbstractItemView, QSplitter
from PySide2.QtGui import QStandardItemModel, QStandardItem, QIcon, Qt, QDrag
from PySide2 import QtCore
PATH = os.path.join('.','img_src')
print('LayerSelector Loaded with path:' , PATH)
class CustomQStandardItem(QStandardItem):
def __init__(self, icon, text):
super().__init__(icon, text)
def dropMimeData(self, data, action, row, column, parent):
pass
class LayersList(QWidget):
'''
LayerList class which acts as collapsable list.
'''
def __init__(self, name, layers, expand = True):
super().__init__()
self.currently_expanded = True
self.main_layout = QVBoxLayout()
self.main_layout.setMargin(0)
self.main_layout.setSpacing(0)
self.main_layout.setContentsMargins(0, 0, 0, 0)
self.expand_button = QPushButton(name)
self.expand_button.setToolTip(f"List of {name} Layers")
self.expand_button.setIcon(QIcon(os.path.join(PATH,'LayersList_Up.png')))
self.layer_list = QListView()
self.layer_list.setDragEnabled(True)
self.container_model = QStandardItemModel()
for l in layers:
qs = CustomQStandardItem(QIcon(os.path.join(PATH,'LayersList_Layer_Icon.png')),l)
self.container_model.appendRow(qs)
self.layer_list.setModel(self.container_model)
self.layer_list.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.main_layout.addWidget(self.expand_button,0, Qt.AlignTop)
self.main_layout.addWidget(self.layer_list, 0, Qt.AlignTop)
self.expand_button.clicked.connect(self.expand)
self.setLayout(self.main_layout)
self.resized_size = 16.5 * len(layers)
self.set_styling()
if not expand:
self.expand()
@QtCore.Slot()
def expand(self):
if self.currently_expanded:
self.layer_list.setMaximumHeight(0)
self.expand_button.setIcon(QIcon(os.path.join(PATH,'LayersList_Down.png')))
self.currently_expanded = False
else:
self.layer_list.setMaximumHeight(self.resized_size)
self.expand_button.setIcon(QIcon(os.path.join(PATH,'LayersList_Up.png')))
self.currently_expanded = True
def set_styling(self):
self.setStyleSheet("background-color:aliceblue ;")
self.expand_button.setStyleSheet("text-align:left;")
self.layer_list.setStyleSheet("background-color:aliceblue; border:1px solid;border-style: ridge;")
class LayersSelectorWidget(QWidget):
'''
LayerChoiceWidget class provide widget plugin for picking layers.
'''
def __init__(self):
super().__init__()
names = ['Core Layers',
'Convolution Layers',
'Pooling Layers',
'Recurrent Layers',
'Preprocessing Layers',
'Attention Layers',
'Reshaping Layers',
'Locally-Connected Layers'
]
layers = [
['Dense', 'Activation', 'Embedding', 'Masking', 'Lambda'],
['Conv1D', 'Conv2D', 'Conv3D', 'SeparableConv1D', 'SeparableConv2D', 'DepthwiseConv2D', 'Conv2DTranspose', 'Conv3Dtranspose'],
['MaxPooling1D', 'MaxPooling2D', 'MaxPooling3D', 'AveragePooling1D', 'AveragePooling2D', 'AveragePooling3D', 'GlobalMAxPooling1D', 'GlobalMAxPooling2D', 'GlobalMAxPooling3D', 'GlobalAveragePooling1D', 'GlobalAveragePooling2D', 'GlobalAveragePooling3D'],
['LSTM', 'GRU', 'SimpleRNN', 'TimeDistributed', 'BiDirectional', 'ConvLSTM2D'],
['TextToVector', 'Normalization'],
['Attention', 'AdditiveAttention'],
['Reshape', 'Flatten', 'Cropping1D', 'Cropping2D', 'Cropping3D', 'UpSampling1D', 'UpSampling2D', 'UpSampling3D', 'ZeroPadding1D', 'ZeroPadding2D', 'ZeroPadding3D'],
['LocallyConnected1D', 'LocallyConnected2D']
]
self.main_layout = QVBoxLayout()
for i in range(len(names)):
if i > 3:
self.main_layout.addWidget(LayersList(names[i], layers[i], False))
else:
self.main_layout.addWidget(LayersList(names[i], layers[i]))
self.main_layout.setSpacing(0)
self.main_layout.setAlignment(Qt.AlignTop)
self.main_layout.setMargin(0)
self.main_layout.setSpacing(0)
self.main_layout.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.main_layout)
del(names)
del(layers)
self.set_styling()
def set_styling(self):
self.setStyleSheet("background-color:aliceblue; border:0px solid;border-style: solid;")
Below is the result of above Code :
You can also play with set_styling
to change look and feel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With