Qt绘图 day9

news2024/11/25 9:49:57

Qt绘图 day9

基本绘图流程

  • Qt的绘制系统支持在屏幕和打印设备上使用相同的API进行绘制,主要基于QPainter、QPaintDevice和QPaintEngine类。

    • QPainter:用于执行绘图操作
    • QPaintDevice:用于二维空间的抽象
    • QPainEngine:提供绘图器在不同类型的设备上绘图的接口
      在这里插入图片描述
  • QPainter中提供了一些便捷函数来绘制常用的图形,还可以设置线条,边框的画笔以及进行填充个的画刷,所有对空间的绘图操作都要放进函数paintEvent()中,否则绘图无法显示

  • 绘图流程

    • 1.创建画家
    • 2.设置绘图设备
    • 3.进行绘制
    • 4.让画家离开绘图设备
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		//1.创建一个画家
		QPainter painter;
		//2.设置绘图设备
		painter.begin(this);
		//3.画一条线
		painter.drawLine(0, 0, this->width(), this->height());
		//4.让画家离开绘图设备
		painter.end();
	}
  • QPainter提供的一些其他常用图形绘图函数
函数功能函数功能
drawChord绘制弦drawPolygon绘制多边形
drawArc绘制圆弧drawPoint绘制点
drawConvexPolygon绘制凸多边形drawPolyline绘制折线
drawElipse绘制椭圆drawRect绘制矩形
drawLine绘制线条drawRoundedRect绘制圆角矩形
drawPie绘制扇形fillRect绘制填充矩形
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{

	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		qDebug() << __FUNCTION__;

		//1.创建一个画家
		QPainter painter;
		//设置绘图设备
		painter.begin(this);

		//画一条线
		//painter.drawLine(0, 0, this->width(), this->height());

		QList<QPointF> list{
			{width() / 2.0,height() / 4.0},
			{width() * 3 / 4.0,height() * 3 / 4.0},
			{width() / 4.0,height() * 3 / 4.0},
			//{width() / 2.0,height() / 4.0}
		};
		//绘制折现,一般把多个点一对一对的连接起来,不是每两个点相连
		//painter.drawLines(list);

		//绘制点与点之间连线,这里想连接成一个三角形就必须要第四条线
		//painter.drawPolyline(list.data(),list.size());

		//绘制多边形,这里就不需要第四条线,也可以连接成一个三角形
		painter.drawPolygon(list.data(),list.size() );
		//让画家离开绘图设备
		painter.end();
	}

private:
};
int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

使用画笔

  • 给painter设置一个画笔QPen可以实现绘制线条不同的yanse
    • Pen有样式(style),宽度(width),颜色(brush),笔帽样式(capStyle)与连接方式(joinStyle)
  • style使用Qt::PenStyle定义线条类型,默认是Qt::PenStyle::SolidLine
  • brush用与填充画笔生成的笔触,使用QBrush类来指定画笔颜色
  • capStyle帽样式绝对使用QPainter的绘制线结束帽
  • joinStyle连接样式描述了如何绘制两条线之间的连接
  • 当更改画笔属性时,画家的比必须重置
void setPen(const QPen& pen)
void setPen(const QColor &color)
void setPen(Qt::PenStyle style)

线条样式

  • style使用Qt::PenStyle定义线条类型,默认是Qt::PenStyle::SolidLine。
  • QPen:
    在这里插入图片描述
    在这里插入图片描述
  • painter.setRenderHint(QPainter::RenderHint::Antialiasing); 去锯齿
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{

	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		penStyle();
	}
	void penStyle()
	{
		//开启画家,使用构造方式开起画家不需要结束,会自动结束
		QPainter painter(this);
		//设置渲染提示,Antialiasing(高质量渲染)反锯齿
		painter.setRenderHint(QPainter::RenderHint::Antialiasing);

		for (int i = 0; i < 6; i++)
		{
			painter.setPen(QPen(Qt::red, 5, Qt::PenStyle(i)));
			painter.drawLine(i * 50, 0, i * 50 + 100, 200);
		}
	}

private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

