Qt 图片处理(一) 实时绘制曲线、箭头、文本、矩形、圆形

前言

本系列文章主要记录我学习qt时t写的一些测试程序,偏向于qt图形绘制、图片处理等等。


本文主要实现鼠标绘制曲线、箭头、圆形、矩形、文本内容等等,该功能可以集成到截图组件中,对图像进行二次处理。
截图组件文章链接:Qt 简单截图工具(一) 高仿QQ截屏 滑动截屏
本文程序运行结果如下:
在这里插入图片描述

一、实现原理

  将所有绘制相关的数据整理为结构体,通过结构体来绘制图形,一个图形就是一个结构体对象。这种方式可以更好的维护所有图形对象,例如画笔样式、画刷样式的修改可以走同一套逻辑进行修改,之后想添加其他类型的图形只需要修改结构体对象即可。

二、具体实现

  • 结构体定义

  主要通过绘制图形点集来绘制相应图形,其余属性大多为画笔样式、画刷样式等等。

代码如下:

enum DrawStyle
{
	DRAW_Line = 0,								//线
	DRAW_Rectangle,								//矩形
	DRAW_Circul,								//圆形
	DRAW_Arrow,									//箭头
	DRAW_Text,									//文本
	DRAW_Mosaic,								//马赛克
	DRAW_Marker_Pen								//马克笔
};

struct LineStyle
{
	QVector<QPoint> points_;					//绘制图形点集
	QColor color_;								//线颜色
	int width_;									//线宽度
	Qt::PenStyle pen_style_;					//线样式
	DrawStyle draw_style_;						//绘制图形样式
	QString content_;							//文本内容
	QFont font_;								//文本样式--暂不设置
};
  • 主要代码

  因为该组件实现较为简单,区分不同绘制类型进行绘制即可,这里不再详细解释代码实现逻辑,详情见注释。

代码如下:

