c++ 实现图标编辑器核心部件

解决方案:



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();
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值