笔帽样式

  • 有四种笔帽样式,Qt文档中只给了三种示例
    在这里插入图片描述

    在这里插入图片描述

void capStyle()
	{
		QPainter painter(this);
		painter.setRenderHint(QPainter::RenderHint::Antialiasing);

		painter.setPen(QPen(QBrush(Qt::red), 5, Qt::PenStyle::DotLine, Qt::PenCapStyle::FlatCap));
		painter.drawLine(0, 0, 100, 200);

		painter.setPen(QPen(QBrush(Qt::red), 5, Qt::PenStyle::DotLine, Qt::PenCapStyle::MPenCapStyle));
		painter.drawLine(100, 0, 200, 200);

		painter.setPen(QPen(QBrush(Qt::red), 5, Qt::PenStyle::DotLine, Qt::PenCapStyle::RoundCap));
		painter.drawLine(200, 0, 300, 200);

		painter.setPen(QPen(QBrush(Qt::red), 5, Qt::PenStyle::DotLine, Qt::PenCapStyle::SquareCap));
		painter.drawLine(300, 0, 400, 200);
	}
  • 运行结果
    在这里插入图片描述

连接样式

  • 实际有五种连接样式
  • Qt文档中只给了四种
    在这里插入图片描述
    在这里插入图片描述
void joinStyle()
	{
		QPainter painter(this);
		painter.setRenderHint(QPainter::RenderHint::Antialiasing);

		int s[] = { Qt::MiterJoin,Qt::BevelJoin,Qt::RoundJoin,Qt::SvgMiterJoin,Qt::MPenJoinStyle };

		for (int i = 0; i < 5; i++)
		{

			painter.setPen(QPen(QBrush(Qt::red), 5, Qt::SolidLine, Qt::PenCapStyle::SquareCap, Qt::PenJoinStyle(s[i])));

			//设置三角形的三个点
			QPoint point[] = { {20 + i * 100,30},{50 + i * 100,60},{100 + i * 100,10} };
			painter.drawPolygon(point, 3);
		}
	}
  • 运行结果
    在这里插入图片描述

设置画刷与线性渐变

  • QBrush提供了画刷来对比图形进行填充,一个画刷使用它的颜色和风格来定义,Brush有样式(style)、颜色(color)、渐变(gradient)和纹理(texture)
    • style使用Qt::BrushStyle定义填充模式,默认笔刷样式是Qt::NoBrush
    • color定义填充图形颜色
    • gradient()定义当前样式为Qt::LinearGradientPattern, Qt::RadialGradientPattern或Qt::ConicalGradientPattern时使用的渐变填充。 当创建QBrush时,通过给QGradient作为构造函数参数来创建渐变笔刷。 Qt提供三个不同的梯度:QLinearGradient, QConicalGradient,和QRadialGradient所有继承QGradient。
      在这里插入图片描述
      在这里插入图片描述

画刷填充样式与颜色填充

#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{

	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		brushStyle();
		brushStylePuls();
	}
	void brushStyle()
	{
		//定义画家与画刷颜色
		QPainter painter(this);
		painter.setBrush(Qt::red);

		int w = 100;
		int h = 100;
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 5; j++)
			{
				painter.setBrush(Qt::BrushStyle(i * 5 + j));
				painter.drawRect(i * w, j * h, w, h);
			}
		}
	}
	void brushStylePuls()
	{ 
		//定义画家与画刷颜色
		QPainter painter(this);
		painter.setBrush(Qt::red);

		int w = 100;
		int h = 100;
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 5; j++)
			{
				//另一种带颜色的构造方式
				painter.setBrush(QBrush(Qt::GlobalColor::blue, Qt::BrushStyle(i * 5 + j)));
				painter.drawRect((i * w) + 350, j * h, w, h);
			}
		}
	}
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

使用纹理填充

#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{

	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		brushStylePulsMax();
	}
	void brushStylePulsMax()
	{ 
		//定义画家
		QPainter painter(this);
		//设置为无画笔
		painter.setPen(Qt::NoPen);

		painter.setBrush(QBrush(QPixmap(":/Resource/tubiao.ico")));

		int w = 150;
		int h = 150;
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 5; j++)
			{
				painter.drawRect(i * w, j * h, w, h);
			}
		}
	}
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