DrawToDecide::DrawToDecide(QWidget* parent)
	: QWidget(parent)
	, mouse_pressed_(false)
	, draw_style_(DRAW_Line)
{
	this->setFixedSize(600, 600);

	QVector<QPushButton*> btn_draw;
	btn_draw.push_back(new QPushButton(QStringLiteral("线")));
	btn_draw.push_back(new QPushButton(QStringLiteral("矩形")));
	btn_draw.push_back(new QPushButton(QStringLiteral("圆形")));
	btn_draw.push_back(new QPushButton(QStringLiteral("箭头")));
	btn_draw.push_back(new QPushButton(QStringLiteral("文本")));
	btn_draw.push_back(new QPushButton(QStringLiteral("马赛克")));
	btn_draw.push_back(new QPushButton(QStringLiteral("马克笔")));

	com_style_ = new QComboBox();
	com_style_->setCursor(Qt::ArrowCursor);
	QStringList list_style;
	list_style << QStringLiteral("SolidLine") << QStringLiteral("DotLine") << QStringLiteral("DashDotLine") << QStringLiteral("DashLine") << QStringLiteral("DashDotDotLine");
	com_style_->addItems(list_style);
	com_style_->setItemData(0, (int)Qt::SolidLine);
	com_style_->setItemData(1, (int)Qt::DotLine);
	com_style_->setItemData(2, (int)Qt::DashDotLine);
	com_style_->setItemData(3, (int)Qt::DashLine);
	com_style_->setItemData(4, (int)Qt::DashDotDotLine);

	com_color_ = new QComboBox();
	com_color_->setCursor(Qt::ArrowCursor);
	QStringList list_color;
	list_color << QStringLiteral("黑") << QStringLiteral("红") << QStringLiteral("绿") << QStringLiteral("蓝");
	com_color_->addItems(list_color);
	com_color_->setItemData(0, QColor(0, 0, 0));
	com_color_->setItemData(1, QColor(255, 0, 0));
	com_color_->setItemData(2, QColor(0, 255, 0));
	com_color_->setItemData(3, QColor(0, 0, 255));

	com_width_ = new QComboBox();
	com_width_->setCursor(Qt::ArrowCursor);
	QStringList list_width;
	list_width << QStringLiteral("1") << QStringLiteral("2") << QStringLiteral("3") << QStringLiteral("4") << QStringLiteral("5") << QStringLiteral("6");
	com_width_->addItems(list_width);
	com_width_->setItemData(0, 1);
	com_width_->setItemData(1, 2);
	com_width_->setItemData(2, 3);
	com_width_->setItemData(3, 4);
	com_width_->setItemData(4, 5);
	com_width_->setItemData(5, 6);

	QVBoxLayout* main_layout = new QVBoxLayout();
	QHBoxLayout* top_button_layout = new QHBoxLayout();
	QHBoxLayout* top_com_layout = new QHBoxLayout();
	for (int i = 0; i < btn_draw.size(); i++)
	{
		top_button_layout->addWidget(btn_draw.at(i));
		btn_draw.at(i)->setCursor(Qt::ArrowCursor);
	}
	top_com_layout->addWidget(com_style_);
	top_com_layout->addWidget(com_color_);
	top_com_layout->addWidget(com_width_);
	main_layout->addLayout(top_button_layout);
	main_layout->addLayout(top_com_layout);
	main_layout->addStretch();

	connect(btn_draw.at(0), &QPushButton::clicked, this, [=]() {
		draw_style_ = DRAW_Line;
		});
	connect(btn_draw.at(1), &QPushButton::clicked, this, [=]() {
		draw_style_ = DRAW_Rectangle;
		});
	connect(btn_draw.at(2), &QPushButton::clicked, this, [=]() {
		draw_style_ = DRAW_Circul;
		});
	connect(btn_draw.at(3), &QPushButton::clicked, this, [=]() {
		draw_style_ = DRAW_Arrow;
		});
	connect(btn_draw.at(4), &QPushButton::clicked, this, [=]() {
		draw_style_ = DRAW_Text;
		});
	connect(btn_draw.at(5), &QPushButton::clicked, this, [=]() {
		draw_style_ = DRAW_Mosaic;
		});
	connect(btn_draw.at(6), &QPushButton::clicked, this, [=]() {
		draw_style_ = DRAW_Marker_Pen;
		});
	this->setLayout(main_layout);
	QCursor cursor(QPixmap(":/PracticeOne/Resources/pen.png"));
	this->setCursor(cursor);

	line_eidit_ = new QLineEdit();
	line_eidit_->setObjectName("custom_draw_text_input");
	//设置透明色生效
	line_eidit_->window()->setAttribute(Qt::WA_TranslucentBackground, true);
	line_eidit_->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
	connect(line_eidit_, &QLineEdit::editingFinished, this, &DrawToDecide::LineEditFinishText);
}

DrawToDecide::~DrawToDecide()
{
}


void DrawToDecide::DrawShape(QPainter& _painter, LineStyle* _line_style)
{
	QTextOption toption(Qt::AlignCenter);
	toption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
	switch (_line_style->draw_style_)
	{
	case DRAW_Line:
		_painter.drawPolyline(QPolygon(_line_style->points_));
		break;
	case DRAW_Rectangle:
		_painter.drawRect(QRect(_line_style->points_.at(0), _line_style->points_.at(1)));
		break;
	case DRAW_Circul:
		_painter.drawEllipse(QRect(_line_style->points_.at(0), _line_style->points_.at(1)));
		break;
	case DRAW_Arrow:
		_painter.setBrush(_line_style->color_);
		_painter.drawPolygon(QPolygon(GetArrowShape(_line_style->points_.at(0), _line_style->points_.at(1))));
		_painter.setBrush(Qt::NoBrush);
		break;
	case DRAW_Text:

		_painter.drawText(QRect(_line_style->points_.at(0), _line_style->points_.at(1)), _line_style->content_, toption);
		break;
	default:
		break;
	}

}

