显示.9格式图片
This commit is contained in:
parent
762e6b9af2
commit
0478eb0019
20 changed files with 1229 additions and 8 deletions
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?eclipse-pydev version="1.0"?><pydev_project>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Python34</pydev_property>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 3.0</pydev_property>
|
||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
||||
<path>/${PROJECT_DIR_NAME}</path>
|
||||
|
|
|
@ -35,6 +35,12 @@ encoding//\u5206\u5272\u7A97\u53E3\u7684\u5206\u5272\u6761\u91CD\u5199/Splitter.
|
|||
encoding//\u52A8\u753B\u7279\u6548/\u53F3\u952E\u83DC\u5355\u52A8\u753B.py=utf-8
|
||||
encoding//\u52A8\u753B\u7279\u6548/\u6DE1\u5165\u6DE1\u51FA.py=utf-8
|
||||
encoding//\u53F3\u4E0B\u89D2\u5F39\u51FA\u6846/WindowNotify.py=utf-8
|
||||
encoding//\u56FE\u7247/\u663E\u793A.9\u683C\u5F0F\u56FE\u7247/pyd\u7248\u672C/QtNinePatch/sip/configure.py=utf-8
|
||||
encoding//\u56FE\u7247/\u663E\u793A.9\u683C\u5F0F\u56FE\u7247/pyd\u7248\u672C/QtNinePatch/sip/testQtNinePatch.py=utf-8
|
||||
encoding//\u56FE\u7247/\u663E\u793A.9\u683C\u5F0F\u56FE\u7247/\u7EAFpython\u7248\u672C1/NinePatch.py=utf-8
|
||||
encoding//\u56FE\u7247/\u663E\u793A.9\u683C\u5F0F\u56FE\u7247/\u7EAFpython\u7248\u672C1/testNinePatch.py=utf-8
|
||||
encoding//\u56FE\u7247/\u663E\u793A.9\u683C\u5F0F\u56FE\u7247/\u7EAFpython\u7248\u672C2/QtNinePatch.py=utf-8
|
||||
encoding//\u56FE\u7247/\u663E\u793A.9\u683C\u5F0F\u56FE\u7247/\u7EAFpython\u7248\u672C2/testQtNinePatch.py=utf-8
|
||||
encoding//\u56FE\u7247\u52A0\u8F7D/LoadImage.py=utf-8
|
||||
encoding//\u56FE\u7247\u52A0\u8F7D/SlippedImgWidget.py=utf-8
|
||||
encoding//\u56FE\u7247\u52A0\u8F7D/res_rc.py=utf-8
|
||||
|
|
53
图片/显示.9格式图片/README.md
Normal file
53
图片/显示.9格式图片/README.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
# .9格式图片显示(气泡)
|
||||
|
||||
什么叫.9.PNG呢,这是安卓开发里面的一种特殊的图片
|
||||
这种格式的图片在android 环境下具有自适应调节大小的能力。
|
||||
|
||||
|
||||
(1)允许开发人员定义可扩展区域,当需要延伸图片以填充比图片本身更大区域时,可扩展区的内容被延展。
|
||||
|
||||
(2)允许开发人员定义内容显示区,用于显示文字或其他内容
|
||||
|
||||
目前手机QQ中很多漂亮的的聊天气泡就是.9格式的png图片
|
||||
|
||||
在Github开源库中搜索到两个C++版本的
|
||||
|
||||
1.一个是NinePatchQt https://github.com/Roninsc2/NinePatchQt
|
||||
|
||||
2.一个是QtNinePatch https://github.com/soramimi/QtNinePatch
|
||||
|
||||
### For PyQt
|
||||
1、目前针对第一个库在2年前用[纯python版本1](纯python版本1/)参考源码重新写一个见
|
||||
|
||||
2、这次针对第二个写了[纯python版本2](纯python版本2/)的和[pyd编译好的](pyd版本)两个版本
|
||||
|
||||
### 说明
|
||||
1、建议优先使用pyd版本的(后续提供Python3.4 3.5 3.6 3.7 编译好的32为库文件),也可以自行编译,编译步骤见下文。
|
||||
|
||||
2、其次可以使用纯python版本2的(个人觉得方便调用)
|
||||
|
||||
3、最后再考虑纯python版本1的吧
|
||||
|
||||
4、以上为个人意见,两个C++版本的写法不一样,但是核心算法应该是类似的。
|
||||
|
||||
### 自行编译
|
||||
|
||||
1、首先要安装好PyQt5、编译安装对应的sip、对应的VC++编译工具
|
||||
|
||||
2、用Qt Creator 打开pro文件进行编译
|
||||
|
||||
3、进入源码中的sip文件夹
|
||||
|
||||
4、修改configure.py文件
|
||||
|
||||
```python
|
||||
# 这里是你的VC版本和对应的Qt目录中的文件夹
|
||||
config.platform = "win32-msvc2010"
|
||||
qt_path = 'D:/soft/Qt/Qt5.5.1/5.5/msvc2010'
|
||||
```
|
||||
|
||||
5、python configure.py
|
||||
|
||||
# 截图
|
||||
|
||||
![截图1](ScreenShot/1.gif)
|
BIN
图片/显示.9格式图片/ScreenShot/1.gif
Normal file
BIN
图片/显示.9格式图片/ScreenShot/1.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 290 KiB |
136
图片/显示.9格式图片/pyd版本/QtNinePatch/QtNinePatch.cpp
Normal file
136
图片/显示.9格式图片/pyd版本/QtNinePatch/QtNinePatch.cpp
Normal file
|
@ -0,0 +1,136 @@
|
|||
#include "QtNinePatch.h"
|
||||
|
||||
struct Part {
|
||||
bool stretchable;
|
||||
int pos;
|
||||
int len;
|
||||
Part()
|
||||
: stretchable(false)
|
||||
, pos(0)
|
||||
, len(0)
|
||||
{
|
||||
}
|
||||
Part(int pos, int len, bool stretchable)
|
||||
: stretchable(stretchable)
|
||||
, pos(pos)
|
||||
, len(len)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static inline bool isStretchableMarker(QRgb pixel)
|
||||
{
|
||||
return (qAlpha(pixel) >> 7) & 1;
|
||||
}
|
||||
|
||||
static QPixmap resize9patch(QImage const &image, int dw, int dh)
|
||||
{
|
||||
int sw = image.width();
|
||||
int sh = image.height();
|
||||
if (sw > 2 && sh > 2 && dw > 0 && dh > 0) {
|
||||
QPixmap pixmap(dw, dh);
|
||||
pixmap.fill(Qt::transparent);
|
||||
QPainter pr(&pixmap);
|
||||
pr.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
std::vector<Part> horz;
|
||||
std::vector<Part> vert;
|
||||
int horz_stretch = 0;
|
||||
int vert_stretch = 0;
|
||||
{
|
||||
int pos;
|
||||
QRgb last;
|
||||
QRgb next;
|
||||
pos = 0;
|
||||
last = image.pixel(1, 0);
|
||||
for (int x = 1; x < sw - 1; x++) {
|
||||
next = image.pixel(x + 1, 0);
|
||||
if (isStretchableMarker(last) != isStretchableMarker(next) || x == sw - 2) {
|
||||
bool stretchable = isStretchableMarker(last);
|
||||
int len = x - pos;
|
||||
horz.push_back(Part(pos, len, stretchable));
|
||||
if (stretchable) horz_stretch += len;
|
||||
last = next;
|
||||
pos = x;
|
||||
}
|
||||
}
|
||||
pos = 0;
|
||||
last = image.pixel(0, 1);
|
||||
for (int y = 1; y < sh - 1; y++) {
|
||||
next = image.pixel(0, y + 1);
|
||||
if (isStretchableMarker(last) != isStretchableMarker(next) || y == sh - 2) {
|
||||
bool stretchable = isStretchableMarker(last);
|
||||
int len = y - pos;
|
||||
vert.push_back(Part(pos, len, stretchable));
|
||||
if (stretchable) vert_stretch += len;
|
||||
last = next;
|
||||
pos = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
double horz_mul = 0;
|
||||
double vert_mul = 0;
|
||||
if (horz_stretch > 0) horz_mul = (double)(dw - (sw - 2 - horz_stretch)) / horz_stretch;
|
||||
if (vert_stretch > 0) vert_mul = (double)(dh - (sh - 2 - vert_stretch)) / vert_stretch;
|
||||
int dy0 = 0;
|
||||
int dy1 = 0;
|
||||
double vstretch = 0;
|
||||
for (int i = 0; i < (int)vert.size(); i++) {
|
||||
int sy0 = vert[i].pos;
|
||||
int sy1 = vert[i].pos + vert[i].len;
|
||||
if (i + 1 == (int)vert.size()) {
|
||||
dy1 = dh;
|
||||
} else if (vert[i].stretchable) {
|
||||
vstretch += (double)vert[i].len * vert_mul;
|
||||
double s = floor(vstretch);
|
||||
vstretch -= s;
|
||||
dy1 += (int)s;
|
||||
} else {
|
||||
dy1 += vert[i].len;
|
||||
}
|
||||
int dx0 = 0;
|
||||
int dx1 = 0;
|
||||
double hstretch = 0;
|
||||
for (int j = 0; j < (int)horz.size(); j++) {
|
||||
int sx0 = horz[j].pos;
|
||||
int sx1 = horz[j].pos + horz[j].len;
|
||||
if (j + 1 == (int)horz.size()) {
|
||||
dx1 = dw;
|
||||
} else if (horz[j].stretchable) {
|
||||
hstretch += (double)horz[j].len * horz_mul;
|
||||
double s = floor(hstretch);
|
||||
hstretch -= s;
|
||||
dx1 += (int)s;
|
||||
} else {
|
||||
dx1 += horz[j].len;
|
||||
}
|
||||
pr.drawImage(QRect(dx0, dy0, dx1 - dx0, dy1 - dy0), image, QRect(sx0 + 1, sy0 + 1, sx1 - sx0, sy1 - sy0));
|
||||
dx0 = dx1;
|
||||
}
|
||||
dy0 = dy1;
|
||||
}
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
QPixmap QtNinePatch::createPixmapFromNinePatchImage(const QImage &image, int dw, int dh)
|
||||
{
|
||||
int w = dw;
|
||||
int h = dh;
|
||||
if (w < image.width() || h < image.height()) { // shrink
|
||||
if (w < image.width()) w = image.width();
|
||||
if (h < image.height()) h = image.height();
|
||||
QPixmap pm1 = resize9patch(image, w, h);
|
||||
if (pm1.isNull()) return QPixmap();
|
||||
QPixmap pm2(dw, dh);
|
||||
pm2.fill(Qt::transparent);
|
||||
QPainter pr(&pm2);
|
||||
pr.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
pr.drawPixmap(0, 0, dw, dh, pm1, 0, 0, w, h);
|
||||
return pm2;
|
||||
} else {
|
||||
return resize9patch(image, w, h);
|
||||
}
|
||||
}
|
26
图片/显示.9格式图片/pyd版本/QtNinePatch/QtNinePatch.h
Normal file
26
图片/显示.9格式图片/pyd版本/QtNinePatch/QtNinePatch.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef QTNINEPATCH_H
|
||||
#define QTNINEPATCH_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#if defined(QTNINEPATCHLIB_LIBRARY)
|
||||
# define QTNINEPATCHLIBSHARED_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define QTNINEPATCHLIBSHARED_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <vector>
|
||||
|
||||
class QtNinePatch;
|
||||
|
||||
class QTNINEPATCHLIBSHARED_EXPORT QtNinePatch
|
||||
{
|
||||
|
||||
public:
|
||||
static QPixmap createPixmapFromNinePatchImage(const QImage &, int, int);
|
||||
};
|
||||
|
||||
#endif // QTNINEPATCH_H
|
38
图片/显示.9格式图片/pyd版本/QtNinePatch/QtNinePatch.pro
Normal file
38
图片/显示.9格式图片/pyd版本/QtNinePatch/QtNinePatch.pro
Normal file
|
@ -0,0 +1,38 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2018-10-25T14:12:10
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core axcontainer gui
|
||||
|
||||
#greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = QtNinePatch
|
||||
TEMPLATE = lib
|
||||
CONFIG += release
|
||||
CONFIG += warn_off exceptions_off hide_symbols
|
||||
|
||||
#CONFIG += staticlib
|
||||
#CONFIG += dll static release
|
||||
|
||||
DESTDIR = build
|
||||
DLLDESTDIR = build
|
||||
|
||||
DEFINES += QTNINEPATCHLIB_LIBRARY
|
||||
|
||||
SOURCES += QtNinePatch.cpp
|
||||
|
||||
HEADERS += QtNinePatch.h
|
||||
|
||||
unix {
|
||||
target.path = /usr/lib
|
||||
INSTALLS += target
|
||||
}
|
||||
|
||||
DEFINES += _XKEYCHECK_H
|
||||
|
||||
INCLUDEPATH += .
|
||||
INCLUDEPATH += $$[QT_INSTALL_HEADERS]
|
||||
|
||||
LIBS += -L$$[QT_INSTALL_LIBS]
|
202
图片/显示.9格式图片/pyd版本/QtNinePatch/QtNinePatch.pro.user
Normal file
202
图片/显示.9格式图片/pyd版本/QtNinePatch/QtNinePatch.pro.user
Normal file
|
@ -0,0 +1,202 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 3.5.1, 2018-10-26T00:09:02. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{52a31565-4664-45f3-a98d-2ef2ad3b26ae}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap"/>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.5.1 MSVC2010 32bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.5.1 MSVC2010 32bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.55.win32_msvc2010_kit</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">F:/Python/PyhtonTest/PyQt/QtNinePatch/build</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清理</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">在本地部署</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments"></value>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable"></value>
|
||||
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory">%{buildDir}</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">自定义执行档</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
</qtcreator>
|
BIN
图片/显示.9格式图片/pyd版本/QtNinePatch/sip/QtNinePatch.dll
Normal file
BIN
图片/显示.9格式图片/pyd版本/QtNinePatch/sip/QtNinePatch.dll
Normal file
Binary file not shown.
BIN
图片/显示.9格式图片/pyd版本/QtNinePatch/sip/QtNinePatch.pyd
Normal file
BIN
图片/显示.9格式图片/pyd版本/QtNinePatch/sip/QtNinePatch.pyd
Normal file
Binary file not shown.
14
图片/显示.9格式图片/pyd版本/QtNinePatch/sip/QtNinePatch.sip
Normal file
14
图片/显示.9格式图片/pyd版本/QtNinePatch/sip/QtNinePatch.sip
Normal file
|
@ -0,0 +1,14 @@
|
|||
%Module QtNinePatch
|
||||
%Import QtCore/QtCoremod.sip
|
||||
%Import QtGui/QtGuimod.sip
|
||||
|
||||
class QtNinePatch
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "../QtNinePatch.h"
|
||||
%End
|
||||
|
||||
public:
|
||||
static QPixmap createPixmapFromNinePatchImage(const QImage &, int, int);
|
||||
|
||||
};
|
87
图片/显示.9格式图片/pyd版本/QtNinePatch/sip/configure.py
Normal file
87
图片/显示.9格式图片/pyd版本/QtNinePatch/sip/configure.py
Normal file
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- encoding:utf-8 -*-
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import PyQt5
|
||||
from PyQt5.QtCore import PYQT_CONFIGURATION
|
||||
import sipconfig
|
||||
|
||||
|
||||
# 模块名
|
||||
moduleName = 'QtNinePatch'
|
||||
|
||||
# The name of the SIP build file generated by SIP and used by the build
|
||||
# system.
|
||||
build_file = '%s.sbf' % moduleName
|
||||
|
||||
# Get the SIP configuration information.
|
||||
config = sipconfig.Configuration()
|
||||
# pyqt5.5 + python34 + msvc 2010
|
||||
config.platform = "win32-msvc2010"
|
||||
qt_path = 'D:/soft/Qt/Qt5.5.1/5.5/msvc2010'
|
||||
print('QT_DIR: %s' % qt_path)
|
||||
|
||||
pyqtpath = os.path.dirname(PyQt5.__file__)
|
||||
print('PyQt5 path: ', pyqtpath)
|
||||
|
||||
config.sip_bin = os.path.join(pyqtpath, 'sip.exe')
|
||||
config.default_sip_dir = os.path.join(pyqtpath, 'sip')
|
||||
|
||||
sip_cmd = ' '.join([
|
||||
config.sip_bin,
|
||||
'-c', "build",
|
||||
'-b', "build/" + build_file,
|
||||
'-I', config.default_sip_dir + '/PyQt5',
|
||||
PYQT_CONFIGURATION.get('sip_flags', ''),
|
||||
'%s.sip' % moduleName,
|
||||
])
|
||||
|
||||
os.makedirs('build', exist_ok=True)
|
||||
print(sip_cmd)
|
||||
os.system(sip_cmd)
|
||||
|
||||
|
||||
# Create the Makefile.
|
||||
makefile = sipconfig.SIPModuleMakefile(
|
||||
config, build_file, dir='build'
|
||||
)
|
||||
|
||||
# Add the library we are wrapping. The name doesn't include any platform
|
||||
# specific prefixes or extensions (e.g. the 'lib' prefix on UNIX, or the
|
||||
# '.dll' extension on Windows).
|
||||
|
||||
# 添加头文件路径
|
||||
makefile.extra_include_dirs = [
|
||||
'../', '.',
|
||||
os.path.join(qt_path, 'include'),
|
||||
os.path.join(qt_path, 'include', 'QtCore'),
|
||||
os.path.join(qt_path, 'include', 'QtGui')
|
||||
]
|
||||
|
||||
# 添加用C++编译的库文件路径
|
||||
makefile.extra_lib_dirs = [
|
||||
os.path.abspath('../build'),
|
||||
os.path.join(qt_path, 'lib'),
|
||||
]
|
||||
print(makefile.extra_lib_dirs)
|
||||
|
||||
makefile.extra_libs = [
|
||||
moduleName,
|
||||
'Qt5Core',
|
||||
'Qt5Gui'
|
||||
]
|
||||
print(makefile.extra_libs)
|
||||
|
||||
# Generate the Makefile itself.
|
||||
makefile.generate()
|
||||
|
||||
shutil.copy('../build/%s.dll' % moduleName, '%s.dll' % moduleName)
|
||||
|
||||
os.chdir('build')
|
||||
os.system('nmake')
|
||||
|
||||
os.chdir('../')
|
||||
shutil.copy('build/%s.pyd' % moduleName, '%s.pyd' % moduleName)
|
||||
print('ok')
|
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
53
图片/显示.9格式图片/pyd版本/QtNinePatch/sip/testQtNinePatch.py
Normal file
53
图片/显示.9格式图片/pyd版本/QtNinePatch/sip/testQtNinePatch.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2018年10月25日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: testQtNinePatch
|
||||
@description:
|
||||
"""
|
||||
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = "Copyright (c) 2018 Irony"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
import sys
|
||||
|
||||
from PyQt5.QtGui import QImage
|
||||
from PyQt5.QtWidgets import QApplication, QLabel
|
||||
|
||||
from QtNinePatch import QtNinePatch
|
||||
|
||||
|
||||
class Label(QLabel):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Label, self).__init__(*args, **kwargs)
|
||||
#.9 格式的图片
|
||||
self.image = QImage('skin_aio_friend_bubble_pressed.9.png')
|
||||
|
||||
def showEvent(self, event):
|
||||
super(Label, self).showEvent(event)
|
||||
pixmap = QtNinePatch.createPixmapFromNinePatchImage(
|
||||
self.image, self.width(), self.height())
|
||||
self.setPixmap(pixmap)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(Label, self).resizeEvent(event)
|
||||
pixmap = QtNinePatch.createPixmapFromNinePatchImage(
|
||||
self.image, self.width(), self.height())
|
||||
self.setPixmap(pixmap)
|
||||
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
w = Label()
|
||||
w.resize(400, 200)
|
||||
w.show()
|
||||
|
||||
sys.exit(app.exec_())
|
361
图片/显示.9格式图片/纯python版本1/NinePatch.py
Normal file
361
图片/显示.9格式图片/纯python版本1/NinePatch.py
Normal file
|
@ -0,0 +1,361 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2018年10月25日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: NinePatch
|
||||
@description:
|
||||
"""
|
||||
from math import fabs
|
||||
|
||||
from PyQt5.QtCore import QRect
|
||||
from PyQt5.QtGui import QImage, QColor, QPainter, qRed, qGreen, qBlue, qAlpha
|
||||
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = "Copyright (c) 2018 Irony"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
class _Exception(Exception):
|
||||
|
||||
def __init__(self, imgW, imgH):
|
||||
self.imgW = imgW
|
||||
self.imgH = imgH
|
||||
|
||||
|
||||
class NinePatchException(Exception):
|
||||
|
||||
def __str__(self):
|
||||
return "Nine patch error"
|
||||
|
||||
|
||||
class ExceptionIncorrectWidth(_Exception):
|
||||
|
||||
def __str__(self):
|
||||
return "Input incorrect width. Mimimum width = :{imgW}".format(imgW=self.imgW)
|
||||
|
||||
|
||||
class ExceptionIncorrectWidthAndHeight(_Exception):
|
||||
|
||||
def __str__(self):
|
||||
return "Input incorrect width width and height. Minimum width = :{imgW} . Minimum height = :{imgH}".format(imgW=self.imgW, imgH=self.imgH)
|
||||
|
||||
|
||||
class ExceptionIncorrectHeight(_Exception):
|
||||
|
||||
def __str__(self):
|
||||
return "Input incorrect height. Minimum height = :{imgW}".format(imgW=self.imgW)
|
||||
|
||||
|
||||
class ExceptionNot9Patch(Exception):
|
||||
|
||||
def __str__(self):
|
||||
return "It is not nine patch image"
|
||||
|
||||
|
||||
class NinePatch:
|
||||
|
||||
def __init__(self, fileName):
|
||||
self.CachedImage = None # 缓存图片
|
||||
self.OldWidth = -1
|
||||
self.OldHeight = -1
|
||||
self.ResizeDistancesX = []
|
||||
self.ResizeDistancesY = [] # [(int,int)]数组
|
||||
self.setImage(fileName)
|
||||
|
||||
def width(self):
|
||||
return self.Image.width()
|
||||
|
||||
def height(self):
|
||||
return self.Image.height()
|
||||
|
||||
def setImage(self, fileName):
|
||||
self.Image = QImage(fileName)
|
||||
if self.Image.isNull():
|
||||
return
|
||||
|
||||
self.ContentArea = self.GetContentArea()
|
||||
self.GetResizeArea()
|
||||
if not self.ResizeDistancesX or not self.ResizeDistancesY:
|
||||
raise ExceptionNot9Patch
|
||||
|
||||
def __del__(self):
|
||||
if hasattr(self, "CachedImage"):
|
||||
del self.CachedImage
|
||||
if hasattr(self, "Image"):
|
||||
del self.Image
|
||||
|
||||
def Draw(self, painter, x, y):
|
||||
painter.drawImage(x, y, self.CachedImage)
|
||||
|
||||
def SetImageSize(self, width, height):
|
||||
resizeWidth = 0
|
||||
resizeHeight = 0
|
||||
for i in range(len(self.ResizeDistancesX)):
|
||||
resizeWidth += self.ResizeDistancesX[i][1]
|
||||
|
||||
for i in range(len(self.ResizeDistancesY)):
|
||||
resizeHeight += self.ResizeDistancesY[i][1]
|
||||
|
||||
if (width < (self.Image.width() - 2 - resizeWidth) and height < (self.Image.height() - 2 - resizeHeight)):
|
||||
raise ExceptionIncorrectWidthAndHeight(
|
||||
self.Image.width() - 2, self.Image.height() - 2)
|
||||
|
||||
if (width < (self.Image.width() - 2 - resizeWidth)):
|
||||
raise ExceptionIncorrectWidth(
|
||||
self.Image.width() - 2, self.Image.height() - 2)
|
||||
|
||||
if (height < (self.Image.height() - 2 - resizeHeight)):
|
||||
raise ExceptionIncorrectHeight(
|
||||
self.Image.width() - 2, self.Image.height() - 2)
|
||||
|
||||
if (width != self.OldWidth or height != self.OldHeight):
|
||||
self.OldWidth = width
|
||||
self.OldHeight = height
|
||||
self.UpdateCachedImage(width, height)
|
||||
|
||||
@classmethod
|
||||
def GetContentAreaRect(self, width, height):
|
||||
# print("GetContentAreaRect : width:%d height:%d" % (width, height))
|
||||
return (QRect(self.ContentArea.x(), self.ContentArea.y(), (width - (self.Image.width() - 2 - self.ContentArea.width())),
|
||||
(height - (self.Image.height() - 2 - self.ContentArea.height()))))
|
||||
|
||||
def DrawScaledPart(self, oldRect, newRect, painter):
|
||||
if (newRect.width() and newRect.height()):
|
||||
# print("DrawScaledPart newRect.width:%d newRect.height:%d" % (newRect.width() , newRect.height()))
|
||||
img = self.Image.copy(oldRect)
|
||||
img = img.scaled(newRect.width(), newRect.height())
|
||||
painter.drawImage(newRect.x(), newRect.y(), img,
|
||||
0, 0, newRect.width(), newRect.height())
|
||||
|
||||
def DrawConstPart(self, oldRect, newRect, painter):
|
||||
# print("DrawConstPart oldRect:{oldRect} newRect:{newRect}".format(oldRect = oldRect, newRect = newRect))
|
||||
img = self.Image.copy(oldRect)
|
||||
painter.drawImage(newRect.x(), newRect.y(), img, 0,
|
||||
0, newRect.width(), newRect.height())
|
||||
|
||||
def IsColorBlack(self, color):
|
||||
r = qRed(color)
|
||||
g = qGreen(color)
|
||||
b = qBlue(color)
|
||||
a = qAlpha(color)
|
||||
if a < 128:
|
||||
return False
|
||||
return r < 128 and g < 128 and b < 128
|
||||
|
||||
def GetContentArea(self):
|
||||
j = self.Image.height() - 1
|
||||
left = 0
|
||||
right = 0
|
||||
for i in range(self.Image.width()):
|
||||
if (self.IsColorBlack(self.Image.pixel(i, j)) and left == 0):
|
||||
left = i
|
||||
else:
|
||||
if (left != 0 and self.IsColorBlack(self.Image.pixel(i, j))):
|
||||
right = i
|
||||
|
||||
if (left and not right):
|
||||
right = left
|
||||
|
||||
left -= 1
|
||||
i = self.Image.width() - 1
|
||||
top = 0
|
||||
bot = 0
|
||||
|
||||
for j in range(self.Image.height()):
|
||||
if (self.IsColorBlack(self.Image.pixel(i, j)) and top == 0):
|
||||
top = j
|
||||
else:
|
||||
if (top and self.IsColorBlack(self.Image.pixel(i, j))):
|
||||
bot = j
|
||||
|
||||
if (top and not bot):
|
||||
bot = top
|
||||
top -= 1
|
||||
# print("GetContentArea left: %d top:%d %d %d" % (left, top, right - left, bot - top))
|
||||
return (QRect(left, top, right - left, bot - top))
|
||||
|
||||
def GetResizeArea(self):
|
||||
j = 0
|
||||
left = 0
|
||||
right = 0
|
||||
|
||||
for i in range(self.Image.width()):
|
||||
if (self.IsColorBlack(self.Image.pixel(i, j)) and left == 0):
|
||||
left = i
|
||||
if (left and self.IsColorBlack(self.Image.pixel(i, j)) and not self.IsColorBlack(self.Image.pixel(i + 1, j))):
|
||||
right = i
|
||||
left -= 1
|
||||
# print("ResizeDistancesX.append ", left, " ", right - left)
|
||||
self.ResizeDistancesX.append((left, right - left))
|
||||
right = 0
|
||||
left = 0
|
||||
i = 0
|
||||
top = 0
|
||||
bot = 0
|
||||
|
||||
for j in range(self.Image.height()):
|
||||
if (self.IsColorBlack(self.Image.pixel(i, j)) and top == 0):
|
||||
top = j
|
||||
|
||||
if (top and self.IsColorBlack(self.Image.pixel(i, j)) and not self.IsColorBlack(self.Image.pixel(i, j + 1))):
|
||||
bot = j
|
||||
top -= 1
|
||||
# print("ResizeDistancesY.append ", top, " ", bot - top)
|
||||
self.ResizeDistancesY.append((top, bot - top))
|
||||
top = 0
|
||||
bot = 0
|
||||
# print(self.ResizeDistancesX, len(self.ResizeDistancesX))
|
||||
# print(self.ResizeDistancesY, len(self.ResizeDistancesY))
|
||||
|
||||
def GetFactor(self, width, height, factorX, factorY):
|
||||
topResize = width - (self.Image.width() - 2)
|
||||
leftResize = height - (self.Image.height() - 2)
|
||||
for i in range(len(self.ResizeDistancesX)):
|
||||
topResize += self.ResizeDistancesX[i][1]
|
||||
factorX += self.ResizeDistancesX[i][1]
|
||||
|
||||
for i in range(len(self.ResizeDistancesY)):
|
||||
leftResize += self.ResizeDistancesY[i][1]
|
||||
factorY += self.ResizeDistancesY[i][1]
|
||||
|
||||
factorX = float(topResize) / factorX
|
||||
factorY = float(leftResize) / factorY
|
||||
return factorX, factorY
|
||||
|
||||
def UpdateCachedImage(self, width, height):
|
||||
# print("UpdateCachedImage: ", width, " " , height)
|
||||
self.CachedImage = QImage(
|
||||
width, height, QImage.Format_ARGB32_Premultiplied)
|
||||
self.CachedImage.fill(QColor(0, 0, 0, 0))
|
||||
painter = QPainter(self.CachedImage)
|
||||
factorX = 0.0
|
||||
factorY = 0.0
|
||||
factorX, factorY = self.GetFactor(width, height, factorX, factorY)
|
||||
# print("after GetFactor: ", width, height, factorX, factorY)
|
||||
lostX = 0.0
|
||||
lostY = 0.0
|
||||
x1 = 0 # for image parts X
|
||||
y1 = 0 # for image parts Y
|
||||
# widthResize # width for image parts
|
||||
# heightResize # height for image parts
|
||||
resizeX = 0
|
||||
resizeY = 0
|
||||
offsetX = 0
|
||||
offsetY = 0
|
||||
for i in range(len(self.ResizeDistancesX)):
|
||||
y1 = 0
|
||||
offsetY = 0
|
||||
lostY = 0.0
|
||||
for j in range(len(self.ResizeDistancesY)):
|
||||
widthResize = self.ResizeDistancesX[i][0] - x1
|
||||
heightResize = self.ResizeDistancesY[j][0] - y1
|
||||
|
||||
self.DrawConstPart(QRect(x1 + 1, y1 + 1, widthResize, heightResize),
|
||||
QRect(x1 + offsetX, y1 + offsetY, widthResize, heightResize), painter)
|
||||
|
||||
y2 = self.ResizeDistancesY[j][0]
|
||||
heightResize = self.ResizeDistancesY[j][1]
|
||||
resizeY = round(float(heightResize) * factorY)
|
||||
lostY += resizeY - (float(heightResize) * factorY)
|
||||
if (fabs(lostY) >= 1.0):
|
||||
if (lostY < 0):
|
||||
resizeY += 1
|
||||
lostY += 1.0
|
||||
else:
|
||||
resizeY -= 1
|
||||
lostY -= 1.0
|
||||
|
||||
self.DrawScaledPart(QRect(x1 + 1, y2 + 1, widthResize, heightResize),
|
||||
QRect(x1 + offsetX, y2 + offsetY, widthResize, resizeY), painter)
|
||||
|
||||
x2 = self.ResizeDistancesX[i][0]
|
||||
widthResize = self.ResizeDistancesX[i][1]
|
||||
heightResize = self.ResizeDistancesY[j][0] - y1
|
||||
resizeX = round(float(widthResize) * factorX)
|
||||
lostX += resizeX - (float(widthResize) * factorX)
|
||||
if (fabs(lostX) >= 1.0):
|
||||
if (lostX < 0):
|
||||
resizeX += 1
|
||||
lostX += 1.0
|
||||
else:
|
||||
resizeX -= 1
|
||||
lostX -= 1.0
|
||||
|
||||
self.DrawScaledPart(QRect(x2 + 1, y1 + 1, widthResize, heightResize),
|
||||
QRect(x2 + offsetX, y1 + offsetY, resizeX, heightResize), painter)
|
||||
|
||||
heightResize = self.ResizeDistancesY[j][1]
|
||||
self.DrawScaledPart(QRect(x2 + 1, y2 + 1, widthResize, heightResize),
|
||||
QRect(x2 + offsetX, y2 + offsetY, resizeX, resizeY), painter)
|
||||
|
||||
y1 = self.ResizeDistancesY[j][0] + self.ResizeDistancesY[j][1]
|
||||
offsetY += resizeY - self.ResizeDistancesY[j][1]
|
||||
|
||||
x1 = self.ResizeDistancesX[i][0] + self.ResizeDistancesX[i][1]
|
||||
offsetX += resizeX - self.ResizeDistancesX[i][1]
|
||||
|
||||
x1 = self.ResizeDistancesX[len(
|
||||
self.ResizeDistancesX) - 1][0] + self.ResizeDistancesX[len(self.ResizeDistancesX) - 1][1]
|
||||
widthResize = self.Image.width() - x1 - 2
|
||||
y1 = 0
|
||||
lostX = 0.0
|
||||
lostY = 0.0
|
||||
offsetY = 0
|
||||
for i in range(len(self.ResizeDistancesY)):
|
||||
self.DrawConstPart(QRect(x1 + 1, y1 + 1, widthResize, self.ResizeDistancesY[i][0] - y1),
|
||||
QRect(x1 + offsetX, y1 + offsetY, widthResize, self.ResizeDistancesY[i][0] - y1), painter)
|
||||
y1 = self.ResizeDistancesY[i][0]
|
||||
resizeY = round(float(self.ResizeDistancesY[i][1]) * factorY)
|
||||
lostY += resizeY - (float(self.ResizeDistancesY[i][1]) * factorY)
|
||||
if (fabs(lostY) >= 1.0):
|
||||
if (lostY < 0):
|
||||
resizeY += 1
|
||||
lostY += 1.0
|
||||
else:
|
||||
resizeY -= 1
|
||||
lostY -= 1.0
|
||||
|
||||
self.DrawScaledPart(QRect(x1 + 1, y1 + 1, widthResize, self.ResizeDistancesY[i][1]),
|
||||
QRect(x1 + offsetX, y1 + offsetY, widthResize, resizeY), painter)
|
||||
y1 = self.ResizeDistancesY[i][0] + self.ResizeDistancesY[i][1]
|
||||
offsetY += resizeY - self.ResizeDistancesY[i][1]
|
||||
|
||||
y1 = self.ResizeDistancesY[len(
|
||||
self.ResizeDistancesY) - 1][0] + self.ResizeDistancesY[len(self.ResizeDistancesY) - 1][1]
|
||||
heightResize = self.Image.height() - y1 - 2
|
||||
x1 = 0
|
||||
offsetX = 0
|
||||
for i in range(len(self.ResizeDistancesX)):
|
||||
self.DrawConstPart(QRect(x1 + 1, y1 + 1, self.ResizeDistancesX[i][0] - x1, heightResize),
|
||||
QRect(x1 + offsetX, y1 + offsetY, self.ResizeDistancesX[i][0] - x1, heightResize), painter)
|
||||
x1 = self.ResizeDistancesX[i][0]
|
||||
resizeX = round(float(self.ResizeDistancesX[i][1]) * factorX)
|
||||
lostX += resizeX - (float(self.ResizeDistancesX[i][1]) * factorX)
|
||||
if (fabs(lostX) >= 1.0):
|
||||
if (lostX < 0):
|
||||
resizeX += 1
|
||||
lostX += 1.0
|
||||
else:
|
||||
resizeX -= 1
|
||||
lostX += 1.0
|
||||
|
||||
self.DrawScaledPart(QRect(x1 + 1, y1 + 1, self.ResizeDistancesX[i][1], heightResize),
|
||||
QRect(x1 + offsetX, y1 + offsetY, resizeX, heightResize), painter)
|
||||
x1 = self.ResizeDistancesX[i][0] + self.ResizeDistancesX[i][1]
|
||||
offsetX += resizeX - self.ResizeDistancesX[i][1]
|
||||
|
||||
x1 = self.ResizeDistancesX[len(
|
||||
self.ResizeDistancesX) - 1][0] + self.ResizeDistancesX[len(self.ResizeDistancesX) - 1][1]
|
||||
widthResize = self.Image.width() - x1 - 2
|
||||
y1 = self.ResizeDistancesY[len(
|
||||
self.ResizeDistancesY) - 1][0] + self.ResizeDistancesY[len(self.ResizeDistancesY) - 1][1]
|
||||
heightResize = self.Image.height() - y1 - 2
|
||||
self.DrawConstPart(QRect(x1 + 1, y1 + 1, widthResize, heightResize),
|
||||
QRect(x1 + offsetX, y1 + offsetY, widthResize, heightResize), painter)
|
BIN
图片/显示.9格式图片/纯python版本1/skin_aio_friend_bubble_pressed.9.png
Normal file
BIN
图片/显示.9格式图片/纯python版本1/skin_aio_friend_bubble_pressed.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
52
图片/显示.9格式图片/纯python版本1/testNinePatch.py
Normal file
52
图片/显示.9格式图片/纯python版本1/testNinePatch.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2018年10月25日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: testNinePatch
|
||||
@description:
|
||||
"""
|
||||
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = "Copyright (c) 2018 Irony"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
import sys
|
||||
|
||||
from PyQt5.QtGui import QImage, QPainter
|
||||
from PyQt5.QtWidgets import QApplication, QLabel, QWidget
|
||||
|
||||
from NinePatch import NinePatch
|
||||
|
||||
|
||||
class Label(QWidget):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Label, self).__init__(*args, **kwargs)
|
||||
#.9 格式的图片
|
||||
self.image = NinePatch('skin_aio_friend_bubble_pressed.9.png')
|
||||
|
||||
def paintEvent(self, event):
|
||||
super(Label, self).paintEvent(event)
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHint(QPainter.Antialiasing)
|
||||
painter.setRenderHint(QPainter.SmoothPixmapTransform)
|
||||
try:
|
||||
self.image.SetImageSize(self.width(), self.height())
|
||||
self.image.Draw(painter, 0, 0)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
w = Label()
|
||||
w.resize(400, 200)
|
||||
w.show()
|
||||
|
||||
sys.exit(app.exec_())
|
140
图片/显示.9格式图片/纯python版本2/QtNinePatch.py
Normal file
140
图片/显示.9格式图片/纯python版本2/QtNinePatch.py
Normal file
|
@ -0,0 +1,140 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2018年10月25日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: QtNinePatch
|
||||
@description:
|
||||
"""
|
||||
from math import floor
|
||||
|
||||
from PyQt5.QtCore import Qt, QRect
|
||||
from PyQt5.QtGui import qAlpha, QPixmap, QPainter
|
||||
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = "Copyright (c) 2018 Irony"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
class Part:
|
||||
|
||||
def __init__(self, pos=0, length=0, stretchable=False):
|
||||
self.pos = pos
|
||||
self.length = length
|
||||
self.stretchable = stretchable
|
||||
|
||||
|
||||
def isStretchableMarker(pixel):
|
||||
return (qAlpha(pixel) >> 7) & 1
|
||||
|
||||
|
||||
def resize9patch(image, dw, dh):
|
||||
sw = image.width()
|
||||
sh = image.height()
|
||||
if sw > 2 and sh > 2 and dw > 0 and dh > 0:
|
||||
pixmap = QPixmap(dw, dh)
|
||||
pixmap.fill(Qt.transparent)
|
||||
pr = QPainter(pixmap)
|
||||
pr.setRenderHint(QPainter.Antialiasing)
|
||||
pr.setRenderHint(QPainter.SmoothPixmapTransform)
|
||||
|
||||
horz = []
|
||||
vert = []
|
||||
horz_stretch = 0
|
||||
vert_stretch = 0
|
||||
|
||||
pos = 0
|
||||
last = image.pixel(1, 0)
|
||||
for x in range(1, sw - 1):
|
||||
nextP = image.pixel(x + 1, 0)
|
||||
if isStretchableMarker(last) != isStretchableMarker(nextP) or x == sw - 2:
|
||||
stretchable = isStretchableMarker(last)
|
||||
length = x - pos
|
||||
horz.append(Part(pos, length, stretchable))
|
||||
if stretchable:
|
||||
horz_stretch += length
|
||||
last = nextP
|
||||
pos = x
|
||||
pos = 0
|
||||
last = image.pixel(0, 1)
|
||||
for y in range(1, sh - 1):
|
||||
nextP = image.pixel(0, y + 1)
|
||||
if isStretchableMarker(last) != isStretchableMarker(nextP) or y == sh - 2:
|
||||
stretchable = isStretchableMarker(last)
|
||||
length = y - pos
|
||||
vert.append(Part(pos, length, stretchable))
|
||||
if stretchable:
|
||||
vert_stretch += length
|
||||
last = nextP
|
||||
pos = y
|
||||
|
||||
horz_mul = 0
|
||||
vert_mul = 0
|
||||
if horz_stretch > 0:
|
||||
horz_mul = float((dw - (sw - 2 - horz_stretch)) / horz_stretch)
|
||||
if vert_stretch > 0:
|
||||
vert_mul = float((dh - (sh - 2 - vert_stretch)) / vert_stretch)
|
||||
dy0 = 0
|
||||
dy1 = 0
|
||||
vstretch = 0
|
||||
len_vert = len(vert)
|
||||
len_horz = len(horz)
|
||||
for i in range(len_vert):
|
||||
sy0 = vert[i].pos
|
||||
sy1 = vert[i].pos + vert[i].length
|
||||
if i + 1 == len_vert:
|
||||
dy1 = dh
|
||||
elif vert[i].stretchable:
|
||||
vstretch += float(vert[i].length * vert_mul)
|
||||
s = floor(vstretch)
|
||||
vstretch -= s
|
||||
dy1 += int(s)
|
||||
else:
|
||||
dy1 += vert[i].length
|
||||
dx0 = 0
|
||||
dx1 = 0
|
||||
hstretch = 0
|
||||
for j in range(len_horz):
|
||||
sx0 = horz[j].pos
|
||||
sx1 = horz[j].pos + horz[j].length
|
||||
if j + 1 == len_horz:
|
||||
dx1 = dw
|
||||
elif horz[j].stretchable:
|
||||
hstretch += float(horz[j].length * horz_mul)
|
||||
s = floor(hstretch)
|
||||
hstretch -= s
|
||||
dx1 += int(s)
|
||||
else:
|
||||
dx1 += horz[j].length
|
||||
pr.drawImage(QRect(dx0, dy0, dx1 - dx0, dy1 - dy0),
|
||||
image, QRect(sx0 + 1, sy0 + 1, sx1 - sx0, sy1 - sy0))
|
||||
dx0 = dx1
|
||||
dy0 = dy1
|
||||
return pixmap
|
||||
return QPixmap()
|
||||
|
||||
|
||||
def createPixmapFromNinePatchImage(image, dw, dh):
|
||||
w = dw
|
||||
h = dh
|
||||
if w < image.width() or h < image.height(): # shrink
|
||||
w = max(image.width(), w)
|
||||
h = max(image.height(), h)
|
||||
pm1 = resize9patch(image, w, h)
|
||||
if pm1.isNull():
|
||||
return QPixmap()
|
||||
pm2 = QPixmap(dw, dh)
|
||||
pm2.fill(Qt.transparent)
|
||||
pr = QPainter(pm2)
|
||||
pr.setRenderHint(QPainter.Antialiasing)
|
||||
pr.setRenderHint(QPainter.SmoothPixmapTransform)
|
||||
pr.drawPixmap(0, 0, dw, dh, pm1, 0, 0, w, h)
|
||||
return pm2
|
||||
else:
|
||||
return resize9patch(image, dw, dh)
|
BIN
图片/显示.9格式图片/纯python版本2/skin_aio_friend_bubble_pressed.9.png
Normal file
BIN
图片/显示.9格式图片/纯python版本2/skin_aio_friend_bubble_pressed.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
53
图片/显示.9格式图片/纯python版本2/testQtNinePatch.py
Normal file
53
图片/显示.9格式图片/纯python版本2/testQtNinePatch.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2018年10月25日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: testQtNinePatch
|
||||
@description:
|
||||
"""
|
||||
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = "Copyright (c) 2018 Irony"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
import sys
|
||||
|
||||
from PyQt5.QtGui import QImage
|
||||
from PyQt5.QtWidgets import QApplication, QLabel
|
||||
|
||||
import QtNinePatch
|
||||
|
||||
|
||||
class Label(QLabel):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Label, self).__init__(*args, **kwargs)
|
||||
#.9 格式的图片
|
||||
self.image = QImage('skin_aio_friend_bubble_pressed.9.png')
|
||||
|
||||
def showEvent(self, event):
|
||||
super(Label, self).showEvent(event)
|
||||
pixmap = QtNinePatch.createPixmapFromNinePatchImage(
|
||||
self.image, self.width(), self.height())
|
||||
self.setPixmap(pixmap)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
super(Label, self).resizeEvent(event)
|
||||
pixmap = QtNinePatch.createPixmapFromNinePatchImage(
|
||||
self.image, self.width(), self.height())
|
||||
self.setPixmap(pixmap)
|
||||
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
w = Label()
|
||||
w.resize(400, 200)
|
||||
w.show()
|
||||
|
||||
sys.exit(app.exec_())
|
Loading…
Reference in a new issue