渐变填充

  • Qt目前支持三种类型的渐变填充:
  • 线性渐变(QLinearGradient) 在开始点和结束点之间插入颜色。
  • 径向渐变(QRadialGradient) 在围绕它的圆上的焦点和端点之间插入颜色。
  • 锥形渐变(QConicalGradient) 在中心点周围插值颜色。
  • 可以使用type()函数检索渐变的类型。 每一种类型都由QGradient的一个子类表示。
    在这里插入图片描述
  • QLinearGradient 显示从起点到终点的渐变。
线性渐变(QLinearGradient)

在这里插入图片描述

  • lgra.setSpread(QGradient::PadSpread);设置渐变填充区之外的颜色
    在这里插入图片描述
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{

	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		linearGradientPadSpread();
		linearGradientRepeatSpread();
		linearGradientReflectSpread();
	}
	void linearGradientPadSpread()
	{ 
		//定义线性渐变
		//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
		QLinearGradient lgra(0,0,100,100);

		//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
		lgra.setColorAt(0, Qt::red);
		lgra.setColorAt(0.48, Qt::blue);
		lgra.setColorAt(1, Qt::yellow);

		//开启画家
		QPainter painter(this);

		//设置填充渐变区域之外的区域
		lgra.setSpread(QGradient::PadSpread);

		//把渐变交给画刷
		painter.setBrush(lgra);

		//绘制矩形
		painter.drawRect(50, 50, 200, 200);
		//绘制圆形
		painter.drawEllipse(0, 0, 100, 100);

	}
	void linearGradientRepeatSpread()
	{
		//定义线性渐变
		//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
		QLinearGradient lgra(260, 0, 360, 100);

		//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
		lgra.setColorAt(0, Qt::red);
		lgra.setColorAt(0.48, Qt::blue);
		lgra.setColorAt(1, Qt::yellow);

		//开启画家
		QPainter painter(this);

		//设置填充渐变区域之外的区域
		lgra.setSpread(QGradient::RepeatSpread);
		
		//把渐变交给画刷
		painter.setBrush(lgra);

		//绘制矩形
		painter.drawRect(300, 50, 200, 200);
		//绘制圆形
		painter.drawEllipse(260, 0, 100, 100);

	}
	void linearGradientReflectSpread()
	{
		//定义线性渐变
		//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
		QLinearGradient lgra(510, 0, 610, 100);

		//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
		lgra.setColorAt(0, Qt::red);
		lgra.setColorAt(0.48, Qt::blue);
		lgra.setColorAt(1, Qt::yellow);

		//开启画家
		QPainter painter(this);

		//设置填充渐变区域之外的区域
		lgra.setSpread(QGradient::ReflectSpread);

		//把渐变交给画刷
		painter.setBrush(lgra);

		//绘制矩形
		painter.drawRect(550, 50, 200, 200);
		//绘制圆形
		painter.drawEllipse(510, 0, 100, 100);

	}
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述
  • 通过这种坐标设置填充就很麻烦,一旦绘图位置变了,就得更新填充,所以它的父类中有一个方法可以设置一下坐标模式
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 我们一般使用第二种模式、
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{

	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		linearGradientPadSpread();
		linearGradientRepeatSpread();
		linearGradientReflectSpread();
	}
	void linearGradientPadSpread()
	{ 
		//定义线性渐变
		//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
		QLinearGradient lgra(0,0,1,1);

		//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
		lgra.setColorAt(0, Qt::red);
		lgra.setColorAt(0.48, Qt::blue);
		lgra.setColorAt(1, Qt::yellow);

		//开启画家
		QPainter painter(this);

		//设置填充渐变区域之外的区域
		lgra.setSpread(QGradient::PadSpread);
		//设置梯度坐标模式
		lgra.setCoordinateMode(QGradient::CoordinateMode::ObjectMode);

		//把渐变交给画刷
		painter.setBrush(lgra);

		//绘制矩形
		painter.drawRect(50, 50, 200, 200);
		//绘制圆形
		painter.drawEllipse(0, 0, 100, 100);

	}
	void linearGradientRepeatSpread()
	{
		//定义线性渐变
		//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
		QLinearGradient lgra(0, 0, 1, 1);

		//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
		lgra.setColorAt(0, Qt::red);
		lgra.setColorAt(0.48, Qt::blue);
		lgra.setColorAt(1, Qt::yellow);

		//开启画家
		QPainter painter(this);

		//设置填充渐变区域之外的区域
		lgra.setSpread(QGradient::RepeatSpread);
		//设置梯度坐标模式
		lgra.setCoordinateMode(QGradient::CoordinateMode::ObjectMode);
		
		//把渐变交给画刷
		painter.setBrush(lgra);

		//绘制矩形
		painter.drawRect(300, 50, 200, 200);
		//绘制圆形
		painter.drawEllipse(260, 0, 100, 100);

	}
	void linearGradientReflectSpread()
	{
		//定义线性渐变
		//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
		QLinearGradient lgra(0, 0, 1, 1);

		//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
		lgra.setColorAt(0, Qt::red);
		lgra.setColorAt(0.48, Qt::blue);
		lgra.setColorAt(1, Qt::yellow);

		//开启画家
		QPainter painter(this);

		//设置填充渐变区域之外的区域
		lgra.setSpread(QGradient::ReflectSpread);
		//设置梯度坐标模式
		lgra.setCoordinateMode(QGradient::CoordinateMode::ObjectMode);
		//把渐变交给画刷
		painter.setBrush(lgra);

		//绘制矩形
		painter.drawRect(550, 50, 200, 200);
		//绘制圆形
		painter.drawEllipse(510, 0, 100, 100);

	}
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"