QVector<QPoint> DrawToDecide::GetArrowShape(QPoint _start_point, QPoint _end_point)
{
	QVector<QPoint> arrow_points;
	float x1 = _start_point.x();
	float y1 = _start_point.y();
	float x2 = _end_point.x();
	float y2 = _end_point.y();

	double angle = atan2(y2 - y1, x2 - x1);				//计算线段的夹角
	float arrow_length_long = 20;						//箭头边的长度--长
	float arrow_angle_long = 0.6;						//箭头与线段的夹角--长
	float arrow_length_short = 12;						//箭头边的长度--短
	float arrow_angle_short = 0.3;						//箭头与线段的夹角--短

	float point_long_x1 = x2 - arrow_length_long * cos(angle - arrow_angle_long);
	float point_long_y1 = y2 - arrow_length_long * sin(angle - arrow_angle_long);
	float point_long_x2 = x2 - arrow_length_long * cos(angle + arrow_angle_long);
	float point_long_y2 = y2 - arrow_length_long * sin(angle + arrow_angle_long);
	float point_short_x1 = x2 - arrow_length_short * cos(angle - arrow_angle_short);
	float point_short_y1 = y2 - arrow_length_short * sin(angle - arrow_angle_short);
	float point_short_x2 = x2 - arrow_length_short * cos(angle + arrow_angle_short);
	float point_short_y2 = y2 - arrow_length_short * sin(angle + arrow_angle_short);

	arrow_points.append(_start_point);
	arrow_points.append(QPoint(point_short_x1, point_short_y1));
	arrow_points.append(QPoint(point_long_x1, point_long_y1));
	arrow_points.append(_end_point);
	arrow_points.append(QPoint(point_long_x2, point_long_y2));
	arrow_points.append(QPoint(point_short_x2, point_short_y2));
	arrow_points.append(_start_point);

	return arrow_points;
}

void DrawToDecide::LineEditFinishText()
{
	QString lineedit_text = line_eidit_->text();
	line_eidit_->clear();
	line_eidit_->close();
	lines_.at(lines_count_)->content_ = lineedit_text;
	qDebug() << lineedit_text;
}

void DrawToDecide::mouseMoveEvent(QMouseEvent* event)
{
	if (mouse_pressed_)
	{
		switch (draw_style_)
		{
		case DRAW_Line:
			points_.append(event->pos());
			lines_.at(lines_count_)->points_ = points_;
			break;
		case DRAW_Rectangle:
			lines_.at(lines_count_)->points_[1] = event->pos();
			break;
		case DRAW_Circul:
			lines_.at(lines_count_)->points_[1] = event->pos();
			break;
		case DRAW_Arrow:
			lines_.at(lines_count_)->points_[1] = event->pos();
			break;
		case DRAW_Text:
			lines_.at(lines_count_)->points_[1] = event->pos();
			break;
		case DRAW_Mosaic:
			break;
		case DRAW_Marker_Pen:
			break;
		default:
			break;
		}

	}
	update();
}

void DrawToDecide::paintEvent(QPaintEvent* event)
{
	QPainter painter(this);
	painter.setRenderHint(QPainter::Antialiasing);
	for (int i = 0; i < lines_.size(); i++)
	{
		LineStyle* line_style = lines_.at(i);
		QPen pen;
		pen.setWidth(line_style->width_);
		pen.setColor(line_style->color_);
		pen.setStyle(line_style->pen_style_);
		painter.setPen(pen);
		DrawShape(painter, line_style);
	}
}

