Qt5绘制方法——QPointer常用方法

以下学习可能要花费一个小时左右。如果遇到疑问在评论区留言,我会看到的!加油!

  • 首先创建一个不带ui,且类名修改为 MainWidget(自定),基类为QWidget的项目。
  • mainwidget.h中重写QWidget::paintEvent(QPaintEvent *event)函数
    void paintEvent(QPaintEvent *event) override; 
  • 在maiwidget.cpp中写源码
void MainWidget::paintEvent(QPaintEvent *event)
{
    /**
    为所欲为绘制
    */
}

看到这里肯定有很多小伙伴在疑虑,
为什么要不带ui?
为什么要用QWidget而不用默认的QMainWindow?
为什么要重写paintEvent,不能在构造函数直接用吗?

1、不带ui是我的习惯,在构造函数里设置一些简单的窗口及自定义控件方便。

2、我们重写的paintEvent函数,是在QWidget中的;而QMainWindow也是继承自QWidget,其本身没有该函数,所以我们不用QMainWindow。

3、这个问题我们需要了解QPainter的机制,请往下看。

绘制系统主要依赖于三个类:QPainter、QPainterEngine、QPainterDevice。QPainter可以理解为画笔,我们主要也是用这个类的函数接口。QPainterDevice就是绘画设备,就是我们所见的屏幕。QPainterEngine则是连接画笔和屏幕的引擎,将QPainter翻译到屏幕上;一般我们用不到这个类,因为我们在使用QPainter时,它会由QPainter自动调用。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

一、前期准备

一些可能用到的函数

    setPalette(QPalette(Qt::white)); 	//设置界面背景颜色,白色,自定
   	setAutoFillBackground(true);		//设置自动填充背景色

二、QPainter的绘制接口

1、绘制点

函数原型:

inline void QPainter::drawPoint(const QPointF &p)
{
    drawPoints(&p, 1);
}

inline void QPainter::drawPoint(int x, int y)
{
    QPoint p(x, y);
    drawPoints(&p, 1);
}

inline void QPainter::drawPoint(const QPoint &p)
{
    drawPoints(&p, 1);
}

就是一个点坐标,不做解释

    QPainter paint(this);
	paint.drawPoint(100,100);

如图,,这个点很小,在运行中默认只有一个像素大小。

2、绘制直线

函数原型:

inline void QPainter::drawLine(const QLineF &l)
{
    drawLines(&l, 1);
}

inline void QPainter::drawLine(const QLine &line)
{
    drawLines(&line, 1);
}

inline void QPainter::drawLine(int x1, int y1, int x2, int y2)
{
    QLine l(x1, y1, x2, y2);
    drawLines(&l, 1);
}

inline void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
{
    QLine l(p1, p2);
    drawLines(&l, 1);
}

inline void QPainter::drawLine(const QPointF &p1, const QPointF &p2)
{
    drawLine(QLineF(p1, p2));
}

可见,直线原理就是告诉接口两个点坐标,再将两个点相连。

如图,语句

    QPainter paint(this);
	paint.drawLine(50,50,250,250);

画出的图

3、绘制矩形

函数原型:

inline void QPainter::drawRect(const QRectF &rect)
{
    drawRects(&rect, 1);
}

inline void QPainter::drawRect(int x, int y, int w, int h)
{
    QRect r(x, y, w, h);
    drawRects(&r, 1);
}

inline void QPainter::drawRect(const QRect &r)
{
    drawRects(&r, 1);
}

可见,矩形的画法是线申明一个点坐标作为左上落脚点,再定义其长度和高度

如图,使用函数

    QPainter paint(this);
	paint.drawRect(50,50,200,200);

4、绘制圆角矩阵

原型:

    void drawRoundRect(const QRectF &r, int xround = 25, int yround = 25);
    QT_DEPRECATED_X("Use drawRoundedRect(..., Qt::RelativeSize) instead")
    void drawRoundRect(int x, int y, int w, int h, int = 25, int = 25);
    QT_DEPRECATED_X("Use drawRoundedRect(..., Qt::RelativeSize) instead")
    void drawRoundRect(const QRect &r, int xround = 25, int yround = 25);

