解决方案:
moc_iconeditor.cpp
/****************************************************************************
** Meta object code from reading C++ file 'iconeditor.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.4.0)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
#include "../../iconeditor.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'iconeditor.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
#error "This file was generated using the moc from 5.4.0. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif
QT_BEGIN_MOC_NAMESPACE
struct qt_meta_stringdata_iconEditor_t {
QByteArrayData data[5];
char stringdata[48];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
qptrdiff(offsetof(qt_meta_stringdata_iconEditor_t, stringdata) + ofs \
- idx * sizeof(QByteArrayData)) \
)
static const qt_meta_stringdata_iconEditor_t qt_meta_stringdata_iconEditor = {
{
QT_MOC_LITERAL(0, 0, 10), // "iconEditor"
QT_MOC_LITERAL(1, 11, 8), // "penColor"
QT_MOC_LITERAL(2, 20, 9), // "iconImage"
QT_MOC_LITERAL(3, 30, 10), // "zoomFactor"
QT_MOC_LITERAL(4, 41, 6) // "size_t"
},
"iconEditor\0penColor\0iconImage\0zoomFactor\0"
"size_t"
};
#undef QT_MOC_LITERAL
static const uint qt_meta_data_iconEditor[] = {
// content:
7, // revision
0, // classname
0, 0, // classinfo
0, 0, // methods
3, 14, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
// properties: name, type, flags
1, QMetaType::QColor, 0x00095103,
2, QMetaType::QImage, 0x00095103,
3, 0x80000000 | 4, 0x0009510b,
0 // eod
};
void iconEditor::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
Q_UNUSED(_o);
Q_UNUSED(_id);
Q_UNUSED(_c);
Q_UNUSED(_a);
}
const QMetaObject iconEditor::staticMetaObject = {
{ &QWidget::staticMetaObject, qt_meta_stringdata_iconEditor.data,
qt_meta_data_iconEditor, qt_static_metacall, Q_NULLPTR, Q_NULLPTR }
};
const QMetaObject *iconEditor::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
void *iconEditor::qt_metacast(const char *_clname)
{
if (!_clname) return Q_NULLPTR;
if (!strcmp(_clname, qt_meta_stringdata_iconEditor.stringdata))
return static_cast<void*>(const_cast< iconEditor*>(this));
return QWidget::qt_metacast(_clname);
}
int iconEditor::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QWidget::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
#ifndef QT_NO_PROPERTIES
if (_c == QMetaObject::ReadProperty) {
void *_v = _a[0];
switch (_id) {
case 0: *reinterpret_cast< QColor*>(_v) = penColor(); break;
case 1: *reinterpret_cast< QImage*>(_v) = iconImage(); break;
case 2: *reinterpret_cast< size_t*>(_v) = zoomFactor(); break;
default: break;
}
_id -= 3;
}
else if (_c == QMetaObject::WriteProperty) {
void *_v = _a[0];
switch (_id) {
case 0: setPenColor(*reinterpret_cast< QColor*>(_v)); break;
case 1: setIconImage(*reinterpret_cast< QImage*>(_v)); break;
case 2: setZoomFactor(*reinterpret_cast< size_t*>(_v)); break;
default: break;
}
_id -= 3;
}
else if (_c == QMetaObject::ResetProperty) {
_id -= 3;
}
else if (_c == QMetaObject::QueryPropertyDesignable) {
_id -= 3;
}
else if (_c == QMetaObject::QueryPropertyScriptable) {
_id -= 3;
}
else if (_c == QMetaObject::QueryPropertyStored) {
_id -= 3;
}
else if (_c == QMetaObject::QueryPropertyEditable) {
_id -= 3;
}
else if (_c == QMetaObject::QueryPropertyUser) {
_id -= 3;
}
else if (_c == QMetaObject::RegisterPropertyMetaType) {
if (_id < 3)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 3;
}
#endif // QT_NO_PROPERTIES
return _id;
}
QT_END_MOC_NAMESPACE
qrc_iconeditor.cpp
/****************************************************************************
** Resource object code
**
** Created by: The Resource Compiler for Qt version 5.4.0
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
#ifdef QT_NAMESPACE
# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
# define QT_RCC_MANGLE_NAMESPACE0(x) x
# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b
# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)
# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \
QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))
#else
# define QT_RCC_PREPEND_NAMESPACE(name) name
# define QT_RCC_MANGLE_NAMESPACE(name) name
#endif
#ifdef QT_NAMESPACE
namespace QT_NAMESPACE {
#endif
#ifdef QT_NAMESPACE
}
#endif
int QT_RCC_MANGLE_NAMESPACE(qInitResources_iconeditor)();
int QT_RCC_MANGLE_NAMESPACE(qInitResources_iconeditor)()
{
return 1;
}
int QT_RCC_MANGLE_NAMESPACE(qCleanupResources_iconeditor)();
int QT_RCC_MANGLE_NAMESPACE(qCleanupResources_iconeditor)()
{
return 1;
}
namespace {
struct initializer {
initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources_iconeditor)(); }
~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources_iconeditor)(); }
} dummy;
}
iconeditor.h
#ifndef ICONEDITOR_H
#define ICONEDITOR_H
#include <qwidget.h>
#include <qimage.h>
#include <qcolor.h>
class iconEditor : public QWidget
{
Q_OBJECT
Q_PROPERTY(QColor penColor READ penColor WRITE setPenColor)
Q_PROPERTY(QImage iconImage READ iconImage WRITE setIconImage)
Q_PROPERTY(size_t zoomFactor READ zoomFactor WRITE setZoomFactor)
private:
const static size_t DEFAULT_ZOOM = 0x00000008;//默认缩放
const static size_t DEFAULT_PIXEL = 0x00000010;//默认像素
const static size_t DEFAULT_FILL = 0x000000FF;//默认填充
const static size_t MIN_ZOOM = 0x00000003;//最小缩放
const static size_t MAX_ALPHA = 0x000000FF;//最大透明
public:
iconEditor(QWidget* = NULL);
~iconEditor() = default;
public:
void setPenColor(const QColor&);
const QColor penColor()const{ return m_color; }
void setZoomFactor(const size_t);
const size_t zoomFactor() const{ return m_zoom; }
void setIconImage(const QImage&);
const QImage iconImage()const { return m_image; }
QSize sizeHint()const;
protected:
void mousePressEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*);
void paintEvent(QPaintEvent*);
private:
void setImagePixel(const QPoint&, bool);
QRect pixelRect(int, int)const;
private:
size_t m_zoom;
QColor m_color;
QImage m_image;
};
#endif // ICONEDITOR_H
iconeditor.cpp
#include "iconeditor.h"
#include <qpainter.h>
#include <qevent.h>
iconEditor::iconEditor(QWidget *parent)
: QWidget(parent),
m_color(Qt::black),
m_zoom(DEFAULT_ZOOM),
m_image(QImage(DEFAULT_PIXEL,DEFAULT_PIXEL,QImage::Format_RGB32)){
//当改变大小时。窗口部件的内容并没有发生变化,而且内容仍旧保留从窗口部件的左上角开始的特性
//当重新定义窗口部件的大小是,通过使用这个信息就避免重新绘制已经显示的区域
setAttribute(Qt::WA_StaticContents);
//设置尺寸策略
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
//图像填充为透明
m_image.fill(qRgba(DEFAULT_FILL, DEFAULT_FILL, DEFAULT_FILL, MAX_ALPHA));
}
QSize iconEditor::sizeHint()const{
//图像大小*缩小因子得合适大小
QSize size = m_zoom * m_image.size();
//当大于最小因子后 就要有网格,因此留出一像素
if (m_zoom > MIN_ZOOM) size += QSize(1, 1);
//返回大小
return size;
}
void iconEditor::setPenColor(const QColor& newColor){
if (&m_color == &newColor) return;
//设置画笔颜色
m_color = newColor;
}
void iconEditor::setIconImage(const QImage& newImage){
if (&m_image == &newImage) return;//如果相同就不进行设置
//转图片的格式
m_image = newImage.convertToFormat(QImage::Format_ARGB32);
update();//重绘
updateGeometry();//自适应大小
}
void iconEditor::setZoomFactor(const size_t newZoom){
if (m_zoom == newZoom) return;//如果相同就不进行设置
m_zoom = newZoom ? newZoom : 1;//防止缩小因子为0 因为可能做除数
update();//重绘
updateGeometry();//自适应大小
}
void iconEditor::paintEvent(QPaintEvent* event){
QPainter painter(this);
//画笔
//获得宽高
int width = m_image.width();
int height = m_image.height();
//如果大于最小的缩小因子,那么就要绘制网格
if (m_zoom > MIN_ZOOM){
//调色板获得窗口颜色 以设置画笔
painter.setPen(palette().foreground().color());
//竖线
for (int x = 0; x <= width; ++x)
painter.drawLine(m_zoom * x, 0, m_zoom * x,m_zoom * height);
//横线
for (int y = 0; y <= height; ++y)
painter.drawLine(0, m_zoom * y, width * m_zoom, m_zoom * y);
}
for (int x = 0; x <= width; ++x){
for (int y = 0; y <= height; ++y){
QRect rect = pixelRect(x, y);//获得矩形
//对落在矩形内的面积进行绘制
if (!event->region().intersected(rect).isEmpty()){
//获得颜色
QColor color = QColor::fromRgba(m_image.pixel(x, y));
//如果并非完全不透明,就先绘制白色背景
if (color.alpha() < MAX_ALPHA)
painter.fillRect(rect, Qt::white);
//填充颜色
painter.fillRect(rect, color);
}
}
}
}
inline QRect iconEditor::pixelRect(int x, int y)const{
//QRect(x,y,w,h)
return m_zoom > MIN_ZOOM ?
QRect(m_zoom * x + 1, m_zoom * y + 1, m_zoom - 1, m_zoom - 1) :
QRect(m_zoom * x, m_zoom * y, m_zoom, m_zoom);
}
void iconEditor::mousePressEvent(QMouseEvent* event){
//左键设置颜色 右键清空
if (event->button() == Qt::LeftButton)
setImagePixel(event->pos(), true);
else if (event->button() == Qt::RightButton)
setImagePixel(event->pos(), false);
}
void iconEditor::mouseMoveEvent(QMouseEvent* event){
//左键设置颜色,右键清空
if (event->buttons() & Qt::LeftButton)
setImagePixel(event->pos(), true);
else if (event->buttons() & Qt::RightButton)
setImagePixel(event->pos(), false);
}
void iconEditor::setImagePixel(const QPoint& pos, bool opaque){
int x = pos.x() / m_zoom;
int y = pos.y() / m_zoom;
//获得矩形的x y
//检测是否在图形中
if (!m_image.rect().contains(x, y)) return;
//如果要设置颜色 颜色为当前画笔的颜色
if (opaque) m_image.setPixel(x, y, penColor().rgba());
else m_image.setPixel(x, y, qRgba(DEFAULT_FILL,DEFAULT_FILL,DEFAULT_FILL,MAX_ALPHA));
//否则清空
//更新点
update(pixelRect(x, y));
}
main.cpp
#include "iconeditor.h"
#include <QtWidgets/QApplication>
#include <qmainwindow.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow* window = new QMainWindow();
iconEditor* editor = new iconEditor(window);
window->setCentralWidget(editor);
window->show();
return a.exec();
}