void DrawToDecide::mousePressEvent(QMouseEvent* event)
{
	if (event->button() == Qt::LeftButton)
	{
		mouse_pressed_ = true;

		LineStyle* line_style = new LineStyle();
		line_style->color_ = com_color_->currentData().value<QColor>();
		line_style->width_ = com_width_->currentData().toInt();
		line_style->draw_style_ = draw_style_;
		line_style->pen_style_ = (Qt::PenStyle)com_style_->currentData().toInt();
		lines_.push_back(line_style);
		lines_count_ = lines_.count() - 1;
		points_.clear();
		switch (draw_style_)
		{
		case DRAW_Line:
			break;
		case DRAW_Rectangle:
			lines_.at(lines_count_)->points_.append(event->pos());
			lines_.at(lines_count_)->points_.append(event->pos());
			break;
		case DRAW_Circul:
			lines_.at(lines_count_)->points_.append(event->pos());
			lines_.at(lines_count_)->points_.append(event->pos());
			break;
		case DRAW_Arrow:
			lines_.at(lines_count_)->points_.append(event->pos());
			lines_.at(lines_count_)->points_.append(event->pos());
			break;
		case DRAW_Text:
			lines_.at(lines_count_)->points_.append(event->pos());
			lines_.at(lines_count_)->points_.append(event->pos());
			break;
		case DRAW_Mosaic:
			break;
		case DRAW_Marker_Pen:
			break;
		default:
			break;
		}
	}
	update();
}

void DrawToDecide::mouseReleaseEvent(QMouseEvent* event)
{
	mouse_pressed_ = false;
	switch (draw_style_)
	{
	case DRAW_Line:
		break;
	case DRAW_Rectangle:
		lines_.at(lines_count_)->points_[1] = event->pos();
		break;
	case DRAW_Circul:
		lines_.at(lines_count_)->points_[1] = event->pos();
		break;
	case DRAW_Arrow:
		lines_.at(lines_count_)->points_[1] = event->pos();
		break;
	case DRAW_Text:
		lines_.at(lines_count_)->points_[1] = event->pos();
		//输入框位置大小处理
		line_eidit_->move(event->globalPos() - (lines_.at(lines_count_)->points_[1] - lines_.at(lines_count_)->points_[0]));
		line_eidit_->setFixedSize((lines_.at(lines_count_)->points_[1] - lines_.at(lines_count_)->points_[0]).x(), (lines_.at(lines_count_)->points_[1] - lines_.at(lines_count_)->points_[0]).y());
		line_eidit_->show();
		break;
	case DRAW_Mosaic:
		break;
	case DRAW_Marker_Pen:
		break;
	default:
		break;
	}
	update();
}

总结

如果此文帮助到你( •̀ ω •́ )✧,动动小手点个赞可好O(∩_∩)O。

原创文章,转载请标明本文出处。
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Qt是一个跨平台的应用程序开发框架,它提供了丰富的图形界面组件和功能库。C++是Qt的主要编程语言,而QChart是Qt提供的一个用于绘制图表的模块。 实时动态绘制曲线是指通过不断更新数据,并在图表上实时展示出来,形成曲线的变化过程。在Qt中使用QChart实现实时动态绘制曲线,可以按照以下步骤进行: 1. 首先,引入必要的头文件和命名空间: #include <QtWidgets/QApplication> #include <QtWidgets/QMainWindow> #include <QtCharts/QChartView> #include <QtCharts/QLineSeries> #include <QTimer> QT_CHARTS_USE_NAMESPACE 2. 创建主窗口,并设置布局: QMainWindow window; QHBoxLayout *mainLayout = new QHBoxLayout; window.setLayout(mainLayout); 3. 创建一个QChart对象,并设置为主窗口的中心部件: QLineSeries *series = new QLineSeries; QChart *chart = new QChart; chart->addSeries(series); chart->createDefaultAxes(); chart->legend()->hide(); QChartView *chartView = new QChartView(chart); mainLayout->addWidget(chartView); 4. 创建一个定时器,并设置定时器的超时槽函数。在该槽函数中更新曲线数据,并重新绘制QTimer *timer = new QTimer; QObject::connect(timer, &QTimer::timeout, [&series]() { static qreal x = 0; static qreal y = 0; series->append(x, y); // 更新数据 x++; y++; }); 5. 启动定时器,并显示主窗口: timer->start(100); // 设置定时器间隔,单位为毫秒 window.show(); return app.exec(); 通过以上步骤,我们可以在Qt中使用QChart实现实时动态绘制曲线。定时器每隔一定的时间间隔触发,更新曲线的数据,并实时绘制在图表上,从而实现曲线的动态变化效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦醒梦起

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值