可见,坐标,长,高和矩形是一样的,只是后面多了两个参数,第一个参数是x轴上圆润长度,第二个参数是y轴上圆润长度。

如图,为了看的清楚,添加一个矩形,

    paint.drawRoundRect(50,50,200,150,50,10);
    paint.drawRect(50,50,200,150);

5、绘制椭圆

函数原型:

inline void QPainter::drawEllipse(int x, int y, int w, int h)
{
    drawEllipse(QRect(x, y, w, h));
}

inline void QPainter::drawEllipse(const QPointF &center, qreal rx, qreal ry)
{
    drawEllipse(QRectF(center.x() - rx, center.y() - ry, 2 * rx, 2 * ry));
}

inline void QPainter::drawEllipse(const QPoint &center, int rx, int ry)
{
    drawEllipse(QRect(center.x() - rx, center.y() - ry, 2 * rx, 2 * ry));
}

可见,绘制椭圆也是固定一个点,再申明长和宽

如图,使用函数paint.drawEllipse(100,100,200,100);

如果不理解是如何形成的,那么我们添加一个矩形来看看,矩形的还不了解就返回上一层看看。

    paint.drawRect(100,100,200,100);
    paint.drawEllipse(100,100,200,100);

6、绘制圆弧

原型:

inline void QPainter::drawArc(const QRect &r, int a, int alen)
{
    drawArc(QRectF(r), a, alen);
}

inline void QPainter::drawArc(int x, int y, int w, int h, int a, int alen)
{
    drawArc(QRectF(x, y, w, h), a, alen);
}

可见,圆弧是先确定一个矩形,再根据两个角度来确定。这两个角度一个是开始角度,一个是绘制角度。
开始角度是说从一个固定角度开始。
绘制角度是说从固定角度开始,你要绘制多少度的弧。

有两点要说的是,角度是被划分成16部分的,所以输入角度时要✖️16;0角度是沿x轴方向的,度数沿逆时针增长。具体见代码:

	paint.drawArc(10,10,200,200,0*16,90*16);		//0度开始,弧长90度
	paint.drawArc(10,10,200,200,30*16,150*16);		//30度开始,弧长150度

7、绘制扇形

原理和画弧一样,不解释

代码:paint.drawPie(10,10,200,200,30*16,150*16);

8、绘制多边形

原型:

	void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule = Qt::OddEvenFill);
    inline void drawPolygon(const QPolygonF &polygon, Qt::FillRule fillRule = Qt::OddEvenFill);
    void drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule = Qt::OddEvenFill);
    inline void drawPolygon(const QPolygon &polygon, Qt::FillRule fillRule = Qt::OddEvenFill);

可见,绘制多边形就是将点坐标作为数组形式,把首地址传给绘制接口,再申明点的个数,最后将两点之间用线段连接。

比如画一个三角形,设定三个点坐标为(100,100)、(100,400)、(500,400),这就是一个直角三角形。再将点和个数传给drawPolygon()函数接口。

    QPoint point[3] = {QPoint(100,100), QPoint(100,400), QPoint(500,400)};
    paint.drawPolygon(point,3);

如图:

9、绘制文本

原型:

    void drawText(const QPointF &p, const QString &s);
    inline void drawText(const QPoint &p, const QString &s);
    inline void drawText(int x, int y, const QString &s);

    void drawText(const QPointF &p, const QString &str, int tf, int justificationPadding);

    void drawText(const QRectF &r, int flags, const QString &text, QRectF *br = nullptr);
    void drawText(const QRect &r, int flags, const QString &text, QRect *br = nullptr);
    inline void drawText(int x, int y, int w, int h, int flags, const QString &text, QRect *br = nullptr);

    void drawText(const QRectF &r, const QString &text, const QTextOption &o = QTextOption());

可见,可以用点、矩形来确定文本位置。有一点要说的是,既然是文本,那么肯定可以使用QFont控制字体的大小、模式等,最后再绘制前paint.setFont(font);完成。

演示代码如下,为了直观,添加了矩形:

    QFont font;
    font.setPointSize(50);
    font.setFamily("Microsoft YaHei");
    font.setItalic(true);
    paint.setFont(font);
    QRect rect(100,100,200,100);
    paint.drawRect(rect);
    paint.drawText(rect,"Hello");