+运行结果
在这里插入图片描述

  • 因为使用了对象模式,即绘画的圆形和矩形都采用统一的渲染,默认渲染
径向渐变(QRadialGradient)
  • QRadialGradient 类以圆心为中心显示渐变。(cx, cy) 是中点,半径(radius)是以中点为圆心的圆的半径,(fx, fy) 是渐变的起点。
    在这里插入图片描述
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{

	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		radialGradientPadSpread();
	}
	void radialGradientPadSpread()
	{ 
		//指定以圆心和半径,以圆心为中心渐变
		QRadialGradient rgra(50, 50, 50);

		//也可以在构造对象后通过函数,设置开始点和结束点
		//rgra.setCenter(50, 50);
		//下面两个设置半径的功能一样 
		//rgra.setRadius(50);
		//rgra.setCenterRadius(50);


		//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
		rgra.setColorAt(0, Qt::red);
		rgra.setColorAt(0.48, Qt::blue);
		rgra.setColorAt(1, Qt::yellow);

		//开启画家
		QPainter painter(this);

		//设置填充渐变区域之外的区域
		rgra.setSpread(QGradient::ReflectSpread);
	

		//把渐变交给画刷
		painter.setBrush(rgra);

		//绘制矩形
		painter.drawRect(50, 50, 200, 200);
		//绘制圆形
		painter.drawEllipse(0, 0, 100, 100);

	}
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述
锥形渐变(QConicalGradient)
  • QConicalGradient圆锥渐变在一个中心点周围逆时针插入颜色, 在 (cx, cy) 坐标上以角度 (angle) 为中心显示渐变。
  • 角度必须在0到360度之间指定。
    在这里插入图片描述
void conicalGradient()
{
    //指定以圆心和角度进行渐变
    QConicalGradient cgra(50, 50, 0);
    //也可以在构造对象后通过函数,设置圆心和角度
    //cgra.setAngle(0);
    //cgra.setCenter(50, 50);
    
    //用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
    cgra.setColorAt(0, qRgb(82, 113, 196));
    cgra.setColorAt(0.48, qRgb(177, 159, 255));
    cgra.setColorAt(1, qRgb(236, 161, 254));

    QPainter painter(this);
    //把渐变色设置给画刷
    painter.setBrush(cgra);
    //绘制矩形,观察渐变区域之外的区域的填充
    painter.drawRect(50, 50, 250, 250);
    //绘制圆形(这里一般和开始指定的渐变坐标一样)
    painter.drawEllipse(0, 0, 100, 100);
}

