PyQt5 自定义渐变窗口

本文介绍了使用Python和QT实现渐变窗口的相关参数,如对象名称、渐变方向、自动关闭设置等。展示了垂直和水平渐变的效果,包括单色、双色及分段显示颜色和图片的效果。还提到了窗口变化绘画模式及延迟刷新问题,最后给出了QT代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

from PyQt5.QtCore import QTimer, pyqtSignal, QPoint, QRect, Qt
from PyQt5.QtWidgets import (QWidget, QMainWindow)
from PyQt5.QtGui import (QMouseEvent, QPainter, QColor, QLinearGradient, QPaintEvent, QKeyEvent, QBrush, QResizeEvent,
                         QGradient, QCloseEvent, QPixmap)
from PublicSourceSection.PublicMethod.Public_Method import *
class NWidgetOrientation(object):
    Horizontal = 0
    Vertical = 1

class ExecptiveMode(object):
    KeepPixmapRatio = 0
    IgnorePixmapRatio = 1

class ResizeDrawMode(object):
    RealTime = 0
    DelayUpdate = 1

class NWidget(QWidget):
    KeyBoardClickEvent = pyqtSignal(QKeyEvent)
    MousePressedEvent = pyqtSignal(QMouseEvent)
    MouseMovedEvent = pyqtSignal(QMouseEvent)
    MouseReleasedEvent = pyqtSignal(QMouseEvent)
    MouseEnterEvent = pyqtSignal(bool)
    WinCloseEvent = pyqtSignal(bool)
    ResizeHorizontalProporTion = pyqtSignal(float)
    ResizeVertivalProporTion = pyqtSignal(float)
    ExitQuestion = pyqtSignal(bool)
    public_dict = defaultdict(dict)

    def __init__(self, object_name: Union[str],
                 orientation: Union[NWidgetOrientation] = NWidgetOrientation.Vertical,
                 autoexit_enable: Union[bool] = False,
                 autoexit_wait: Union[int]=3000,
                 linear_gradient_enable: Union[bool] = False,
                 color_section: Union[Color, int, QColor, list, list|tuple[list|tuple[QColor|str]]] = False,
                 execptive_pixmapmode: Union[ExecptiveMode] = ExecptiveMode.IgnorePixmapRatio,
                 resizedrawmode: Union[ResizeDrawMode] = ResizeDrawMode.DelayUpdate):
        super().__init__()
        self.autoexit_enable = autoexit_enable
        self.setObjectName(object_name)
        self.setOrientation(orientation)
        self.setLinearEnable(linear_gradient_enable)
        self.setColorSection(color_section)
        self.cif_execptive_mode(execptive_pixmapmode)
        self.resizedrawmodel(resizedrawmode)
        self.setMouseTracking(True)
        self.h_key = 'SizeHeight'
        self.w_key = 'SizeWidth'
        self.check_timer = QTimer()
        self.delay_loader_timer = QTimer()
        self.delay_loader_timer.setSingleShot(True)
        self.check_timer.timeout.connect(self.enter_statecheck)
        self.timeout = autoexit_wait

    def setObjectName(self, name: str) -> None:
        super().setObjectName(name)
        self.replace_dict = self.public_dict[name]
        self.replace_dict['MouseEnterEvent'] = False
        self.replace_dict['DelayLoaderStat'] = False
        self.replace_dict['DelayResizeRound'] = []
        self.replace_dict['AutoExitEnable'] = self.autoexit_enable

    def setOrientation(self, orientation: Union[NWidgetOrientation]):
        self.replace_dict['Orientation'] = orientation

    def cif_execptive_mode(self, mode: Union[ExecptiveMode]):
        self.replace_dict['ExecptivePixmapMode'] = mode

    def resizedrawmodel(self, mode):
        self.replace_dict['ResizeDrawMode'] = mode

    def setLinearEnable(self, a0):
        self.replace_dict['LinearGradientEnable'] = a0

    def setColorSection(self, color):
        self.replace_dict['ColorSection'] = color

    def enterEvent(self, event) -> None:
        self.replace_dict['MouseEnterEvent'] = True
        self.MouseEnterEvent.emit(True)
        if self.replace_dict['AutoExitEnable']:
            self.check_timer.stop()

    def leaveEvent(self, event) -> None:
        self.replace_dict['MouseEnterEvent'] = False
        self.MouseEnterEvent.emit(False)
        if self.replace_dict['AutoExitEnable']:
            self.check_timer.start(self.timeout)

    def enter_statecheck(self):
        if self.replace_dict['MouseEnterEvent']:
            pass
        else:
            self.check_timer.stop()
            self.ExitQuestion.emit(True)
            self.setVisible(False)

    def setVisible(self, state) -> None:
        super().setVisible(state)
        if self.replace_dict['AutoExitEnable']:
            if state:
                self.check_timer.start(self.timeout)
            else:
                self.check_timer.stop()

    def keyReleaseEvent(self, event) -> None:
        self.KeyBoardClickEvent.emit(event)

    def mousePressEvent(self, a0: QMouseEvent) -> None:
        super().mouseReleaseEvent(a0)
        self.MousePressedEvent.emit(a0)
        self.setFocus()

    def mouseMoveEvent(self, a0: QMouseEvent) -> None:
        super().mouseMoveEvent(a0)
        self.MouseMovedEvent.emit(a0)

    def mouseReleaseEvent(self, a0: QMouseEvent) -> None:
        super().mouseReleaseEvent(a0)
        self.MouseReleasedEvent.emit(a0)

    def paintEvent(self, a0: QPaintEvent) -> None:
        if self.replace_dict['DelayLoaderStat']:
            super().paintEvent(a0)
        else:
            if self.replace_dict['LinearGradientEnable']:
                painter = QPainter(self)
                painter.setPen(Qt.NoPen)
                color_section = self.replace_dict['ColorSection']
                gradient_orientation = True if (self.replace_dict['Orientation'] == NWidgetOrientation.Horizontal) else False
                if isinstance(color_section, (list, tuple)):
                    start_linear_xpos = 0
                    end_linear_xpos = 0
                    start_linear_ypos = 0
                    end_linear_ypos = 0
                    size_width = self.replace_dict[self.w_key]
                    size_height = self.replace_dict[self.h_key]
                    linear_ystep = size_height // len(color_section) if isinstance(color_section[0], list) else size_height
                    linear_xstep = size_width // len(color_section) if isinstance(color_section[0], list) else size_width
                    for index, color in enumerate(color_section):
                        pixmap_vessel = []
                        end_linear_ypos += linear_ystep
                        end_linear_xpos += linear_xstep
                        if gradient_orientation:
                            line_top = QLinearGradient(start_linear_xpos, 0, end_linear_xpos, 0)
                        else:
                            line_top = QLinearGradient(0, start_linear_ypos, 0, end_linear_ypos)
                        color_section_init = 0
                        color_linear_step = round(1 / (len(color) - 1), 1) if isinstance(color, list) and len(color) > 1 else 1
                        color_std_step = 1 / len(color) if isinstance(color, list) and len(color) > 1 else 1
                        color_section_width = int(linear_xstep * color_std_step)
                        color_section_height = round(linear_ystep * color_std_step)
                        if isinstance(color, list):
                            for columns, _color in enumerate(color):
                                if isinstance(_color, QColor):
                                    line_top.setColorAt(color_section_init, _color)
                                    line_top.setSpread(QGradient.ReflectSpread)
                                else:
                                    if isinstance(_color, bytes):
                                        pixmap = QPixmap()
                                        pixmap = pixmap if pixmap.loadFromData(_color) else QPixmap()

                                    elif isinstance(_color, str):
                                        pixmap = QPixmap(_color)

                                    else:
                                        pixmap = _color
                                    if gradient_orientation:
                                        rational_linear_start = round(color_section_width * columns + index * linear_ystep)
                                        rational_linear_end = round(rational_linear_start + color_section_width)
                                        if self.replace_dict['ExecptivePixmapMode'] == ExecptiveMode.KeepPixmapRatio:
                                            proportion = pixmap.width() / color_section_width
                                            pixmap.setDevicePixelRatio(proportion)
                                        else:
                                            pixmap = pixmap.scaled(color_section_width, size_height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
                                    else:
                                        rational_linear_start = round(color_section_height * columns + index * linear_xstep)
                                        rational_linear_end = round(rational_linear_start + color_section_height)
                                        if self.replace_dict['ExecptivePixmapMode'] == ExecptiveMode.KeepPixmapRatio:
                                            proportion = pixmap.height() / color_section_height
                                            pixmap.setDevicePixelRatio(proportion)
                                        else:
                                            pixmap = pixmap.scaled(size_width, color_section_height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)

                                    pixmap_vessel.append([(rational_linear_start, rational_linear_end), pixmap])
                                color_section_init += color_linear_step

                            if gradient_orientation:
                                lift_rect = QRect(start_linear_xpos, 0, end_linear_xpos, size_height)
                            else:
                                lift_rect = QRect(0, start_linear_ypos, size_width, end_linear_ypos)
                            painter.setBrush(line_top)
                            painter.drawRect(lift_rect)
                            start_linear_xpos += linear_xstep
                            start_linear_ypos += linear_ystep
                            if pixmap_vessel:
                                for pixinfo in pixmap_vessel:
                                    begin_ = pixinfo[0][0]
                                    pixmap_ = pixinfo[1]
                                    pixmap_:QPixmap
                                    if self.replace_dict['ExecptivePixmapMode'] == ExecptiveMode.KeepPixmapRatio:
                                        centra_y = round((size_height - (pixmap_.height() / pixmap_.devicePixelRatio())) // 2)
                                    else:
                                        centra_y = 0
                                    if gradient_orientation:
                                        painter.drawPixmap(begin_, centra_y, pixmap_)
                                    else:
                                        painter.drawPixmap(0, begin_, pixmap_)


                else:
                    if isinstance(color_section, str):
                        filler_color = QColor(color_section)
                    elif isinstance(color_section, Color):
                        filler_color = QColor(color_section.value)
                    elif isinstance(color_section, int):
                        filler_color = QColor(color_section)
                    else:
                        filler_color = color_section
                    painter.setBrush(QBrush(filler_color))
                    overall_rect = QRect(0, 0, self.width(), self.height())
                    painter.drawRect(overall_rect)

    def resizeEvent(self, a0:QResizeEvent) -> None:
        super().resizeEvent(a0)
        currentsize_width = a0.size().width()
        currentsize_height = a0.size().height()
        if self.h_key in self.replace_dict.keys() and currentsize_height != self.replace_dict[self.h_key]:
            self.ResizeVertivalProporTion.emit(currentsize_height / self.replace_dict[self.h_key])
        if self.w_key in self.replace_dict.keys() and currentsize_width != self.replace_dict[self.w_key]:
            self.ResizeHorizontalProporTion.emit(currentsize_width / self.replace_dict[self.w_key])
        if not self.replace_dict['DelayLoaderStat'] and self.replace_dict['ResizeDrawMode'] == ResizeDrawMode.DelayUpdate:
            self.replace_dict['DelayLoaderStat'] = True
            self.delay_loader_timer.timeout.connect(self.delay_loader_stat)
            self.delay_loader_timer.start(1000)
        self.replace_dict[self.w_key] = currentsize_width
        self.replace_dict[self.h_key] = currentsize_height

    def delay_loader_stat(self):
        self.replace_dict['DelayLoaderStat'] = False
        self.replace_dict['DelayResizeRound'].clear()
        self.update()

    def closeEvent(self, a0: QCloseEvent) -> None:
        super().closeEvent(a0)
        if a0.isAccepted():
            self.WinCloseEvent.emit(True)
        else:
            self.WinCloseEvent.emit(False)

object_name: Union[str]                对象名称
orientation: Union[NWidgetOrientation] = NWidgetOrientation.Vertical        渐变方向
autoexit_enable: Union[bool] = False       自动关闭,某些特性场景会用到,鼠标离开就定时关闭窗口,默认不自动关闭
autoexit_wait: Union[int]=3000                自动关闭定时时间,单位毫秒,默认3秒后关闭
linear_gradient_enable: Union[bool] = False        渐变标识,默认不渐变
color_section: Union[Color, int, QColor, list[list[QColor]]] = False        渐变色段
execptive_pixmapmode: Union[ExecptiveMode] 存在非Qcolor类型的色段元素时,填充的模式,可选保持比例和忽略比例

resizedrawmode: Union[ResizeDrawMode] 窗口变化的绘画模式,分为实时的和延迟的

使用实例:

class mainwin(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(400, 800)
        color_list = [[QColor(qRgb(211, 230, 242)), QColor(240, 240, 240), QColor(qRgb(211, 230, 242))]]
        self.customize_qwidget = NWidget('customize_qwidget',
                                    linear_gradient_enable=True,
                                    color_section=color_list)

        self.setCentralWidget(self.customize_qwidget)

if __name__=="__main__":
    exe = QApplication(sys.argv)
    win = mainwin()
    win.show()
    exe.exit(exe.exec_())

效果:

 很显然看到,中间白色把窗口分成了上下两片,是因为我们只设置了三个颜色,即

[[QColor(qRgb(211, 230, 242)),          上

QColor(240, 240, 240),                       中

QColor(qRgb(211, 230, 242))]]           下

对应三个位置,再加一个色段

class mainwin(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(400, 800)
        color_list = [[QColor(qRgb(211, 230, 242)), QColor(240, 240, 240), QColor(qRgb(211, 230, 242))],
                     [QColor(qRgb(211, 230, 242)), QColor(Color.WhiteSmoke.value), QColor(qRgb(226, 238, 248))]]
        self.customize_qwidget = NWidget('customize_qwidget',
                                    linear_gradient_enable=True,
                                    color_section=color_list)

        self.setCentralWidget(self.customize_qwidget)

if __name__=="__main__":
    exe = QApplication(sys.argv)
    win = mainwin()
    win.show()
    exe.exit(exe.exec_())

效果:

 以中间为准,分成上色段和下色段,为了衔接好上色段最后一个颜色和下色段第一个颜色是一样的,效果还可以,色段支持累加

class mainwin(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(400, 800)
        color_list = [[QColor(qRgb(211, 230, 242)), QColor(240, 240, 240), QColor(qRgb(211, 230, 242))],
                     [QColor(qRgb(211, 230, 242)), QColor(Color.WhiteSmoke.value), QColor(qRgb(226, 238, 248))],
                      [QColor(Color.Red.value), QColor(Color.Green.value), QColor(Color.Violet.value)]]
        self.customize_qwidget = NWidget('customize_qwidget',
                                    linear_gradient_enable=True,
                                    color_section=color_list)

        self.setCentralWidget(self.customize_qwidget)

if __name__=="__main__":
    exe = QApplication(sys.argv)
    win = mainwin()
    win.show()
    exe.exit(exe.exec_())

效果:

 单色或者双色的效果

单色

 双色

 以上是垂直渐变的一些效果:

水平渐变就改下参数就行了

 指定一个方向orientation

效果

 既然可以分段显示颜色,那分段显示图片也是可以的,已经写了加载图片的代码,原先打算是只显示单色渐变的,但是图片做静态展示的话,不涉及频繁变动窗口大小,可以考虑用,频繁改变窗口大小,只要动一下就会重绘一次,所以会有点卡),可以添加延迟刷新,指定resizedrawmode: Union[ResizeDrawMode] 为 ResizeDrawMode.DelayUpdate 就可以了,但是延迟刷新过程中因为停止了刷新函数,所以画面会出现短暂为空的情况,暂时还不知道如何维持原内容,窗口变化结束后再刷新绘画,有大佬知道的可以留言指教下

实例化,color_section 参数不需要规则的列表参数,例如下面代码

或者

 分别对应效果

 

垂直方向的

 混合的

有兴趣的也可以用QT,QT的代码详细注释了代码是干嘛的

头文件

#ifndef NWIDGET_H
#define NWIDGET_H
#undef Attribute
#include "FireCracker/Beacon/FieldAttribute.h"
#include <QtWidgets>
#include <QtGui>
#include <string>
#include <string.h>
using namespace std;
class Nwidget:public QWidget{

    Q_OBJECT

public:

    QStringList Evlist = {WIN_MOUSE_ATTRIBUTE.WIN_NORMAL,
                          WIN_MOUSE_ATTRIBUTE.WIN_LEAVE,
                          WIN_MOUSE_ATTRIBUTE.WIN_ENTER,
                          WIN_MOUSE_ATTRIBUTE.WIN_PRESS,
                          WIN_MOUSE_ATTRIBUTE.WIN_RELEASE};

    Nwidget(QString _ObjectName,
             bool IsExit = false,
             int Sec = 5000,
             QWidget *parent = nullptr);

    void setLinearEnable(bool Enable);

    void setOrientation(NT::WIN_ARG_ATTRIBUTE Orien);

    void setAutoExitEnable(bool IsExit);

    void setAutoExitWait(int Sec);

    void setCifExecptiveMode(NT::WIN_ATTRIBUTE mode);

    void setInsertPixmap(QList<pair<QPixmap, int>>Spix);

    void setInsertPixmap(QList<pair<QString, int>>Spix);

    void setInsertRatioMode(QList<pair<NT::WIN_ATTRIBUTE, int>> modePair);

    void setSeColor(QList<QList<QColor>> Pix);

    void setSeColor(QList<QList<QString>> Pix);

    void setSeColor(QList<QColor> Pix);

    void setSeColor(QPixmap Pix);

    void setSeColor(QColor Pix);

    void setSeColor(QString Pix);

    void setLoaderMode(NT::WIN_ATTRIBUTE Type);

    void InsertPixmapClear();

    void SeColorClear();

    void setVisible(bool vsb);

protected:
    QPoint MSSTART;
    QPoint MSEND;
    QPoint MSMV;
    void enterEvent(QEvent *Ev);
    void leaveEvent(QEvent *Ev);
    void paintEvent(QPaintEvent *Ev);
    void resizeEvent(QResizeEvent *Ev);
    virtual void mouseMoveEvent(QMouseEvent *e);
    virtual void mousePressEvent(QMouseEvent *Ev);
    virtual void mouseReleaseEvent(QMouseEvent *Ev);
    void DelayUpdate();

signals:
    void MousePressEvent(QMouseEvent *Ev);
    void MouseReleaseEvent(QMouseEvent *Ev);
    void MenuCheckEvent(QMouseEvent *Ev);
    void MouseMoveEvent(QMouseEvent *Ev);
    void ResizePrpToWidth(double);
    void ResizePrpToHeight(double);
    void MouseLeaveEvent(pair<bool, QString>);
    void MouseEnterEvent(pair<bool, QString>);

private:
    bool ReadyInit;
    QString ObjectName;
    QTimer DelayTimer;
    QTimer AutoTimer;
    QMap<QString, QMap<QString, QPixmap>>Rdo_pixMap;
    QMap<QString, QMap<QString, QString>>Rdo_nestString;
    QMap<QString, QMap<QString, QList<pair<QPixmap, int>>>>Rdo_nestPixmapair;
    QMap<QString, QMap<QString, bool>>Rdo_nestBool;
    QMap<QString, QMap<QString, int>>Rdo_nestInt;
    QMap<QString, QMap<QString, double>>Rdo_nestdouble;
    QMap<QString, QMap<QString, pair<int, int>>>Rdo_nestpospair;
    QMap<QString, QMap<QString, QList<pair<NT::WIN_ATTRIBUTE, int>>>>Rdo_listModePair;
    QMap<QString, QMap<QString, QFont>>Rdo_nestFont;
    QMap<QString, QMap<QString, QList<QList<QColor>>>>Rdo_nestColorList;

};
#endif

cpp文件

#include "FireCracker/Trunk/NWidget.h"
#include "FireCracker/Beacon/FieldAttribute.h"
Nwidget::Nwidget(QString _ObjectName, bool IsExit, int Sec, QWidget *parent):QWidget(parent){
    ReadyInit = false;
    ObjectName = _ObjectName;
    setObjectName(_ObjectName);
    setParent(parent);
    MSSTART = QPoint(0, 0);
    MSEND = QPoint(0, 0);
    MSMV = QPoint(0, 0);
    DelayTimer.setSingleShot(true);
    Rdo_nestInt[ObjectName][WIN_KEY_ATTRIBUTE.WIN_SIZE_W] = this->width();
    Rdo_nestInt[ObjectName][WIN_KEY_ATTRIBUTE.WIN_SIZE_H] = this->height();
    Rdo_nestInt[ObjectName]["LoaderMode"] = NT::WIN_ATTRIBUTE::PIXLOAD_DELAY;
    Rdo_nestInt[ObjectName]["Orientation"] = NT::WIN_ARG_ATTRIBUTE::ORIEN_VERTICAL;
    Rdo_nestInt[ObjectName]["ExceptiveRatioMode"] = NT::WIN_ATTRIBUTE::PIXLOAD_KEEPRATIO;
    Rdo_nestBool[ObjectName]["LinearEnable"] = false;
    Rdo_nestBool[ObjectName]["AutoExitEnable"] = IsExit;
    Rdo_nestBool[ObjectName]["DelayUpStat"] = true;
    Rdo_nestInt[ObjectName]["AutoExitWait"] = Sec;
    Rdo_nestColorList[ObjectName]["SeColor"] = {{QColor(qRgb(211, 230, 242)), QColor(240, 240, 240), QColor(qRgb(211, 230, 242))}};
    connect(&DelayTimer, &QTimer::timeout, this, &Nwidget::DelayUpdate);
    connect(&AutoTimer, &QTimer::timeout, this, &Nwidget::close);
}


void Nwidget::setLinearEnable(bool Enable){
    Rdo_nestBool[ObjectName]["LinearEnable"] = Enable;
}


void Nwidget::setOrientation(NT::WIN_ARG_ATTRIBUTE Orien){
    Rdo_nestInt[ObjectName]["Orientation"] = Orien;
}


void Nwidget::setAutoExitEnable(bool IsExit){
    Rdo_nestBool[ObjectName]["AutoExitEnable"] = IsExit;
    }


void Nwidget::setAutoExitWait(int Sec){
    Rdo_nestInt[ObjectName]["AutoExitWait"] = Sec;
    }


void Nwidget::setCifExecptiveMode(NT::WIN_ATTRIBUTE mode){
    Rdo_nestInt[ObjectName]["ExceptiveRatioMode"] = mode;
}


void Nwidget::setInsertPixmap(QList<pair<QPixmap, int>>Spix){
    Rdo_nestPixmapair[ObjectName]["InsertPixmap"] = Spix;
}


void Nwidget::setInsertPixmap(QList<pair<QString, int>>Spix){
    for (int idx= 0; idx < Spix.size(); idx++){
        Rdo_nestPixmapair[ObjectName]["InsertPixmap"].append(make_pair(QPixmap(Spix[idx].first), Spix[idx].second));
    }
}

void Nwidget::setInsertRatioMode(QList<pair<NT::WIN_ATTRIBUTE, int>> modePair){
    Rdo_listModePair[ObjectName]["InsertPixmapMode"] = modePair;
}


void Nwidget::setSeColor(QList<QList<QColor>> Pix){
    Rdo_nestColorList[ObjectName]["SeColor"] = Pix;
}


void Nwidget::setSeColor(QList<QList<QString>> Pix){
    QList<QList<QColor>>RecomBination;
    for (int index = 0;index < Pix.size(); index++){
        QList<QColor> ColorList;
        for (int itindex = 0; itindex < Pix[index].size(); itindex++){
            ColorList.append(QColor(Pix[index][itindex]));
        }
        RecomBination.append(ColorList);
    }
    Rdo_nestColorList[ObjectName]["SeColor"] = RecomBination;
}


void Nwidget::setSeColor(QList<QColor> Pix){
    Rdo_nestColorList[ObjectName]["SeColor"] = {Pix};
}


void Nwidget::setSeColor(QPixmap Pix){
    Rdo_pixMap[ObjectName]["Pixmap"] = Pix;
}


void Nwidget::setSeColor(QColor Pix){
    Rdo_nestColorList[ObjectName]["SeColor"] = QList<QList<QColor>>({{Pix}});
}


void Nwidget::setSeColor(QString Pix){
    Rdo_nestColorList[ObjectName]["SeColor"] = QList<QList<QColor>>({{QColor(Pix)}});
}


void Nwidget::setLoaderMode(NT::WIN_ATTRIBUTE Type){
    Rdo_nestInt[ObjectName]["LoaderMode"] = Type;
}


void Nwidget::paintEvent(QPaintEvent *Ev){
    if (!Rdo_nestBool[ObjectName]["LinearEnable"] ||
        !Rdo_nestBool[ObjectName]["DelayUpStat"]){
        QWidget::paintEvent(Ev);
    } else {
        QPainter CaptainBrush(this);
        CaptainBrush.setPen(Qt::NoPen);
        //#声明渐变方向和比例模式
        bool Orientation;
        bool DescribeRatio;
        //#实时更新的组件宽高
        int SizeWidth = Rdo_nestInt[ObjectName][WIN_KEY_ATTRIBUTE.WIN_SIZE_W];
        int SizeHeight = Rdo_nestInt[ObjectName][WIN_KEY_ATTRIBUTE.WIN_SIZE_H];
        //#定义渐变方向和比例模式,水平方向为true,反之为false,维持比例模式为true,反之为false
        if (Rdo_nestInt[ObjectName]["Orientation"] == NT::ORIEN_HORIZONTAL){
            Orientation = true;
        } else {
            Orientation = false;
        }
        if (Rdo_nestInt[ObjectName]["ExceptiveRatioMode"] == NT::PIXLOAD_KEEPRATIO){
            DescribeRatio = true;
        } else {
            DescribeRatio = false;
        }
        //#如果开启了渐变,SecColor 数据格式为 QList<QList<QColor>> ,此时列表数据大于或者内列表数据大于1 ,并且不存在QPixmap图片,则执行以下代码
        if ( Rdo_nestBool[ObjectName]["LinearEnable"] &&
             (Rdo_nestColorList[ObjectName]["SeColor"].size() > 1 ||
              Rdo_nestColorList[ObjectName]["SeColor"][0].size() > 1) &&
             Rdo_pixMap[ObjectName]["Pixmap"].isNull()){
            CaptainBrush.setPen(Qt::NoPen);
            QList<QList<QColor>> SeColor = Rdo_nestColorList[ObjectName]["SeColor"]; //#色段数据
            QLinearGradient Grandient; //#声明水平渐变类
            int IPTaddcount = 0; //#色段累计值,从0开始,完成一个QColor绘画则加1
            int StartLinearXpos = 0; //#水平渐变开始位置
            int EndLinearXpos = 0;  //#水平渐变结束位置
            int StartLinearYpos = 0;  //#垂直渐变开始位置
            int EndLinearYpos = 0;  //#垂直渐变结束位置
            int GlobalYstep = SizeHeight / SeColor.size(); //#垂直步长,即高除于色段数
            int GlobalXstep = SizeWidth / SeColor.size();  //#水平步长,即宽除于色段数
            for (int secNum = 0; secNum < SeColor.size(); secNum++){ //#循环色段数
                QList<pair<pair<QPixmap, int>, bool>> exceptivePixList; //#声明一个列表,用于收集图片
                QList<int> exceptiveIndexList;
                QRect SgSrcRect;
                EndLinearYpos += GlobalYstep; //#垂直渐变结束位置领先一个垂直步长
                EndLinearXpos += GlobalXstep; //#水平渐变结束位置领先一个水平步长
                //#定义渐变类,根据渐变方向参数设置开始和结束位置
                if (Orientation){
                    Grandient = QLinearGradient(StartLinearXpos, 0, EndLinearXpos, 0);
                } else {
                    Grandient = QLinearGradient(0, StartLinearYpos, 0, EndLinearYpos);
                }
                double DetailAddtion = 0; //#定义一个渐变步长累加浮点数
                //#定义一个相对色段步长,比如一个色段里面有3中颜色时,色段size为3,把色段分配的长度比做1,则相对步长为0.3,循环3次,则相对步长累加值 DetailAddtion
                //#分别为 0 0.3 0.6,而0.6往后是空的,也就是填不满,因此要在size的基础上减1,相对步长为0 0.5 1,才能实现渐变很好的填充
                double RelativeStep = 1.0 / (double)(SeColor[secNum].size() - 1);
                double StandardStep = 1.0 / (double)SeColor[secNum].size(); //#定义一个标准步长,也就是在size不减1的情况下的相对步长
                int DatailPptToWidthint = GlobalXstep * StandardStep; //#水平一个色号分配到的宽度
                int DatailPptToHeightint = GlobalYstep * StandardStep; //#垂直一个色号分配到的宽度
                int RationalSgExceptiveStart; //#定义一个色号开始绘画点
                for (int sgsec = 0; sgsec < SeColor[secNum].size(); sgsec++){ //#开始循环色段内的色号
                    Grandient.setColorAt(DetailAddtion, SeColor[secNum][sgsec]); //#设置渐变步长累加值
                    Grandient.setSpread(QGradient::ReflectSpread); //#设置渐变模式
                    //#如果存在插入的图片或色号
                    if (Rdo_nestPixmapair[ObjectName].keys().count("InsertPixmap") &&
                        !Rdo_nestPixmapair[ObjectName]["InsertPixmap"].isEmpty()){
                        //#定义一个插入图片的数据列表
                        QList<pair<QPixmap, int>> pixPairList = Rdo_nestPixmapair[ObjectName]["InsertPixmap"];
                        for (int ist = 0; ist < pixPairList.size(); ist++){ //#循环插入数据
                            bool ratioMode=false; //#定义一个模式状态,不沿用 DescribeRatio 的状态了,当发生插入模式操作时, DescribeRatio 为备用状态,当前定义的才是主状态
                            QPixmap IstPixmap = pixPairList[ist].first; //#插入的数据
                            int InstIndex = pixPairList[ist].second;  //#插入数据对应的索引
                            if (!Rdo_listModePair[ObjectName]["InsertPixmapMode"].isEmpty()) //#如果有插入模式数据
                            {
                                QList<pair<NT::WIN_ATTRIBUTE, int>> modeList = Rdo_listModePair[ObjectName]["InsertPixmapMode"]; //#获取插入模式内容
                                for(int i = 0; i < modeList.size(); i++)
                                {
                                    int indexOfmode = modeList[i].second; //#定义插入模式的索引
                                    int modeName = modeList[i].first; //#定义插入模式名
                                    if (indexOfmode == InstIndex) //#如果索引与当前索引一致,则使用插入的模式来进行图片的属性设置
                                    {
                                        if (modeName == NT::PIXLOAD_KEEPRATIO)
                                        {
                                            ratioMode = true;
                                        }
                                        else
                                        {
                                            ratioMode = false;
                                        }
                                        break;
                                    }
                                    else //# 索引不一致时使用备用状态
                                    {
                                        ratioMode = DescribeRatio;
                                    }
                                }
                            }
                            else //# 没有插入数据时,按 DescribeRatio 统一设置图片的属性
                            {
                                ratioMode = DescribeRatio;
                            }
                            //#如果色号对应的索引与要插入的图片索引一致,并且图片还不为空
                            if (IPTaddcount == InstIndex && !IstPixmap.isNull()){
                                if (!Orientation){
                                    //#计算垂直开始位置,分配到的高度 * 索引值 + 色段号 * 单个色段号对应的高
                                    RationalSgExceptiveStart = DatailPptToHeightint * InstIndex + secNum * GlobalYstep;
                                    if (ratioMode){
                                        //#维持比例模式下,计算图片比例,设置比例
                                        double PixPpt = IstPixmap.height() / DatailPptToHeightint;
                                        IstPixmap.setDevicePixelRatio(PixPpt);
                                    }
                                    else
                                    {

                                        //#忽略比例模式下,设置pixmap为最大宽,高度为一个色号的高
                                        IstPixmap = IstPixmap.scaled(SizeWidth,
                                                                     DatailPptToHeightint,
                                                                     Qt::IgnoreAspectRatio,
                                                                     Qt::SmoothTransformation);
                                    }
                                }
                                else
                                {
                                    //#计算水平开始位置,分配到的宽度 * 索引值 + 色段号 * 单个色段号对应的宽
                                    RationalSgExceptiveStart = DatailPptToWidthint * InstIndex + secNum * GlobalXstep;
                                    if (ratioMode){
                                        //#维持比例模式下,计算图片比例,设置比例
                                        double PixPpt = IstPixmap.height() / SizeHeight;
                                        IstPixmap.setDevicePixelRatio(PixPpt);
                                    }
                                    else
                                    {
                                        //#忽略比例模式下,设置pixmap为最大高为组件高,宽度为一个色号的宽
                                        IstPixmap = IstPixmap.scaled(DatailPptToWidthint,
                                                                     SizeHeight,
                                                                     Qt::IgnoreAspectRatio,
                                                                     Qt::SmoothTransformation);
                                    }
                                }
                                //#将数据装入容器,因为渐变在色段循环完毕后才设置完成,需要在后续brush才能生效,因此图片数据必须在绘制完渐变数据后才
                                //#开始进行插入,否则插入的图片将被渐变色号覆盖
                                qDebug() << IstPixmap << InstIndex << 88;
                                exceptiveIndexList.append(InstIndex);
                                exceptivePixList.append(make_pair(make_pair(IstPixmap, RationalSgExceptiveStart), ratioMode));
                            }
                        }
                    }
                    IPTaddcount++; //#完成一个色号的渐变设置,累计值加1
                    DetailAddtion += RelativeStep; //#完成一个色号的渐变设置,渐变步长累加浮点数累加一个相对步长
                }
                //#设置渐变矩形区域
                if (Orientation){
                    SgSrcRect = QRect(0, StartLinearYpos, SizeWidth, EndLinearYpos);
                } else {
                    SgSrcRect = QRect(StartLinearXpos, 0, EndLinearXpos, SizeHeight);
                }
                //#绘画渐变
                CaptainBrush.setBrush(Grandient);
                CaptainBrush.drawRect(SgSrcRect);
                //#完成一个色段渐变的绘画则开始渐变累计值累加一个步长
                StartLinearXpos += GlobalXstep;
                StartLinearYpos += GlobalYstep;
                //#如果存在图片数据
                if (!exceptivePixList.isEmpty()){
                    for (int pixNum = 0; pixNum < exceptivePixList.size(); pixNum++){
                        //#定义基础信息,起始绘画位置,图片,模式
                        int Begin = exceptivePixList[pixNum].first.second; //#图片开始绘画位置
                        QPixmap Pixmap = exceptivePixList[pixNum].first.first; //#图片
                        bool ratioMode = exceptivePixList[pixNum].second; //#模式
                        //# 通过比例得出宽高
                        int pixWidth = Pixmap.width() / Pixmap.devicePixelRatio();
                        int pixHeight = Pixmap.height() / Pixmap.devicePixelRatio();
                        //#声明和定义一个图片居中位置的坐标点
                        QPoint CentraHPos;
                        QPoint CentraVPos;
                        CentraHPos.setX((DatailPptToWidthint - pixWidth) / 2);
                        CentraHPos.setY((SizeHeight - pixHeight) / 2);
                        CentraVPos.setX((SizeWidth - pixWidth) / 2);
                        CentraVPos.setY((DatailPptToHeightint - pixHeight) / 2);
                        //#根据方向和模式开始绘画
                        if (Orientation)
                        {
                            if (ratioMode)
                            {
                                CaptainBrush.drawPixmap(Begin + CentraHPos.x(), CentraHPos.y(), Pixmap);
                            }
                            else
                            {
                                CaptainBrush.drawPixmap(Begin, 0, Pixmap);
                            }
                        }
                        else
                        {
                            if (ratioMode)
                            {
                                CaptainBrush.drawPixmap(CentraVPos.x(), Begin + CentraVPos.y(), Pixmap);
                            }
                            else
                            {
                                CaptainBrush.drawPixmap(0, Begin, Pixmap);
                            }
                        }
                    }
                }
            }
            //#继承原代码
            QWidget::paintEvent(Ev);
        //#存在pixmap数据并且没有色段值或者色段值不符合时,执行以下代码
        } else {
            if (!Rdo_pixMap[ObjectName]["Pixmap"].isNull()){
                QPixmap secNumPix = Rdo_pixMap[ObjectName]["Pixmap"];
                if (DescribeRatio){
                    //#设置图片比例
                    double Ppt = (double)secNumPix.height() / SizeHeight;
                    secNumPix.setDevicePixelRatio(Ppt);
                } else {
                    //#设置图片比例
                    double Ppt = (double)secNumPix.width() / SizeWidth;
                    secNumPix.setDevicePixelRatio(Ppt);
                    secNumPix.scaled(QSize(SizeWidth, SizeHeight),
                                    Qt::AspectRatioMode::IgnoreAspectRatio,
                                    Qt::SmoothTransformation);
                }
                CaptainBrush.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);
                CaptainBrush.setBrush(QBrush(secNumPix));
            }else{
                //#如果图片为空,则使用默认颜色
                QColor secNumColor = Rdo_nestColorList[ObjectName]["SeColor"].first().first();
                CaptainBrush.setBrush(QBrush(secNumColor));
            }
            //#全组件宽高绘画
            QRect DrawRange = QRect(0, 0, SizeWidth, SizeHeight);
            CaptainBrush.drawRect(DrawRange);
        }
    }
}


void Nwidget::resizeEvent(QResizeEvent *EV){
    int WIN_SIZE_W = EV->size().width();
    int WIN_SIZE_H = EV->size().height();
    if (Rdo_nestInt[ObjectName].keys().count(WIN_KEY_ATTRIBUTE.WIN_SIZE_W) &&
        WIN_SIZE_H != Rdo_nestInt[ObjectName][WIN_KEY_ATTRIBUTE.WIN_SIZE_H]){
        emit ResizePrpToHeight(WIN_SIZE_H / Rdo_nestInt[ObjectName][WIN_KEY_ATTRIBUTE.WIN_SIZE_H]);
    }
    if (Rdo_nestInt[ObjectName].keys().count(WIN_KEY_ATTRIBUTE.WIN_SIZE_W) &&
        WIN_SIZE_W != Rdo_nestInt[ObjectName][WIN_KEY_ATTRIBUTE.WIN_SIZE_W]){
        emit ResizePrpToHeight(WIN_SIZE_W / Rdo_nestInt[ObjectName][WIN_KEY_ATTRIBUTE.WIN_SIZE_W]);
    }
    if (Rdo_nestInt[ObjectName]["LoaderMode"] == NT::WIN_ATTRIBUTE::PIXLOAD_DELAY){
        if (ReadyInit){
            Rdo_nestBool[ObjectName]["DelayUpStat"] = false;
            DelayTimer.start(100);
        } else {
            ReadyInit = true;
        }
      Rdo_nestInt[ObjectName][WIN_KEY_ATTRIBUTE.WIN_SIZE_W] = WIN_SIZE_W;
      Rdo_nestInt[ObjectName][WIN_KEY_ATTRIBUTE.WIN_SIZE_H] = WIN_SIZE_H;
    }
}


void Nwidget::DelayUpdate(){
    Rdo_nestBool[ObjectName]["DelayUpStat"] = true;
    this->update();
}


void Nwidget::mousePressEvent(QMouseEvent *Ev){
    emit MousePressEvent(Ev);
}


void Nwidget::mouseMoveEvent(QMouseEvent *Ev){
    emit MouseMoveEvent(Ev);
}


void Nwidget::mouseReleaseEvent(QMouseEvent *Ev){
    emit MouseReleaseEvent(Ev);
}


void Nwidget::enterEvent(QEvent*){
    emit MouseEnterEvent(make_pair(true, ObjectName));
    if (Rdo_nestBool[ObjectName]["AutoExitEnable"]){
        AutoTimer.stop();
    }
}


void Nwidget::leaveEvent(QEvent*){
    emit MouseLeaveEvent(make_pair(false, ObjectName));
    if (Rdo_nestBool[ObjectName]["AutoExitEnable"]){
        AutoTimer.start(Rdo_nestInt[ObjectName]["AutoExitWait"]);
    }
}

void Nwidget::setVisible(bool vsb){
    QWidget::setVisible(vsb);
    if (Rdo_nestBool[ObjectName]["AutoExitEnable"])
        AutoTimer.start(Rdo_nestInt[ObjectName]["AutoExitWait"]);
}

void Nwidget::InsertPixmapClear(){
    Rdo_pixMap[ObjectName]["Pixmap"] = QPixmap();
}


void Nwidget::SeColorClear(){
    Rdo_nestColorList[ObjectName]["SeColor"].clear();
}

相对于python多了可以指定某个图片的显示模式函数

实例化:
 


Nwidget *SP_configWidget = new Nwidget("SP_configWidget");

添加组件参数:
QList<QColor> ToolbarColor {QColor(99,106,178), QColor(188,216,225), QColor(99,106,178)};
SP_configWidget->setSeColor(ToolbarColor); 设置色段
SP_configWidget->setLinearEnable(true); 开启组件渐变
SP_configWidget->setInsertPixmap({make_pair(QPixmap(":/IMG/WindMill/DFcover.jpg"), 2), make_pair(QPixmap(":/IMG/WindMill/WindMill.ico"), 1)}); 添加图片
SP_configWidget->setInsertRatioMode({make_pair(NT::PIXLOAD_IGNORERADIO, 2), make_pair(NT::PIXLOAD_KEEPRATIO, 1)}); 添加图片模式,不加这个的话添加的图片全按setCifExecptiveMode 设置的模式来统一设置
SP_configWidget->setCifExecptiveMode(NT::PIXLOAD_KEEPRATIO); 设置图片显示模式
SP_configWidget->setOrientation(NT::ORIEN_HORIZONTAL); 设置渐变方向

效果:

如图,第一张图片按设置的模式来显示,即保持比例模式,第二张图片按设置的忽略比例模式显示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值