Qt分享一个壁纸页面布局的方式

分享一个壁纸软件的设计思路

QScrollArea中添加一个总体的垂直布局,创建若干个水平布局,使用垂直布局组合,具体如图。在添加QAbstractButton时设置button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)属性,它会根据窗口大小自动调整。
WebImageLabel参考https://blog.csdn.net/weixin_54217201/article/details/137932686

class ImageLabel(QLabel)换成class ImageLabel(QAbstractButton)删除Clicked事件即可

代码如下

python 复制代码
import math
import sys
from typing import List
from enum import Enum
from PyQt5.QtCore import pyqtSignal, QSize, Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import (QAbstractButton, QWidget, QButtonGroup, QApplication, QGridLayout, QLayoutItem,
                             QSizePolicy, QHBoxLayout, QVBoxLayout, QScrollArea, QPushButton, QLabel)

from qfluentwidgets import SmoothScrollDelegate
from components import WebImageLabel, ReloadWidget


class LayoutPosition(Enum):
    Left = 0
    Center = 1
    Right = 2


class PictureGridWidget(QScrollArea):
    rowWidgetCount = 5
    buttonClicked = pyqtSignal(QAbstractButton)
    buttonPressed = pyqtSignal(QAbstractButton)
    buttonReleased = pyqtSignal(QAbstractButton)
    buttonToggled = pyqtSignal(QAbstractButton)
    reloadClicked = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.delegate = SmoothScrollDelegate(self, False)
        self._bigButtons = []
        self._noDataWidget = None
        self.view = QWidget()
        self.buttonGroup = QButtonGroup(self.view)
        self.verticalLayout = QVBoxLayout(self.view)

        self.__initUi()
        self.__initNoDataWidget()

    def __initUi(self):
        self.setWidget(self.view)
        self.setWidgetResizable(True)
        self.setContentsMargins(0, 0, 0, 0)
        self.setObjectName("PictureGridWidget")

        self.verticalLayout.setSpacing(5)
        self.verticalLayout.setContentsMargins(0, 0, 10, 0)
        self.verticalLayout.setAlignment(Qt.AlignTop)

        self.buttonGroup.buttonClicked.connect(self.buttonClicked)
        self.buttonGroup.buttonPressed.connect(self.buttonPressed)
        self.buttonGroup.buttonReleased.connect(self.buttonReleased)
        self.buttonGroup.buttonToggled.connect(self.buttonToggled)

    def __resetRowLayout(self, buttons: list, position: LayoutPosition = LayoutPosition.Left):
        """
        重置行布局
        """
        horizontalLayout = QHBoxLayout()
        verticalLayout_1 = QVBoxLayout()
        verticalLayout_2 = QVBoxLayout()

        horizontalLayout.setSpacing(5)
        verticalLayout_1.setSpacing(5)
        verticalLayout_2.setSpacing(5)
        horizontalLayout.setContentsMargins(0, 0, 0, 0)
        verticalLayout_1.setContentsMargins(0, 0, 0, 0)
        verticalLayout_2.setContentsMargins(0, 0, 0, 0)

        button1 = buttons[0]  # type: QAbstractButton
        button1.setMinimumHeight(300)
        self._bigButtons.append(button1)

        for button in buttons[1:3]:
            verticalLayout_1.addWidget(button)
        for button in buttons[3:5]:
            verticalLayout_2.addWidget(button)

        if position == LayoutPosition.Left:
            horizontalLayout.addWidget(button1)
            horizontalLayout.addLayout(verticalLayout_1)
            horizontalLayout.addLayout(verticalLayout_2)
            horizontalLayout.setStretch(0, 2)
            horizontalLayout.setStretch(1, 1)
            horizontalLayout.setStretch(2, 1)
        elif position == LayoutPosition.Center:
            horizontalLayout.addLayout(verticalLayout_1)
            horizontalLayout.addWidget(button1)
            horizontalLayout.addLayout(verticalLayout_2)
            horizontalLayout.setStretch(0, 1)
            horizontalLayout.setStretch(1, 2)
            horizontalLayout.setStretch(2, 1)
        elif position == LayoutPosition.Right:
            horizontalLayout.addLayout(verticalLayout_1)
            horizontalLayout.addLayout(verticalLayout_2)
            horizontalLayout.addWidget(button1)
            horizontalLayout.setStretch(0, 1)
            horizontalLayout.setStretch(1, 1)
            horizontalLayout.setStretch(2, 2)

        return horizontalLayout

    def __resetLayout(self, buttons: list):
        sum_buttons = len(buttons)
        poses = [i for i in LayoutPosition] * math.ceil(sum_buttons / self.rowWidgetCount)
        for index, value in enumerate(range(0, sum_buttons, self.rowWidgetCount)):
            self.verticalLayout.addLayout(
                self.__resetRowLayout(buttons[value:value + self.rowWidgetCount], poses[index]))

    def __resetBigButtons(self, width: int):
        """
        重置大按钮
        """
        for button in self._bigButtons:  # type: WebImageLabel
            button.scaledToWidth(width // 2)

    def __initNoDataWidget(self):
        if self.count() == 0:
            _noDataWidget = ReloadWidget()
            _noDataWidget.reloadClicked.connect(self.reloadClicked)
            self.verticalLayout.addWidget(_noDataWidget, 0, Qt.AlignVCenter | Qt.AlignHCenter)
            self._noDataWidget = _noDataWidget

        else:
            if self._noDataWidget:
                self._noDataWidget.deleteLater()
                self.verticalLayout.removeWidget(self._noDataWidget)

    def setNoDataWidget(self, widget: QWidget):
        self._noDataWidget = widget
        self.update()

    def noDataWidget(self):
        return self._noDataWidget

    def addButtons(self, buttons: List[QAbstractButton]):
        for button in buttons:
            button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            self.buttonGroup.addButton(button)
        self.__resetLayout(buttons)
        self.__resetBigButtons(self.width())
        self.__initNoDataWidget()

    def buttons(self):
        return self.buttonGroup.buttons()

    def takeAt(self, index: int) -> QLayoutItem:
        item = self.verticalLayout.takeAt(index)
        if isinstance(item, QHBoxLayout):
            item.deleteLater()
        return item

    def count(self):
        return self.verticalLayout.count()

    def removeAllWidgets(self):
        while self.count():
            self.takeAt(0)
        for button in self.buttons():
            self.buttonGroup.removeButton(button)
            button.deleteLater()
        self.__initNoDataWidget()

    def resizeEvent(self, a0):
        self.__resetBigButtons(a0.size().width())
        super().resizeEvent(a0)

    def checkedButton(self):
        return self.buttonGroup.checkedButton()

    def checkedId(self):
        return self.buttonGroup.checkedId()


if __name__ == '__main__':
    QApplication.setHighDpiScaleFactorRoundingPolicy(
        Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
    QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
    QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)

    app = QApplication(sys.argv)
    demo = PictureGridWidget()
    demo.setMinimumSize(900, 600)
    imgList = [
        r"G:\手机\壁纸\电脑壁纸\79f6134e92bb51d4f1602bb0503898fc.png",
        r"G:\手机\壁纸\电脑壁纸\2b1ccbd66541d46c880560476210e35f.png",
        r"G:\手机\壁纸\电脑壁纸\aa7d1b13c29fee7477f3c3f78d6478be.png",
        r"G:\手机\壁纸\电脑壁纸\64bbc8d0138d99f4512719146b72d14f.jpeg",
        r"G:\手机\壁纸\电脑壁纸\9eb771c6486a4a5d2442b0f997084d55.png"
    ]
    labelList = []
    for img in imgList:
        i = WebImageLabel()
        i.setPixmap(QPixmap(img))
        labelList.append(i)
    demo.addButtons(labelList)
    bu = QPushButton(demo)
    demo.buttonClicked.connect(print)
    bu.clicked.connect(lambda: demo.removeAllWidgets())
    demo.show()
    sys.exit(app.exec_())
相关推荐
LawrenceLan5 小时前
Flutter 零基础入门(十一):空安全(Null Safety)基础
开发语言·flutter·dart
计算机毕设VX:Fegn08956 小时前
计算机毕业设计|基于springboot + vue医院设备管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
txinyu的博客6 小时前
解析业务层的key冲突问题
开发语言·c++·分布式
Mr__Miss6 小时前
保持redis和数据库一致性(双写一致性)
数据库·redis·spring
码不停蹄Zzz6 小时前
C语言第1章
c语言·开发语言
行者967 小时前
Flutter跨平台开发在OpenHarmony上的评分组件实现与优化
开发语言·flutter·harmonyos·鸿蒙
阿蒙Amon7 小时前
C#每日面试题-Array和ArrayList的区别
java·开发语言·c#
Knight_AL7 小时前
Spring 事务传播行为 + 事务失效原因 + 传播行为为什么不用其他模式
数据库·sql·spring
SmartRadio7 小时前
ESP32添加修改蓝牙名称和获取蓝牙连接状态的AT命令-完整UART BLE服务功能后的完整`main.c`代码
c语言·开发语言·c++·esp32·ble
倔强的石头_7 小时前
时序数据时代的“存储与分析困局”解析及金仓解决方案
数据库