坐标变换

  • QTransform 用于指定坐标系的 2D 转换 - 平移、缩放、扭曲(剪切)、旋转或投影坐标系。通常在渲染现图形时使用。
  • 可以使用setMatrix()、scale()、rotate()、translate()和shear()函数来构建QTransform对象。或者,也可以通过应用基本的矩阵操作来构建它。矩阵也可以在构造时定义,并且可以使用reset()函数将其重置为单位矩阵(默认值)。
  • QPainter具有平移、缩放、剪切和旋转坐标系统的功能,无需使用QTransform。
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{

	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
		QPainter painter(this);

		transform(&painter);
	}
	void transform(QPainter* painter)
	{
		painter->drawPixmap(0,0,QPixmap(":/Resource/tubiao.ico"));
	}
	
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

平移

  • translate(qreal dx, qreal dy):平移 - 对坐标系沿着 x 轴移动 dx、沿 y 轴移动 dy
void transform(QPainter* painter)
	{
		//平移
		painter->translate(50, 50);

		painter->drawPixmap(0,0,QPixmap(":/Resource/tubiao.ico"));
	}

缩放

  • scale(qreal sx, qreal sy):缩放 - 通过水平的 sx 和垂直的 sy 缩放坐标系
void transform(QPainter* painter)
	{
		//平移
		painter->translate(50, 50);
		//缩放
		painter->scale(0.5, 0.5);

		painter->drawPixmap(0,0,QPixmap(":/Resource/tubiao.ico"));

	}
  • 运行结果
    在这里插入图片描述

旋转

  • rotate(qreal angle, Qt::Axis axis = Qt::ZAxis):旋转 - 对指定的轴用给定的角度逆时针旋转坐标系统
    在这里插入图片描述
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QTimer>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{
		auto timer = new QTimer(this);
		//每60帧调用一次绘图
		timer->callOnTimeout([=]()
			{
				//更新绘图不能手动调用paintEvent
				//paintEvent(nullptr);
				//必须调用update函数更新绘图
				this->update();
			}
		);
		timer->start(1000 / 60);
	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
		QPainter painter(this);

		transform(&painter);
	}

	//旋转值
	qreal angle = 0;
	void transform(QPainter* painter)
	{
		//平移
		painter->translate(50, 50);
		//缩放
		painter->scale(0.5, 0.5);
		//旋转.默认是绕z轴转
		//painter->rotate(angle++);

		//绕x轴转
		QTransform tfm;
		//tfm.rotate(angle++, Qt::Axis::XAxis);
		//painter->setTransform(tfm);
 
		//绕y轴转
		//tfm.rotate(angle++, Qt::Axis::YAxis);
		//painter->setTransform(tfm);

		//绕z轴转
		tfm.rotate(angle++, Qt::Axis::ZAxis);
		painter->setTransform(tfm);

		painter->drawPixmap(0,0,QPixmap(":/Resource/tubiao.ico"));

	}
	
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QTimer>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{
		auto timer = new QTimer(this);
		//每60帧调用一次绘图
		timer->callOnTimeout([=]()
			{
				//更新绘图不能手动调用paintEvent
				//paintEvent(nullptr);
				//必须调用update函数更新绘图
				this->update();
			}
		);
		timer->start(1000 / 60);
	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
		QPainter painter(this);

		transform(&painter);
	}

	//旋转值
	qreal angle = 0;
	void transform(QPainter* painter)
	{

		QPixmap map(":/Resource/tubiao.ico");

		//The QTransform class specifies 2D transformations of a coordinate system
		QTransform tfm;

		//移动
		tfm.translate(width() / 2, height() / 2);

		//缩放
		tfm.scale(0.5, 0.5);

		//绕z轴转
		tfm.rotate(angle++, Qt::Axis::ZAxis);
		painter->setTransform(tfm);

		painter->drawPixmap(0 - map.width() / 2, 0 - map.height() / 2, map);

	}
	
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

错切

  • 图像错切变换也称为图像剪切、错位或错移变换。
  • shear(qreal sh, qreal sv):错切 - 通过水平的 sh 和垂直的 sv 扭曲坐标系,前面的参数实现横向变形,后面的参数实现纵向变形。当它们的值为 0 时,表示不扭曲。
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QTimer>
class Widget :public QWidget
{
public:
	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{
		auto timer = new QTimer(this);
		//每60帧调用一次绘图
		timer->callOnTimeout([=]()
			{
				//更新绘图不能手动调用paintEvent
				//paintEvent(nullptr);
				//必须调用update函数更新绘图
				this->update();
			}
		);
		timer->start(1000 / 60);
	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
		QPainter painter(this);

		transform(&painter);
	}

	//旋转值
	qreal angle = 0;
	void transform(QPainter* painter)
	{

		QPixmap map(":/Resource/tubiao.ico");

		//The QTransform class specifies 2D transformations of a coordinate system
		QTransform tfm;

		//移动
		tfm.translate(width() / 2, height() / 2);

		//缩放
		tfm.scale(0.5, 0.5);

		//错切
		tfm.shear(0.5, 0);

		//绕z轴转
		tfm.rotate(angle++, Qt::Axis::ZAxis);
		painter->setTransform(tfm);

		painter->drawPixmap(0 - map.width() / 2, 0 - map.height() / 2, map);

	}
	
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

QPixmap、QImage、QBitmap、QPicture

  • Qt提供四种处理图像数据的类:QImage、QPixmap、QBitmap、QPicture
  • QImage是为I/O和直接像素访问和操作而设计和优化的,而QPixmap是为在屏幕上显示图像而设计和优化的。 QBitmap只是一个继承了QPixmap的方便类,确保深度为1。 如果QPixmap对象是位图,则isQBitmap()函数返回true,否则返回false。 最后,QPicture类是一个记录和回放QPainter命令的绘图设备。

QPixmap

void pixmap(QPainter* painter)
	{
		//构造一个图像对象
		QPixmap pix(":/Resource/tubiao.ico");
		
		//绘画这个图像到0,0坐标
		//painter->drawPixmap(0, 0, pix);
		painter->drawPixmap(QRect(0, 0, 50, 50), pix);
		//剪切图像
		painter->drawPixmap(0, 50, pix, 0, 0, 200, 200);
		painter->drawPixmap(QRect(0, 250, 100, 100), pix, QRect(100, 100, 200, 200));
	}
  • 运行结果
    在这里插入图片描述

QImage

  • QGradient:里面会有很多预设颜色
    在这里插入图片描述
  • 一般构造QImage的时候,QImage::Format格式,这个比较常用
    在这里插入图片描述
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QTimer>
class Widget :public QWidget
{
public:
	//声明QImage对象
	QImage m_image;

	Widget(QWidget* parent = nullptr) :QWidget(parent)
		,m_image(200,200,QImage::Format::Format_RGBA8888)
	{
		//在QImage上绘图
		{
			
			QPainter painter(&m_image);
			//在这个矩形上绘制,渐变模式为WinterNeva
			painter.fillRect(m_image.rect(),QGradient::WinterNeva);
		}
	
	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
		QPainter painter(this);
		image(&painter);
	}
	void image(QPainter* painter)
	{
		painter->drawImage(0, 0, m_image);
	}
	
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

QBitmap

#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QTimer>
class Widget :public QWidget
{
public:

	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{
		
	
	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
		QPainter painter(this);
		bitmap(&painter);
	}

	void bitmap(QPainter* painter)
	{
		QPixmap pix(":/Resource/tubiao.ico");
		painter->drawPixmap(0, 0, QBitmap::fromPixmap(pix));
	}
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

QPicture

#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QPicture>
class Widget :public QWidget
{
public:

	Widget(QWidget* parent = nullptr) :QWidget(parent)
	{
		
	
	}
protected:
	//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
	void paintEvent(QPaintEvent* ev) override
	{
		//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
		QPainter painter(this);
		picture(&painter);
	}

