除了绘制图形之外,还可使用QPainter::darwText()函数来绘制文字,也可使用QPainter::setFont()设置文字所使用的字体,使用QPainter::fontInfo()函数能够获取字体的信息,它返回QFontInfo类对象。在绘制文字时会默认使用抗锯齿。php
下面仍然在上一节的程序中进行代码演示,更改paintEvent()的内容以下:linux
void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); painter.drawText(100, 100, "qter.org-yafeilinux"); }
这样就在(100, 100)的位置绘制了一个字符串。效果以下图所示。c++
咱们先到QPainter的帮助文档页面,而后查看drawText()函数的重载形式,找到:api
QPainter::drawText ( const QRectF & rectangle, int flags, const QString & text, QRectF * boundingRect = 0 )
下面来看一个例子。为了更明显地看到文字在指定矩形中的位置,咱们绘制出这个矩形。将paintEvent()函数更改以下:函数
void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); //设置一个矩形 QRectF rect(50, 50, 300, 200); //为了更直观地看到字体的位置,咱们绘制出这个矩形 painter.drawRect(rect); painter.setPen(QColor(Qt::red)); //这里先让字体水平居中 painter.drawText(rect, Qt::AlignHCenter, "yafeilinux"); }
如今运行程序,效果以下图所示。字体
可用的对齐方式以下图所示。优化
为了绘制漂亮的文字,可使用QFont类来设置文字字体。你们也能够先在帮助文档中查看该类的介绍。下面将最经常使用的一些设置进行演示。ui
将paintEvent()函数更改以下:this
void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); //设置一个矩形 QRectF rect(50, 50, 300, 200); //为了更直观地看到字体的位置,咱们绘制出这个矩形 painter.drawRect(rect); painter.setPen(QColor(Qt::red)); //这里先让字体水平居中 painter.drawText(rect, Qt::AlignHCenter, "yafeilinux"); //使用字体 QFont font("宋体", 15, QFont::Bold, true); //设置下划线 font.setUnderline(true); //设置上划线 font.setOverline(true); //设置字母大小写 font.setCapitalization(QFont::SmallCaps); //设置字符间的间距 font.setLetterSpacing(QFont::AbsoluteSpacing, 10); //使用字体 painter.setFont(font); painter.setPen(Qt::blue); painter.drawText(120, 80, tr("yafeilinux")); painter.translate(50, 50); painter.rotate(90); painter.drawText(0, 0, tr("helloqt")); }
这里建立了QFont字体对象,使用的构造函数为QFont::QFont ( const QString & family,int pointSize = -1, int weight = -1, bool italic = false ),第一个参数设置字体的family属性,这里使用的字体族为宋体,可使用QFontDatabase类来获取所支持的全部字体;第二个参数是点大小,默认大小为12;第三个参数为weight属性,这里使用了粗体;最后一个属性设置是否使用斜体。而后咱们又使用了其余几个函数来设置字体的格式,最后调用setFont()函数来使用该字体,并使用drawText()函数的另外一种重载形式在点(120, 80)绘制了文字。后面又将坐标系统平移并旋转,而后再次绘制了文字。运行程序,效果以下图所示。spa
若是要绘制一个复杂的图形,那么可使用QPainterPath类,而后使用QPainter::drawPath()来进行绘制。QPainterPath类为绘制操做提供了一个容器,能够用来建立图形而且重复使用。一个绘图路径就是由多个矩形、椭圆、线条或者曲线等组成的对象,一个路径能够是封闭的,例如矩形和椭圆;也能够是非封闭的,例如线条和曲线。
下面看一个例子:添加一个椭圆和一根线在图形路径里。依然在前面的项目中进行讲解。更改paintEvent()函数以下:
void Widget::paintEvent(QPaintEvent *) { //添加一个椭圆和一根线在图形路径里 QPainterPath path; path.addEllipse(100, 100, 50, 50); //添加一个圆心为(100,100),横纵半径都为50的椭圆 path.lineTo(200, 200); //添加一根从当前位置到(200,200)的线 QPainter painter(this); painter.setPen(Qt::blue); painter.setBrush(Qt::red); painter.drawPath(path); }
当建立一个QPainterPath对象后,可使用lineTo()、arcTo()、cubicTo()和quadTo()等函数将直线或者曲线添加到路径中。运行程序,效果以下图所示。
若是只是简单的将几个图形拼接在一块儿,其实彻底没有必要用路径,之因此要引入路径,就是由于它的一个很是有用的功能:复制图形路径。更改paintEvent()函数以下:
void Widget::paintEvent(QPaintEvent *) { //添加一个椭圆和一根线在路径里 QPainterPath path; path.addEllipse(100, 100, 50, 50); //添加一个圆心为(100,100),横纵半径都为50的椭圆 path.lineTo(200, 200); //添加一根从当前位置到(200,200)的线 QPainter painter(this); painter.setPen(Qt::blue); painter.setBrush(Qt::red); painter.drawPath(path); //复制图形路径 QPainterPath path2; path2.addPath(path); path2.translate(100,0); painter.drawPath(path2); }
如今运行程序,效果以下图所示。
能够看到,对于已经绘制好的路径,能够很是简单地进行重复绘制。
咱们先来看一个例子,将paintEvent()函数更改以下:
void Widget::paintEvent(QPaintEvent *) { QPainterPath path; path.lineTo(100, 100); path.lineTo(200, 100); QPainter painter(this); painter.drawPath(path); }
程序运行效果以下图所示。
能够看到,建立路径后,默认是从(0, 0)点开始绘制的,当绘制完第一条直线后当前位置是(100, 100)点,从这里开始绘制第二条直线。绘制完第二条直线后,当前位置是(200, 100)。
咱们也能够使用moveTo()函数来改变当前点的位置。例如将paintEvent()函数更改以下:
void Widget::paintEvent(QPaintEvent *) { QPainterPath path; path.addRect(50, 50, 40, 40); //移动到(100, 100)点 path.moveTo(100, 100); path.lineTo(200, 200); QPainter painter(this); painter.drawPath(path); }
这样当绘制完矩形之后,就会移动到(100, 100)点进行后面的绘制。程序运行效果以下图所示
Qt提供了四个类来处理图像数据:QImage、QPixmap、QBitmap和QPicture,它们都是经常使用的绘图设备。其中QImage主要用来进行I/O处理,它对I/O处理操做进行了优化,并且能够用来直接访问和操做像素;QPixmap主要用来在屏幕上显示图像,它对在屏幕上显示图像进行了优化;QBitmap是QPixmap的子类,用来处理颜色深度为1的图像,即只能显示黑白两种颜色;QPicture用来记录并重演QPainter命令。这一节咱们只讲解QPixmap。
(1)此次咱们从新建立一个Qt Widgets应用,项目名称为mypixmap,在类信息页面,将基类选择为QDialog,类名使用默认的Dialog便可。
(2)而后在源码目录中复制一张图片,好比这里是一张logo.png图片,以下图所示。
(3)在dialog.h文件中添加剧绘事件处理函数的声明:
protected: void paintEvent(QPaintEvent *);
(4)到dialog.cpp文件中先添加头文件包含#include <QPainter>,而后添加函数的定义:
void Widget::paintEvent(QPaintEvent *) { QPainter painter(this); QPixmap pix; pix.load("../mypixmap/logo.png"); painter.drawPixmap(0, 0, 80, 100, pix); }
这里使用了相对路径,由于Qt Creator默认是使用影子构建,即编译生成的文件在build-mypixmap-Desktop_Qt_5_8_0_MinGW_32bit-Debug这样的目录里面,而这个目录就是当前目录,因此源码目录就是其上级目录了。你们能够根据本身的实际状况来更改路径,也可使用绝对路径,不过最好使用资源文件来存放图片。drawPixmap()函数在给定的矩形中来绘制图片,这里矩形的左上角顶点为(0, 0)点,宽80,高100,若是宽高跟图片的大小比例不一样,默认会拉伸图片。运行效果以下图所示。
QPainter类中的translate()函数实现坐标原点的改变,改变原点后,此点将会成为新的原点(0,0)。下面来看一个例子。在paintEvent()函数中继续添加以下代码:
//将(100,100)设为坐标原点 painter.translate(100, 100); painter.drawPixmap(0, 0, 80, 100, pix);
这里将(100,100)设置为了新的坐标原点,因此下面在(0,0)点贴图,就至关于在之前的(100,100)点贴图。运行程序,效果以下图所示。
咱们可使用QPixmap类中的scaled()函数来实现图片的放大和缩小。在paintEvent()函数中继续添加以下代码:
//得到之前图片的宽和高 qreal width = pix.width(); qreal height = pix.height(); //将图片的宽和高都缩小,而且在给定的矩形内保持宽高的比值不变 pix = pix.scaled(width, height,Qt::KeepAspectRatio); painter.drawPixmap(90, 90, pix);
其中参数Qt::KeepAspectRatio,是图片缩放的方式。能够将鼠标指针放到该代码上,按下F1键查看其帮助了,以下图所示。
这里有三个值,只看其示例图片就可大体明白,Qt::IgnoreAspectRatio是不保持图片的宽高比;Qt::KeepAspectRatio是在给定的矩形中保持宽高比;最后一个也是保持宽高比,但可能超出给定的矩形。这里给定的矩形是由咱们显示图片时给定的参数决定的,例如painter.drawPixmap(0,0,100,100,pix);就是在以(0,0)点为起始点的宽和高都是100的矩形中。运行程序效果以下图所示。
旋转使用的是QPainter类的rotate()函数,它默认是以原点为中心进行旋转的。若是要改变旋转的中心,可使用前面讲到的translate()函数完成。在paintEvent()函数中继续添加以下代码:
//让图片的中心做为旋转的中心 painter.translate(40, 50); painter.rotate(90); //顺时针旋转90度 painter.translate(-40,-50); //使原点复原 painter.drawPixmap(100, 100, 80, 100, pix);
这里必须先改变旋转中心,而后再旋转,而后再将原点复原,才能达到想要的效果。运行程序,以下图所示。
实现图片的扭曲,是使用的QPainter类的shear(qreal sh,qreal sv)函数完成的。它有两个参数,前面的参数实现横向变形,后面的参数实现纵向变形。当它们的值为0时,表示不扭曲。在paintEvent()中继续添加以下代码:
painter.shear(0.5, 0); //横向扭曲 painter.drawPixmap(100, 0, 80, 100, pix);
运行效果以下图所示。
QPainter提供了复合模式(Composition Modes)来定义如何完成数字图像的复合,即如何将源图像的像素和目标图像的像素进行合并。QPainter提供的经常使用复合模式及其效果以下图所示。 其中普通的类型是SoiirceOver(一般被称为alpha混合),就是正在绘制的源像素混合在已经绘制的目标像素上,源像素的alpha份量定义了它的透明度,这样源图像就会以透明效果在目标图像上进行显示。当设置了复合模式,它就会应用到全部的绘图操做中,例如画笔、画刷、渐变和pixmap/image绘制等。
实例:
void Widget::paintEvent(QPaintEvent *event) { QPainter painter; QImage image(400, 300, QImage::Format_ARGB32_Premultiplied); painter.begin(&image); painter.setBrush(Qt::green); painter.drawRect(100, 50, 200, 200); painter.setBrush(QColor(0, 0, 255, 150)); painter.drawRect(50, 0, 100, 100); painter.setCompositionMode(QPainter::CompositionMode_SourceIn); painter.drawRect(250, 0, 100, 100); painter.setCompositionMode(QPainter::CompositionMode_DestinationOver); painter.drawRect(50, 200, 100, 100); painter.setCompositionMode(QPainter::CompositionMode_Xor); painter.drawRect(250, 200, 100, 100); painter.end(); painter.begin(this); painter.drawImage(0, 0, image); }
这里先在Qlmage上绘制了一个矩形,而后又在这个矩形的4个角分别绘制了4个小矩形,每一个小矩形都使用了不一样的复合模式,而且使用了半透明的颜色进行填充。 第一个小矩形没有明确指定复合模式,它默认使用的是SourceOver模式。运行效果以下图所示。
参考: