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); 设置渐变方向
效果:
如图,第一张图片按设置的模式来显示,即保持比例模式,第二张图片按设置的忽略比例模式显示