	void picture(QPainter* painter)
	{
		QPicture pic;
		{
			//先让pt与pic取消关联后,才能保存,用块语句包裹即可
			QPainter pt(&pic);
			pt.drawLine(0, 0, width(), height());
			pt.fillRect(100, 200, 150, 35, QGradient::Preset::SkyGlider);
		}
		
		//保存到本地,这个里面保存的是指令只有qt看得懂
		pic.save("text.pic");

		//显示图像
		QPicture picc;
		picc.load("text.pic");
		painter->drawPicture(0, 0, picc);
		//picc.play(painter);
	}
private:
};

int main(int argc, char* argv[])
{
	QApplication a(argc, argv);

	Widget w;
	w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
	w.show();
	
	return a.exec();
}
#include "main.moc"
  • 运行结果,本地的out目录里面会有一个text.pic文件
    在这里插入图片描述
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1101500.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

低学历可以学python吗?

低学历可以学python吗&#xff1f; 看不到前途&#xff0c;是不是自己对以后工作就业的事情感到比较迷茫呢&#xff1f; 是不知道企业要求哪些知识&#xff0c;想要的是什么样能力的人&#xff1f; 最近很多小伙伴找我&#xff0c;说想要一些c语言资料&#xff0c;然后我根据…

Windows 钉钉多开 dingtalkRC版

亲测可用 下载链接&#xff1a; https://dtapp-pub.dingtalk.com/dingtalk-desktop/win_installer/RC/DingTalk_v6.5.20-RC.7229101.exe

基于SpringBoot的医疗预约服务管理系统

基于SpringBootVue的医疗预约服务管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 登陆界面 管理员界面 医生界面 会员界面 摘要 基于SpringBoot的…

计算机网络 | 应用层

计算机网络 | 应用层 计算机网络 | 应用层应用层概述网络应用模型客户/服务器模型&#xff08;Client/Server&#xff0c;C/S&#xff09;P2P模型&#xff08;Peer-to-Peer&#xff09; 域名系统&#xff08;DNS&#xff09; 参考视频&#xff1a;王道计算机考研 计算机网络 参…

【Interview】拟牛顿求一个数的平方根

如何求一个数的平方根&#xff1f; - 一点点算法的文章 - 知乎 牛顿迭代法的思路是通过切线方程与x轴的 交点&#xff0c;逐渐迭代收敛到一个数的平方根。 我们要求m的平方根&#xff0c;构造函数 用图1进行简单说明&#xff1a; 初始化选A点&#xff0c;求切线&#xff0c;…

Windows11家庭版没有本地组策略编辑器解决

1. 新建一个文本文件将下面代码粘到里面&#xff0c;保存后修改后缀为.cmd或者.bat echo off pushd "%~dp0"dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~3*.mum >List.txt dir /b C:\Windows\servicing\Packa…

开路、断路和短路区别

文章目录 开路和断路击穿电源短路、用电器短路、对地短路和对电源短路 开路和断路 开路和断路是电路中两种用于描述电流流动情况的状态。 两者易混淆&#xff0c;常被混淆使用&#xff0c;但是它们还是有所不同。 开路表示电路中存在一个断链&#xff0c;电流无法从一个点流到…

【MultiOTP】在Linux上使用MultiOTP进行SSH登录

在前面的文章中【FreeRADIUS】使用FreeRADIUS进行SSH身份验证已经了解过如何通过Radius去来实现SSH和SUDO的登录&#xff0c;在接下来的文章中只是将密码从【LDAP PASSWORD Googlt OTP】改成了【MultiOTP】生成的passcode&#xff0c;不在需要密码&#xff0c;只需要OTP去登录…

NISP和CISP有什么区别,哪个证更好?

近些年来年关于信息安全的话题屡次登上搜索热榜&#xff0c;无论是个人还是企业或者是各种机构组织&#xff0c;对信息安全这一块的需求越来越大&#xff0c;从事这个行业的人群数量剧增。而随着毕业季的到来&#xff0c;最近有很多学生和相关的从业人员&#xff0c;想要了解关…

视觉slam论文、代码汇总

文章目录 2021GVINS: Tightly Coupled GNSS-Visual-Inertial Fusion for Smooth and Consistent State Estimation 2022IC-GVINS: A Robust, Real-Time, INS-Centric GNSS-Visual-Inertial Navigation System 2023LE-VINS: A Robust Solid-State-LiDAR-Enhanced Visual-Inertia…

leetcode:507. 完美数(python3解法)

难度&#xff1a;简单 对于一个 正整数&#xff0c;如果它和除了它自身以外的所有 正因子 之和相等&#xff0c;我们称它为 「完美数」。 给定一个 整数 n&#xff0c; 如果是完美数&#xff0c;返回 true&#xff1b;否则返回 false。 示例 1&#xff1a; 输入&#xff1a;num…

win11取消文件夹分组

问题描述 最近不知道把哪里碰了&#xff0c;win10文件夹显示的文件都是按照日期分组了&#xff0c;很讨厌。如下图所示 修改方法 1、文件夹空白处-右击 2、分组依据(P)-选择(无)(N) 下面是操作好之后的效果图 结束 -----华丽的分割线&#xff0c;以下是凑字数&#xff0c;大家不…

使用BurpSuite抓取HTTPS接口

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 原因设置方式 原因 BurpSuite之所以不能抓取https数据包&#xff0c;是因为BurpSuite作为中间人代理&#xff0c;我们和https网站之间的数据通信都是由BurpSuite来…

pgbackrest归档目录满,清理后写入仍报错,分析及处理

一、 背景 pgbackrest配置的归档目录/backup被写满 归档报错 No space left on device&#xff0c;wal日志堆积 解决方法直接查看第三部分 二、 问题分析及处理 1. 目录清理 首先想到的就是清理/backup目录&#xff0c;清理后剩余6T空间 但发现pgbackrest归档依旧在报错 No …

命令行配置文件

在说具体的配置方式之前&#xff0c;我们需要首先梳理清除几个概念。这有助于我们明白自己在做什么&#xff0c;以及如何把经验平移到其他方面。 和命令行相关的有几个概念&#xff1a;terminal&#xff08;终端&#xff09;、shell&#xff08;解释器&#xff09;&#xff1b…

云安全—分布式基础

0x00 前言 云必然是依赖于分布式技术来进行实现的&#xff0c;所以有必要学习和来了解分布式相关的内容 0x01 分布式计算 1.基本概述 分布式计算的定义&#xff1a;通过网络互联的计算机都具有一定的计算能力&#xff0c;他们之间互相传递数据&#xff0c;实现信息共享&…

android aidl Can‘t resolve Salary问题

** 解决方法 ** 在数据aidl中写上包名&#xff0c;并且保证他的实体类也应当在与数据aidl文件相同的java类的包下 如果实例类放在aidl文件中会报一些稀奇古怪的错误&#xff0c;可以生成.java文件但是里面的实体类是不能识别的

6个方面揭秘,PMP究竟值不值得考?

首先先肯定一下&#xff0c;pmp是值得考的&#xff0c;考了能受益的大概分了以下几类&#xff1a; 1、项目管理人士&#xff1a;部门主管、项目主管、项目经理、项目助理、项目团队成员、技术人员、技术转管理、技术主管、项目管理者&#xff1b; 2、想从事项目管理职业的人士…

跨境商城源码部署(多商户入驻,一键铺货,快速部署)

现如今&#xff0c;互联网的快速发展为商业带来了前所未有的机遇&#xff0c;跨境电商作为其中的热门领域&#xff0c;吸引了众多企业和创业者的关注。而通过部署跨境商城源码&#xff0c;您将获得多商户入驻、一键铺货等功能&#xff0c;轻松拥有一家生意蓬勃发展的跨境商城。…

21.Hadoop在Windows环境下的下载安装配置超详细版

Hadoop在Windows环境下的下载安装配置超详细版 本文章所需下载安装软件&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1jIQyy0VHuPvQZ8-n_Zq0pg?pwd1017 hadoop的Windows化安装步骤是非常麻烦的&#xff0c;如果有一步出错将导致得充头从来。 环境配置 前置依赖1&…