class AspectRatioWidget(QWidget): '''Widget that keeps the aspect ratio of child widget on resize''' def __init__(self, widget, aspectRatio): super(AspectRatioWidget, self).__init__() self.layout = QBoxLayout(QBoxLayout.LeftToRight, self) self.layout.addItem(QSpacerItem(0, 0)) self.layout.addWidget(widget) self.layout.addItem(QSpacerItem(0, 0)) self.setAspectRatio(aspectRatio) def setAspectRatio(self, aspectRatio): self.aspectRatio = aspectRatio self.updateAspectRatio() def updateAspectRatio(self): newAspectRatio = self.size().width() / self.size().height() if newAspectRatio > self.aspectRatio: # Too wide self.layout.setDirection(QBoxLayout.LeftToRight) widgetStretch = self.height() * self.aspectRatio outerStretch = (self.width() - widgetStretch) / 2 + 0.5 else: # Too tall self.layout.setDirection(QBoxLayout.TopToBottom) widgetStretch = self.width() * (1 / self.aspectRatio) outerStretch = (self.height() - widgetStretch) / 2 + 0.5 self.layout.setStretch(0, outerStretch) self.layout.setStretch(1, widgetStretch) self.layout.setStretch(2, outerStretch) def resizeEvent(self, event): self.updateAspectRatio()
def __init__(self, algorithms): super(Window, self).__init__() self.stackedWidget = QStackedWidget() self.orientationCombo = QComboBox() for category in categories: pass for algorithm in algorithms: self.orientationCombo.addItem(algorithm.get_name()) self.stackedWidget.addWidget(GroupOfSliders(algorithm)) layout = QBoxLayout(QBoxLayout.TopToBottom) settings_layout = QBoxLayout(QBoxLayout.TopToBottom) settings_layout.addWidget(self.stackedWidget) select_layout = QBoxLayout(QBoxLayout.TopToBottom) select_layout.addWidget(self.orientationCombo) layout.addItem(settings_layout) layout.addItem(select_layout) self.setLayout(layout) self.setWindowTitle(algorithm.get_name() + " Settings")
def __init__(self, settings_obj, parent=None): super().__init__(parent) self.setupUi(self) self.source_obj = settings_obj if isinstance(settings_obj, list): self.type_ = type( settings_obj[0]) if len(settings_obj) > 0 else str [self.listWidget.addItem(str(t)) for t in settings_obj] self.listWidget.itemDoubleClicked.connect( self.on_item_double_clicked) self.dictGroupBox.hide() elif isinstance(settings_obj, dict): self.listGroupBox.hide() self.controls = {} layout = QBoxLayout(QBoxLayout.TopToBottom) for key, value in settings_obj.items(): control = QCheckBox(key, self) layout.addWidget(control) control.setChecked(value) self.controls[key] = control layout.addItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.dictGroupBox.setLayout(layout) self.addButton.clicked.connect(self.on_add_button_clicked) self.okButton.clicked.connect(self.on_ok_button_clicked)
class IconEditorPalette(QWidget): """ Class implementing a palette widget for the icon editor. @signal colorSelected(QColor) emitted after a new color has been selected @signal compositingChanged(QPainter.CompositionMode) emitted to signal a change of the compositing mode """ colorSelected = pyqtSignal(QColor) compositingChanged = pyqtSignal(QPainter.CompositionMode) def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(IconEditorPalette, self).__init__(parent) if self.layoutDirection == Qt.Horizontal: direction = QBoxLayout.LeftToRight else: direction = QBoxLayout.TopToBottom self.__layout = QBoxLayout(direction, self) self.setLayout(self.__layout) self.__preview = QLabel(self) self.__preview.setFrameStyle(QFrame.Panel | QFrame.Sunken) self.__preview.setFixedHeight(64) self.__preview.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.__preview.setWhatsThis( self.tr("""<b>Preview</b>""" """<p>This is a 1:1 preview of the current icon.</p>""")) self.__layout.addWidget(self.__preview) self.__color = QLabel(self) self.__color.setFrameStyle(QFrame.Panel | QFrame.Sunken) self.__color.setFixedHeight(24) self.__color.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.__color.setWhatsThis( self. tr("""<b>Current Color</b>""" """<p>This is the currently selected color used for drawing.</p>""" )) self.__layout.addWidget(self.__color) self.__colorTxt = QLabel(self) self.__colorTxt.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.__colorTxt.setWhatsThis( self.tr( """<b>Current Color Value</b>""" """<p>This is the currently selected color value used for""" """ drawing.</p>""")) self.__layout.addWidget(self.__colorTxt) self.__colorButton = QPushButton(self.tr("Select Color"), self) self.__colorButton.setWhatsThis( self.tr( """<b>Select Color</b>""" """<p>Select the current drawing color via a color selection""" """ dialog.</p>""")) self.__colorButton.clicked.connect(self.__selectColor) self.__layout.addWidget(self.__colorButton) self.__colorAlpha = QSpinBox(self) self.__colorAlpha.setRange(0, 255) self.__colorAlpha.setWhatsThis( self.tr( """<b>Select alpha channel value</b>""" """<p>Select the value for the alpha channel of the current""" """ color.</p>""")) self.__layout.addWidget(self.__colorAlpha) self.__colorAlpha.valueChanged[int].connect(self.__alphaChanged) self.__compositingGroup = QGroupBox(self.tr("Compositing"), self) self.__compositingGroupLayout = QVBoxLayout(self.__compositingGroup) self.__compositingGroup.setLayout(self.__compositingGroupLayout) self.__sourceButton = QRadioButton(self.tr("Replace"), self.__compositingGroup) self.__sourceButton.setWhatsThis( self.tr("""<b>Replace</b>""" """<p>Replace the existing pixel with a new color.</p>""")) self.__sourceButton.clicked[bool].connect(self.__compositingChanged) self.__compositingGroupLayout.addWidget(self.__sourceButton) self.__sourceOverButton = QRadioButton(self.tr("Blend"), self.__compositingGroup) self.__sourceOverButton.setWhatsThis( self.tr("""<b>Blend</b>""" """<p>Blend the new color over the existing pixel.</p>""")) self.__sourceOverButton.setChecked(True) self.__sourceOverButton.clicked[bool].connect( self.__compositingChanged) self.__compositingGroupLayout.addWidget(self.__sourceOverButton) self.__layout.addWidget(self.__compositingGroup) spacer = QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding) self.__layout.addItem(spacer) def previewChanged(self, pixmap): """ Public slot to update the preview. @param pixmap new preview pixmap (QPixmap) """ self.__preview.setPixmap(pixmap) def colorChanged(self, color): """ Public slot to update the color preview. @param color new color (QColor) """ self.__currentColor = color self.__currentAlpha = color.alpha() pm = QPixmap(90, 18) pm.fill(color) self.__color.setPixmap(pm) self.__colorTxt.setText("{0:d}, {1:d}, {2:d}, {3:d}".format( color.red(), color.green(), color.blue(), color.alpha())) self.__colorAlpha.setValue(self.__currentAlpha) def __selectColor(self): """ Private slot to select a new drawing color. """ col = QColorDialog.getColor(self.__currentColor) col.setAlpha(self.__currentAlpha) if col.isValid(): self.colorSelected.emit(col) def __alphaChanged(self, val): """ Private slot to track changes of the alpha channel. @param val value of the alpha channel """ if val != self.__currentAlpha: col = QColor(self.__currentColor) col.setAlpha(val) self.colorSelected.emit(col) def setCompositingMode(self, mode): """ Public method to set the compositing mode. @param mode compositing mode to set (QPainter.CompositionMode) """ if mode == QPainter.CompositionMode_Source: self.__sourceButton.setChecked(True) elif mode == QPainter.CompositionMode_SourceOver: self.__sourceOverButton.setChecked(True) def __compositingChanged(self, on): """ Private slot to handle a change of the compositing mode. @param on flag indicating the checked state of the compositing button (boolean) """ if on: if self.__sourceButton.isChecked(): self.compositingChanged.emit(QPainter.CompositionMode_Source) elif self.__sourceOverButton.isChecked(): self.compositingChanged.emit( QPainter.CompositionMode_SourceOver)
class NTFSLogFileDialog(QDialog, QObject): complete = pyqtSignal() def __init__(self, parent=None): QDialog.__init__(self, parent) QObject.__init__(self) self.selected_partition = -1 self.ui() def ui(self): self.setWindowTitle("Import File System Log File") self.setFixedSize(self.sizeHint()) self.layout = QBoxLayout(QBoxLayout.TopToBottom, self) spacer_item1 = QSpacerItem(10, 5) self.layout.addItem(spacer_item1) self.setLayout(self.layout) # First Group self.disk_raw_chk_box = QCheckBox( "In this case, it's possible to carve some files.", self) self.disk_raw_chk_box.stateChanged.connect( lambda: self.select_type(self.disk_raw_chk_box)) self.disk_raw_group_box = QGroupBox(self) self.disk_raw_group_box.setStyleSheet("margin-top: 0;") self.disk_raw_group_box.setDisabled(True) disk_raw_group_box_layout = QHBoxLayout(self.disk_raw_group_box) self.disk_raw_group_box.setLayout(disk_raw_group_box_layout) self.disk_raw_label = QLabel("Disk Raw: ", self) self.disk_raw_text_box = QLineEdit() self.disk_raw_text_box.setReadOnly(True) self.disk_raw_text_box.setFixedWidth(400) self.browse_disk_raw_btn = QPushButton("...", self) self.browse_disk_raw_btn.setFixedWidth(50) self.browse_disk_raw_btn.clicked.connect(self.btn_clicekd) self.browse_disk_raw_btn.setCursor(QCursor(Qt.PointingHandCursor)) disk_raw_group_box_layout.addWidget(self.disk_raw_label) disk_raw_group_box_layout.addWidget(self.disk_raw_text_box) disk_raw_group_box_layout.addWidget(self.browse_disk_raw_btn) self.layout.addWidget(self.disk_raw_chk_box) self.layout.addWidget(self.disk_raw_group_box) # Second Group self.ntfs_log_file_chk_box = QCheckBox( "In this case, NTFS Log analysis only supported.", self) self.ntfs_log_file_chk_box.stateChanged.connect( lambda: self.select_type(self.ntfs_log_file_chk_box)) self.ntfs_log_group_box = QGroupBox(self) self.ntfs_log_group_box.setStyleSheet("margin-top: 0;") self.ntfs_log_group_box.setDisabled(True) ntfs_log_group_box_layout = QGridLayout(self) self.ntfs_log_group_box.setLayout(ntfs_log_group_box_layout) self.mft_label = QLabel("$MFT: ", self) self.mft_path_text_box = QLineEdit(self) self.mft_path_text_box.setReadOnly(True) self.mft_path_text_box.setFixedWidth(400) self.browse_mft_btn = QPushButton("...", self) self.browse_mft_btn.setFixedWidth(50) self.browse_mft_btn.clicked.connect(self.btn_clicekd) self.browse_mft_btn.setCursor(QCursor(Qt.PointingHandCursor)) self.usnjrnl_label = QLabel("$UsnJrnl: ", self) self.usnjrnl_path_text_box = QLineEdit(self) self.usnjrnl_path_text_box.setReadOnly(True) self.usnjrnl_path_text_box.setFixedWidth(400) self.browse_usnjrnl_btn = QPushButton("...", self) self.browse_usnjrnl_btn.setFixedWidth(50) self.browse_usnjrnl_btn.clicked.connect(self.btn_clicekd) self.browse_usnjrnl_btn.setCursor(QCursor(Qt.PointingHandCursor)) self.logfile_label = QLabel("$LogFile: ", self) self.logfile_path_text_box = QLineEdit(self) self.logfile_path_text_box.setReadOnly(True) self.logfile_path_text_box.setFixedWidth(400) self.browse_logfile_btn = QPushButton("...", self) self.browse_logfile_btn.setFixedWidth(50) self.browse_logfile_btn.clicked.connect(self.btn_clicekd) self.browse_logfile_btn.setCursor(QCursor(Qt.PointingHandCursor)) ntfs_log_group_box_layout.addWidget(self.mft_label, 0, 0) ntfs_log_group_box_layout.addWidget(self.mft_path_text_box, 0, 1) ntfs_log_group_box_layout.addWidget(self.browse_mft_btn, 0, 2) ntfs_log_group_box_layout.addWidget(self.usnjrnl_label, 1, 0) ntfs_log_group_box_layout.addWidget(self.usnjrnl_path_text_box, 1, 1) ntfs_log_group_box_layout.addWidget(self.browse_usnjrnl_btn, 1, 2) ntfs_log_group_box_layout.addWidget(self.logfile_label, 2, 0) ntfs_log_group_box_layout.addWidget(self.logfile_path_text_box, 2, 1) ntfs_log_group_box_layout.addWidget(self.browse_logfile_btn, 2, 2) self.submit_btn = QPushButton("Submit", self) self.submit_btn.setFixedSize(100, 40) self.submit_btn.setCursor(QCursor(Qt.PointingHandCursor)) self.logging_label = QLabel("Loading...", self) self.logging_label.setFixedHeight(20) self.logging_label.setAlignment(Qt.AlignCenter) self.logging_label.hide() self.loading_bar = QProgressBar(self) self.loading_bar.setFixedHeight(10) self.loading_bar.setTextVisible(False) self.loading_bar.hide() self.bar_thread = LoadingBarThread(self) self.bar_thread.change_value.connect(self.loading_bar.setValue) self.spacer_item2 = QSpacerItem(10, 15) self.spacer_item3 = QSpacerItem(10, 20) self.layout.addItem(self.spacer_item2) self.layout.addWidget(self.ntfs_log_file_chk_box) self.layout.addWidget(self.ntfs_log_group_box) self.layout.addItem(self.spacer_item3) self.layout.addWidget(self.submit_btn, alignment=Qt.AlignHCenter) # self.setWindowModality(Qt.WindowModal) self.setWindowFlag(Qt.WindowCloseButtonHint | Qt.WindowModal) self.show() def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.close() def select_type(self, b): if b is self.disk_raw_chk_box: if b.isChecked(): self.ntfs_log_file_chk_box.setChecked(False) self.ntfs_log_group_box.setDisabled(True) self.disk_raw_group_box.setDisabled(False) else: self.disk_raw_group_box.setDisabled(True) else: if b.isChecked(): self.disk_raw_chk_box.setChecked(False) self.disk_raw_group_box.setDisabled(True) self.ntfs_log_group_box.setDisabled(False) else: self.ntfs_log_group_box.setDisabled(True) def btn_clicekd(self): sender = self.sender() fileName = QFileDialog.getOpenFileName(self) if sender is self.browse_disk_raw_btn: self.disk_raw_text_box.setText(fileName[0]) elif sender is self.browse_mft_btn: self.mft_path_text_box.setText(fileName[0]) elif sender is self.browse_usnjrnl_btn: self.usnjrnl_path_text_box.setText(fileName[0]) elif sender is self.browse_logfile_btn: self.logfile_path_text_box.setText(fileName[0]) def ready(self): self.submit_btn.hide() self.layout.removeWidget(self.submit_btn) self.layout.addWidget(self.logging_label, alignment=Qt.AlignBottom | Qt.AlignHCenter) self.layout.addWidget(self.loading_bar) self.logging_label.show() self.loading_bar.show() self.bar_thread.start() def resume(self): if self.bar_thread.cnt < 50: self.bar_thread.cnt = 100 return self.bar_thread.toggle_status() def change_interface(self, contents): from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem self.layout.removeWidget(self.disk_raw_chk_box) self.disk_raw_chk_box.hide() self.layout.removeWidget(self.disk_raw_group_box) self.disk_raw_group_box.hide() self.layout.removeItem(self.spacer_item2) self.layout.removeWidget(self.ntfs_log_file_chk_box) self.ntfs_log_file_chk_box.hide() self.layout.removeWidget(self.ntfs_log_group_box) self.ntfs_log_group_box.hide() self.layout.removeItem(self.spacer_item3) self.layout.removeWidget(self.submit_btn) self.disk_name_label = QLabel("Image Name:\t" + contents[0][0], self) self.disk_size_label = QLabel( "Image Size:\t{} Bytes".format(contents[0][1]), self) self.disk_size_label.setFixedHeight(20) self.disk_size_label.setAlignment(Qt.AlignVCenter) self.disk_part_label = QLabel("Partition:", self) self.disk_part_label.setFixedHeight(20) self.disk_part_label.setAlignment(Qt.AlignBottom) self.partition_tree = QTreeWidget(self) self.partition_tree.setHeaderLabels([ "Order", "File System", "Active", "Starting Offset", "Total Sector", "Size" ]) self.partition_tree.item_changed.connect(self.item_changed) self.partition_tree.resizeColumnToContents(2) self.partition_tree.resizeColumnToContents(3) self.partition_tree.resizeColumnToContents(4) self.partition_tree.headerItem().setTextAlignment(0, Qt.AlignCenter) self.partition_tree.headerItem().setTextAlignment(1, Qt.AlignCenter) self.partition_items = [] for row in range(1, 5): self.partition_tree.headerItem().setTextAlignment( row + 1, Qt.AlignCenter) item = QTreeWidgetItem(self.partition_tree) item.setText(0, str(row)) item.setTextAlignment(0, Qt.AlignLeft) if not contents[row]: item.setText(1, "None") item.setCheckState(0, Qt.Unchecked) item.setDisabled(True) continue for col in range(5): item.setText(col + 1, contents[row][col]) item.setTextAlignment(col + 1, Qt.AlignCenter) item.setTextAlignment(1, Qt.AlignLeft) item.setCheckState(0, Qt.Unchecked) self.partition_items.append(item) self.layout.addWidget(self.disk_name_label) self.layout.addWidget(self.disk_size_label) self.layout.addWidget(self.disk_part_label) self.layout.addWidget(self.partition_tree) self.layout.addItem(QSpacerItem(10, 10)) self.layout.addWidget(self.submit_btn, alignment=Qt.AlignCenter) def item_changed(self, changed_item, p_int): if changed_item.checkState(0) == Qt.Checked: self.selected_partition = int(changed_item.text(0)) for item in self.partition_items: if item is not changed_item: item.setCheckState(0, Qt.Unchecked)
class IconEditorPalette(QWidget): """ Class implementing a palette widget for the icon editor. @signal colorSelected(QColor) emitted after a new color has been selected @signal compositingChanged(QPainter.CompositionMode) emitted to signal a change of the compositing mode """ colorSelected = pyqtSignal(QColor) compositingChanged = pyqtSignal(QPainter.CompositionMode) def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(IconEditorPalette, self).__init__(parent) if self.layoutDirection == Qt.Horizontal: direction = QBoxLayout.LeftToRight else: direction = QBoxLayout.TopToBottom self.__layout = QBoxLayout(direction, self) self.setLayout(self.__layout) self.__preview = QLabel(self) self.__preview.setFrameStyle(QFrame.Panel | QFrame.Sunken) self.__preview.setFixedHeight(64) self.__preview.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.__preview.setWhatsThis(self.tr( """<b>Preview</b>""" """<p>This is a 1:1 preview of the current icon.</p>""" )) self.__layout.addWidget(self.__preview) self.__color = QLabel(self) self.__color.setFrameStyle(QFrame.Panel | QFrame.Sunken) self.__color.setFixedHeight(24) self.__color.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.__color.setWhatsThis(self.tr( """<b>Current Color</b>""" """<p>This is the currently selected color used for drawing.</p>""" )) self.__layout.addWidget(self.__color) self.__colorTxt = QLabel(self) self.__colorTxt.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.__colorTxt.setWhatsThis(self.tr( """<b>Current Color Value</b>""" """<p>This is the currently selected color value used for""" """ drawing.</p>""" )) self.__layout.addWidget(self.__colorTxt) self.__colorButton = QPushButton(self.tr("Select Color"), self) self.__colorButton.setWhatsThis(self.tr( """<b>Select Color</b>""" """<p>Select the current drawing color via a color selection""" """ dialog.</p>""" )) self.__colorButton.clicked.connect(self.__selectColor) self.__layout.addWidget(self.__colorButton) self.__colorAlpha = QSpinBox(self) self.__colorAlpha.setRange(0, 255) self.__colorAlpha.setWhatsThis(self.tr( """<b>Select alpha channel value</b>""" """<p>Select the value for the alpha channel of the current""" """ color.</p>""" )) self.__layout.addWidget(self.__colorAlpha) self.__colorAlpha.valueChanged[int].connect(self.__alphaChanged) self.__compositingGroup = QGroupBox(self.tr("Compositing"), self) self.__compositingGroupLayout = QVBoxLayout(self.__compositingGroup) self.__compositingGroup.setLayout(self.__compositingGroupLayout) self.__sourceButton = QRadioButton(self.tr("Replace"), self.__compositingGroup) self.__sourceButton.setWhatsThis(self.tr( """<b>Replace</b>""" """<p>Replace the existing pixel with a new color.</p>""" )) self.__sourceButton.clicked[bool].connect(self.__compositingChanged) self.__compositingGroupLayout.addWidget(self.__sourceButton) self.__sourceOverButton = QRadioButton(self.tr("Blend"), self.__compositingGroup) self.__sourceOverButton.setWhatsThis(self.tr( """<b>Blend</b>""" """<p>Blend the new color over the existing pixel.</p>""" )) self.__sourceOverButton.setChecked(True) self.__sourceOverButton.clicked[bool].connect( self.__compositingChanged) self.__compositingGroupLayout.addWidget(self.__sourceOverButton) self.__layout.addWidget(self.__compositingGroup) spacer = QSpacerItem( 10, 10, QSizePolicy.Minimum, QSizePolicy.Expanding) self.__layout.addItem(spacer) def previewChanged(self, pixmap): """ Public slot to update the preview. @param pixmap new preview pixmap (QPixmap) """ self.__preview.setPixmap(pixmap) def colorChanged(self, color): """ Public slot to update the color preview. @param color new color (QColor) """ self.__currentColor = color self.__currentAlpha = color.alpha() pm = QPixmap(90, 18) pm.fill(color) self.__color.setPixmap(pm) self.__colorTxt.setText( "{0:d}, {1:d}, {2:d}, {3:d}".format( color.red(), color.green(), color.blue(), color.alpha())) self.__colorAlpha.setValue(self.__currentAlpha) def __selectColor(self): """ Private slot to select a new drawing color. """ col = QColorDialog.getColor(self.__currentColor) col.setAlpha(self.__currentAlpha) if col.isValid(): self.colorSelected.emit(col) def __alphaChanged(self, val): """ Private slot to track changes of the alpha channel. @param val value of the alpha channel """ if val != self.__currentAlpha: col = QColor(self.__currentColor) col.setAlpha(val) self.colorSelected.emit(col) def setCompositingMode(self, mode): """ Public method to set the compositing mode. @param mode compositing mode to set (QPainter.CompositionMode) """ if mode == QPainter.CompositionMode_Source: self.__sourceButton.setChecked(True) elif mode == QPainter.CompositionMode_SourceOver: self.__sourceOverButton.setChecked(True) def __compositingChanged(self, on): """ Private slot to handle a change of the compositing mode. @param on flag indicating the checked state of the compositing button (boolean) """ if on: if self.__sourceButton.isChecked(): self.compositingChanged.emit( QPainter.CompositionMode_Source) elif self.__sourceOverButton.isChecked(): self.compositingChanged.emit( QPainter.CompositionMode_SourceOver)
def ui(self): central_widget = QWidget() layout = QBoxLayout(QBoxLayout.TopToBottom) central_widget.setLayout(layout) first_row_layout = QBoxLayout(QBoxLayout.LeftToRight) second_row_layout = QBoxLayout(QBoxLayout.LeftToRight) third_row_layout = QBoxLayout(QBoxLayout.LeftToRight) btn_desc_group = QGroupBox(self) btn_desc_group.setLayout(first_row_layout) btn_desc_group.setFixedHeight(80) menu_desc_group1 = QGroupBox(self) menu_desc_group1.setFixedHeight(400) # menu_desc_group1.setMaximumWidth(self.max_width_of_group_box) menu_desc_group_layout1 = QGridLayout() menu_desc_group1.setLayout(menu_desc_group_layout1) menu_desc_group2 = QGroupBox(self) # menu_desc_group2.setMaximumWidth(self.max_width_of_group_box) menu_desc_group_layout2 = QGridLayout() menu_desc_group2.setLayout(menu_desc_group_layout2) menu_desc_group3 = QGroupBox(self) menu_desc_group3.setFixedHeight(300) # menu_desc_group3.setMaximumWidth(self.max_width_of_group_box) menu_desc_group_layout3 = QGridLayout() menu_desc_group3.setLayout(menu_desc_group_layout3) menu_desc_group4 = QGroupBox(self) # menu_desc_group4.setMaximumWidth(self.max_width_of_group_box) menu_desc_group_layout4 = QGridLayout() menu_desc_group4.setLayout(menu_desc_group_layout4) second_row_layout.addWidget(menu_desc_group1) second_row_layout.addWidget(menu_desc_group2) third_row_layout.addWidget(menu_desc_group3) third_row_layout.addWidget(menu_desc_group4) layout.addWidget(btn_desc_group) layout.addLayout(second_row_layout) layout.addLayout(third_row_layout) import os cwd = os.getcwd() title_font = QFont("Times New Roman", 10) title_font.setBold(True) btn_img_label1 = QLabel(self) btn_img_label1.setPixmap(QPixmap(cwd + self.btn_img_path[0])) btn_title_label1 = QLabel(self.btn_title[0], self) btn_title_label1.setFont(title_font) btn_desc_label1 = QLabel(self.btn_desc[0], self) btn_img_label2 = QLabel(self) btn_img_label2.setPixmap(QPixmap(cwd + self.btn_img_path[1])) btn_title_label2 = QLabel(self.btn_title[1], self) btn_title_label2.setFont(title_font) btn_desc_label2 = QLabel(self.btn_desc[1], self) first_row_layout.addWidget(btn_img_label1, alignment=Qt.AlignCenter) first_row_layout.addWidget(btn_title_label1) first_row_layout.addWidget(btn_desc_label1) first_row_layout.addItem(QSpacerItem(10, 5)) first_row_layout.addWidget(btn_img_label2, alignment=Qt.AlignCenter) first_row_layout.addWidget(btn_title_label2) first_row_layout.addWidget(btn_desc_label2) menu_img_label1 = QLabel(self) menu_img_label1.setPixmap(QPixmap(cwd + self.menu_img_path[0])) total = len(self.menu_title[0]) menu_desc_group_layout1.addWidget(menu_img_label1, 0, 0, total, 1, Qt.AlignCenter) for i in range(total): title_label = QLabel(" {}".format(self.menu_title[0][i]), self) title_label.setFixedWidth(120) title_label.setFont(title_font) desc_label = QLabel(self.menu_desc[0][i], self) menu_desc_group_layout1.addWidget(title_label, i, 1) menu_desc_group_layout1.addWidget(desc_label, i, 2) menu_img_label2 = QLabel(self) menu_img_label2.setPixmap(QPixmap(cwd + self.menu_img_path[1])) menu_desc_group_layout2.addWidget(menu_img_label2, 0, 0, 2, 1, Qt.AlignCenter) title_label = QLabel(" {}".format(self.menu_title[1][0]), self) title_label.setFixedWidth(150) title_label.setFont(title_font) desc_label = QLabel(self.menu_desc[1][0], self) menu_desc_group_layout2.addWidget(title_label, 0, 1, Qt.AlignCenter) menu_desc_group_layout2.addWidget(desc_label, 1, 1, Qt.AlignTop | Qt.AlignHCenter) menu_img_label3 = QLabel(self) menu_img_label3.setPixmap(QPixmap(cwd + self.menu_img_path[2])) total = len(self.menu_title[2]) menu_desc_group_layout3.addWidget(menu_img_label3, 0, 0, total, 1, Qt.AlignCenter) for i in range(total): title_label = QLabel(" {}".format(self.menu_title[2][i]), self) title_label.setFixedWidth(150) title_label.setFont(title_font) desc_label = QLabel(self.menu_desc[2][i], self) menu_desc_group_layout3.addWidget(title_label, i, 1) menu_desc_group_layout3.addWidget(desc_label, i, 2) menu_img_label4 = QLabel(self) menu_img_label4.setPixmap(QPixmap(cwd + self.menu_img_path[3])) total = len(self.menu_title[3]) menu_desc_group_layout4.addWidget(menu_img_label4, 0, 0, total, 1, Qt.AlignCenter) for i in range(total): title_label = QLabel(" {}".format(self.menu_title[3][i]), self) title_label.setFixedWidth(100) title_label.setFont(title_font) desc_label = QLabel(self.menu_desc[3][i], self) menu_desc_group_layout4.addWidget(title_label, i, 1) menu_desc_group_layout4.addWidget(desc_label, i, 2) scroll = QScrollArea() scroll.setWidget(central_widget) scroll.setWidgetResizable(True) central_layout = QVBoxLayout(self) central_layout.addWidget(scroll) self.show()