如图:

10、绘制图片

原型,有点多,只罗列了常用的几个:

inline void QPainter::drawPixmap(const QPoint &p, const QPixmap &pm)
{
    drawPixmap(QPointF(p), pm);
}

inline void QPainter::drawPixmap(const QRect &r, const QPixmap &pm)
{
    drawPixmap(QRectF(r), pm, QRectF());
}

inline void QPainter::drawPixmap(int x, int y, const QPixmap &pm)
{
    drawPixmap(QPointF(x, y), pm);
}

inline void QPainter::drawPixmap(int x, int y, int w, int h, const QPixmap &pm)
{
    drawPixmap(QRectF(x, y, w, h), pm, QRectF());
}

可见,图片绘制也是由点、矩形来确定位置的,最后加上图片的路径即可(用QPixmap)。

代码如下,加入矩形:

    paint.drawRect(10,10,380,280);
    paint.drawPixmap(10,10,380,280,QPixmap("/Users/yucheng/allpic/back.jpeg"));

如图:

11、二进制绘制图片

用法和QPixmap相同,将类变为QBitmap即可。具体看代码:

    QPainter paint(this);
    QPixmap pix("/Users/yucheng/allpic/qq.png");
    QBitmap bit("/Users/yucheng/allpic/qq.png");
    paint.drawPixmap(10,10,pix);
    paint.drawPixmap(110,10,bit);

三、画笔与画刷

1、简介

首先要知道,画笔类QPen常用来画线,画刷类QBrush常用来填充图形内部。

2、画笔

画笔用来画图形,众所周知,笔有很多种,包括影响线条的粗细、颜色,以及个人影响的线条的款式,如实线、虚线、点线。当然,线条粗了以后,始末端的样式也是不同的,包括平整、圆形

接下来一个个看!

(1)、线条粗细、颜色

QPainter可以使用QPen来定义笔,QPen中使用.setWidth(int)来设置笔的粗细,使用.setBush(Qt::black);来设置笔的颜色。

.setWidth(int)后的参数是像素大小,最小为1,即使输入0,也是画出一像素大小。

.setBush(Qt::black);后颜色是Qt自带的颜色输入Qt::后会显示各类接口,选择想要的颜色即可。

代码,为了颜色及款式对比鲜明,往后我都将背景填充为白色

    QPainter paint(this);
    QPen pen;
    pen.setWidth(10);
    pen.setBrush(Qt::blue);
    paint.setPen(pen);
    paint.drawLine(50,100,50,200);
    paint.drawRect(100,100,200,100);

效果:

(2)、线条款式

线条默认都是直线的,当然也有其他了。如图:

默认情况是直线,使用pen.setStyle(Qt::SolidLine);切换喜欢的样式。

(3)、线条末端样式和线条连接方式

线条末端一般分为三种情形:

默认是第一种情况,见上图(1),使用pen.setCapStyle(Qt::SquareCap);切换模式。

线条接连也分为三种方式:

默认是第一种方式,见上图(1),使用pen.setJoinStyle(Qt::BevelJoin);切换形式。

(4)、前三种结合举例

代码:

void MainWidget::paintEvent(QPaintEvent *event)
{
    QPainter paint(this);
    QPen pen;
    pen.setWidth(10);
    pen.setBrush(Qt::blue);

    pen.setStyle(Qt::DashDotLine);		//设置线条为破折号+远点形式(2)
    pen.setCapStyle(Qt::RoundCap);		//设置笔帽末端为圆形(1)
    pen.setJoinStyle(Qt::RoundJoin);	//设置线条连接方式为圆形(3)

    paint.setPen(pen);
    paint.drawLine(50,100,50,200);
    paint.drawRect(100,100,200,100);
}

内部也可以写成

    QPainter paint(this);
    QPen pen(Qt::blue,10,Qt::DashDotLine,Qt::RoundCap,Qt::RoundJoin);
    paint.setPen(pen);
    paint.drawLine(50,100,50,200);
    paint.drawRect(100,100,200,100);

图形如下:

与(1)中图形对比

3、画刷

画刷用来给图形内部填色,包括样式、颜色、渐变、纹理

