PyQt5 自定义渐变窗口

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); 设置渐变方向

效果:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值