(1)、画刷颜色

QPainter使用QBrush来定义画刷,使用.setBrush(QBrush)设置。

代码:

	QPainter paint(this);
    QPen pen;
    pen.setWidth(3);
    pen.setBrush(Qt::blue);
    
    paint.setPen(pen);					//设置画笔
    paint.setBrush(Qt::red);			//设置画刷为红色
    paint.drawRect(100,100,200,100);

显示:

(2)、画刷纹理

画刷纹理主要有:图片来源 只展示部分,剩余的在下面介绍。

在使用时,我们需要定义一个QBrush类成员来存放纹理及其颜色。.setStyle(Qt::NoBrush)来设置纹理.setColor(Qt::Red)设置纹理颜色

代码:

    QPainter paint(this);
    QPen pen;
    pen.setWidth(3);
    pen.setBrush(Qt::blue);

    QBrush brush;
    brush.setStyle(Qt::Dense1Pattern);
    brush.setColor(Qt::red);
    
    paint.setPen(pen);
    paint.setBrush(brush);
    paint.drawRect(100,100,200,100);

效果:

(3)、纹理渐变

渐变纹理只有在使用下面三种纹理才能使用:

Qt::LinearGradientPatternQt::RadialGradientPatternQt::ConicalGradientPattern

如图:

并且,每种纹理都要定义初始化纹理类。

纹理类型纹理定义-类定义方法参数解释
Qt::LinearGradientPatternQLinearGradientQLinearGradient(const QPointF &start, const QPointF &finalStop)起始点、终点
Qt::RadialGradientPatternQRadialGradientQRadialGradient(const QPointF &center, qreal radius, const QPointF &focalPoint)中心点坐标、半径、焦点坐标
Qt::ConicalGradientPatternQConicalGradientQConicalGradient(const QPointF &center, qreal startAngle)中点坐标、渐变角度

如代码,使用第二个举例:

    QPainter paint(this);
    QPen pen;
    pen.setWidth(3);
    pen.setBrush(Qt::blue);

    QRadialGradient gradient(200,150,50);		//中点坐标、半径、焦点可不写,自定
    gradient.setColorAt(0,Qt::red);
    gradient.setColorAt(1,Qt::green);
    QBrush brush(gradient);

    paint.setPen(pen);
    paint.setBrush(brush);
    paint.drawRect(100,100,200,100);

效果:

(4)、自定图形渐变

没什么好说的,直接上代码:

    QPainter paint(this);
    QPen pen;
    pen.setWidth(3);
    pen.setBrush(Qt::blue);

    QBrush brush;
    brush.setStyle(Qt::TexturePattern);     //当你不写这句话时,没有关系,因为在下一句执行时会自动设置style
    brush.setTexture(QPixmap("/Users/yucheng/allpic/qq.png"));

    paint.setPen(pen);
    paint.setBrush(brush);
    paint.drawRect(100,100,200,100);

效果:

四、最后

1、简洁代码

在进行简单操作时,总是定义一个新的成员总是很麻烦,比如说自定义纹理,用了将近10行的代码,那么在熟练之后可以用类的构造函数来简化方法。将自定义纹理代码简化如下:

    QPainter paint(this);
    paint.setPen(QPen(Qt::blue,3));
    paint.setBrush(QBrush(QPixmap("/Users/yucheng/allpic/qq.png")));
    paint.drawRect(100,100,200,100);

2、反走样

反走样在图形学中就是锯齿,玩游戏的朋友都知道开了抗锯齿的画面都会舒服很多。对比下面两个图形,尤其是上下部分。

仔细发现,左边的圆部分地方会有明显的锯齿,但是右边的就没有,那是因为我们在绘制右边的图形时,添加了反走样。

代码:

    QPainter paint(this);
    paint.setPen(QPen(Qt::black,50));
    paint.drawEllipse(50,50,500,500);
    paint.setRenderHint(QPainter::Antialiasing,true);		//反走样
    paint.drawEllipse(600,50,500,500);

3、颜色取样方式

不管在设定画笔颜色或者画刷颜色时候,我们都用的是Qt自带的颜色。当然还可以使用QColor类中的颜色。
了解QColor的用法参考博客:QColor用法

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值