资源描述
单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,单击此处编辑母版标题样式,*,1,嵌入式,GUI,程序设计,Qt5,图形与图片(第六章),教学回顾,Qt,内置对话框(重点),Qt,工具盒;,Qt,进度条;,Qt,调色板;,Qt,可扩展对话框,2,教学内容,Qt,绘制事件,Qt 2D,绘图,画笔,画刷,基本图形和文本绘制,渐变填充,绘制文本,图像处理,坐标系统与坐标变换,绘图举例:表盘,3,4,Qt,绘制事件,事件处理和绘制(,Painting,),当应用程序收到绘制事件时,就会调用,QWidget:paintEvent(),,该函数就是绘制窗口的地方,有两种方法要求重绘一个窗口,update(),把重绘事件添加到事件队列中,重复调用,update(),会被,Qt,合并为一次,不会产生图像的闪烁,可带参数指定重绘某个区域,repaint(),立即产生绘制事件,一般情况下不推荐使用此方法,只使用在需要立即重绘的特效情况下,可带参数指定重绘某个区域,5,事件处理和绘制(,Painting,),为处理绘制事件,只需要,重写,paintEvent,函数,,并在该函数中,实例化一个,QPainter,对象,进行绘制,6,class MyWidget:public QWidget,.,protected:,void,paintEvent,(QPaintEvent*);,void MyWidget:paintEvent(QPaintEvent*ev),QPainter,p(this);,.,基本绘制,QPainter,类,提供,绘制操作,其构造函数原型为:,QPainter,(QPaintDevice*,device,),QPaintDevice,代表绘制,2D,图像的,画布,如下继承,QPaintDevice,的类对象都可用于,QPainter,绘制,QWidget,QImage,QPixmap,QPicture,QPrinter,QSvgGenerator,QGLPixelBuffer,QGLFrameBufferObject,.,7,8,Qt 2D,绘图,QT 2D,绘图,Qt,中的,2D,绘图部分,由,3,个类支撑整个框架:,QPainter,用来执行具体的绘图相关操作如画点,画线,填充,变换,,alpha,通道等。,QPaintDevice,是,QPainter,用来绘图的绘图设备,,Qt,中有几种预定义的绘图设备,如,QWidget,,,QPixmap,,,QImage,等。他们都从,QPaintDevice,继承。,9,QPainter,线和轮廓,都可以用,画笔,(QPen),进行绘制,用,画刷,(QBrush),进行,填充,。,字体,使用,QFont,类定义,当绘制文字时,,Qt,使用指定字体的属性,如果没有匹配的字体,,Qt,将使用最接近的字体,通常情况下,,QPainter,以默认的坐标系统进行绘制,也可以用,QMatrix,类,对坐标进行变换,10,QPainter,当绘制时,可以使用,QPainter:RenderHint,来告诉绘图引擎是否,启用反锯齿功能,使图变得平滑,QPainter:RenderHint,的可取值,QPainter:Antialiasing,:告诉绘图引擎应该在可能的情况下进行边的反锯齿绘制,QPainter:TextAntialiasing,:尽可能的情况下文字的反锯齿绘制,QPainter:SmoothPixmapTransform,:使用平滑的,pixmap,变换算法,(,双线性插值算法,),,而不是近邻插值算法,11,QPainter,的绘图函数,drawArc(),弧,drawChord(),弦,drawConvexPolygon(),凸多边形,drawEllipse(),椭圆,drawImage()QImage,表示的图像,drawLine(),线,drawLines(),多条线,drawPath(),路径,drawPicture(),按,QPainter,指令绘制,drawPie(),扇形,drawPixmap()QPixmap,表示的图像,drawPoint(),点,drawPoints(),多个点,drawPolygon(),多边形,drawPolyline(),多折线,drawRect(),矩形,drawRects(),多个矩形,drawRoundRect(),圆角矩形,drawText(),文字,drawTiledPixmap(),平铺图像,drawLineSegments(),绘制折线,12,13,画笔,画笔,画笔的属性包括,线型、线宽、颜色,等。画笔属性可以,在构造函数中,指定,也可以使用,setStyle(),,,setWidth(),,,setBrush(),,,setCapStyle(),,,setJoinStyle(),等函数设定,Qt,中,使用,Qt:PenStyle,定义了,6,种画笔风格,分别是,Qt:SolidLine,,,Qt:DashLine,,,Qt:DotLine,,,Qt:DashDotLine,,,Qt:DashDotDotLine,,,Qt:CustomDashLine,。,自定义线风格,(Qt:CustomDashLine),,需要使用,QPen,的,setDashPattern(),函数来设定自定义风格。,14,线型,Qt:SolidLine,Qt:DashLine,Qt:DotLine,Qt:DashDotLine,Qt:DashDotDotLine,Qt:CustomDashLine,由,dashPattern,控制,15,画笔,端点风格,(cap style),端点风格决定了线的端点样式,只对线宽大于,1,的线有效。,Qt,定义了三种端点风格用枚举类型,Qt:PenCapStyle,表示,分别为,Qt:SqureCap,,,QT:FlatCap,,,Qt:RoundCap,。,连接风格,(Join style),连接风格是两条线如何连接,连接风格对线宽大于等于,1,的线有效。,Qt,定义了四种连接方式,用枚举类型,Qt:PenStyle,表示。分别是,Qt:MiterJoin,,,Qt:BevelJoin,,,Qt:RoundJoin,,,Qt:SvgMiterJoin,。,16,端点风格和连接风格,连接风格,Qt:BevelJoin,,斜边,(default),Qt:MiterJoin,Qt:RoundJoin,17,端点风格,Qt:SquareCap(default),:矩形封线尾,Qt:FlatCap,:不封线尾,Qt:RoundCap,画笔示例,18,QPainter p(this);,QPen pen(Qt:black,5);,p.setPen(pen);,p.drawPolygon(polygon);,19,画刷,画刷,在,Qt,中图形使用,QBrush,进行填充,画刷包括,填充颜色,和,风格,(,填充模式,),。,在,Qt,中,颜色使用,QColor,类,表示,,QColor,支持,RGB,,,HSV,,,CMYK,颜色模型。,QColor,还支持,alpha,混合的轮廓和填充。,RGB,是面向硬件的模型。颜色由,红绿蓝,三种基色混合而成。,HSV/HSL,模型比较符合人对颜色的感觉,由色调,(0-359),,饱和度,(0-255),,亮度,(0-255),组成,主要用于颜色选择器。,CMYK,由青,洋红,黄,黑四种基色组成。主要用于打印机等硬件拷贝设备上。每个颜色分量的取值是,0-255,。,另外,QColor,还可以用,SVG1.0,中定义的任何颜色名为参数初始化。,基本模式填充包括有各种点、线组合的模式。,20,QColor,Qcolor,的构造函数,r,(,red,),g,(,green,),b,(,blue,),a,(,alpha,)的取值范围为,0-255,Alpha,控制透明度,255,:不透明,0,:完全透明,Qt,预定义颜色,21,QColor(int r,int g,int b,int a),颜色微调,颜色可以通过如下函数进行微调,QColor:,lighter,(int factor),QColor:,darker,(int factor),22,darker,lighter,Qt:red,QRgb,QRgb,类,可以用于,保存颜色值,,可,与,QColor,相互转换,获取,32-bit,的,RGB,颜色值,+alpha,值,创建新颜色,获取单独某个颜色值,:,qRed,qGreen,qBlue,qAlpha,获取灰度值,23,QRgb orange=qRgb(255,127,0);,QRgb overlay=qRgba(255,0,0,100);,int red=qRed(orange);,int gray=qGray(orange);,实色画刷,调用画刷构造函数,24,QBrush red(Qt:red);,QBrush odd(QColor(55,128,97);,QPainter p(this);,p.setPen(Qt:NoPen);,p.setBrush(Qt:red);,p.drawPolygon(polygon);,模式画刷,模式化画刷构造函数,25,QBrush(const QColor&color,Qt:BrushStyle style),带纹理的画刷,以,QPixmap,为参数的构造函数,如果使用黑白的,pixmap,,则用画刷颜色,如果使用彩色,pixmap,,则用,pixmap,的颜色,26,QBrush(const QPixmap&pixmap),QPixmap pacPixmap(pacman.png);,painter.setPen(QPen(Qt:black,3);,painter.setBrush(pacPixmap);,painter.drawEllipse(rect();,27,基本图形和文本绘制,基本图形绘制,实现,paintEvent,函数,28,void RectWithCircle:paintEvent(QPaintEvent*ev),QPainter p(this);,p.setBrush(Qt:green);,p.drawRect(10,10,width()-20,height()-20);,p.setBrush(Qt:yellow);,p.drawEllipse(20,20,width()-40,height()-40);,基本文本绘制,QPainter:drawText,29,QPainter p(this);,QFont font(Helvetica);,p.setFont(font);,p.drawText(20,20,120,20,0,Hello World!);,font.setPixelSize(10);,p.setFont(font);,p.drawText(20,40,120,20,0,Hello World!);,font.setPixelSize(20);,p.setFont(font);,p.drawText(20,60,120,20,0,Hello World!);,QRect r;,p.setPen(Qt:red);,p.drawText(20,80,120,20,0,Hello World!,r,返回文本,外边框的矩形区域,30,渐变填充,渐变填充,Qt,提供了,渐变填充,的画刷,渐变填充包括两个要素:,颜色的变化,和,路径的变化,。,颜色变化可以指定从一种颜色渐变到另外一种颜色。,路径变化指在路径上,指定一些点的颜色,进行分段渐变。,Qt,中,提供了三种渐变填充,线性,(QLinearGradient),圆形,(QRadialGradient),圆锥渐变,(QConicalGradient),所有的类都从,QGradient,类,继承,构造渐变填充的画刷,QBrush b=QBrush(QRadialGradient(.);,31,填充设置,从图形的起点到终点,以从,0,至,1,的比例渐变填充,完成,0-1,范围的填充后,,后续颜色铺开的方式,可以不同,通过,setSpread(),函数来设置,32,QGradient:setColorAt(qreal pos,QColor);,QGradient:PadSpread,(default),QGradient:RepeatSpread,QGradient:ReflectSpread,线性渐变填充,线性渐变填充指定两个控制点,画刷在两个控制点之间进行颜色插值。,通过创建,QLinearGradient,对象来设置画刷。,QPainter p(this);,QLinearGradient g(0,0,100,100);,g.setColorAt(0.0,Qt:white);,g.setColorAt(1.0,Qt:blue);,p.setBrush(g);,p.drawRect(0,0,100,100);,在,QGradient,构造函数中指定线性填充的两点分别为,(0,0),,,(100,100),。,setColorAt(),函数在,0-1,之间,设置指定位置的颜色。,33,线型填充示例,34,圆形渐变填充,圆形渐变填充需要指定,圆心,半径和焦点,,,QRadialGradient(qreal cx,qreal cy,qreal radius,qreal fx,qreal fy),。画刷在焦点和圆上的所有点之间进行颜色插值。创建,QRadialGradient,对象设置画刷,QPainter painter(this);,QRadialGradient radialGradient(50,50,50,30,30);,radialGradient.setColorAt(0.0,Qt:white);,radialGradient.setColorAt(1.0,Qt:blue);,painter.setBrush(radialGradient);,painter.drawRect(0,0,100,100);,35,圆锥渐变填充,圆锥渐变填充指定,圆心,和,开始角,,,QConicalGradient(qreal cx,qreal cy,qreal angle),。画刷,沿圆心逆时针对颜色进行插值,,创建,QConicalGradient,对象并设置画刷。,QPainter painter(this);,QConicalGradient conicalGradient(50,50,90);,conicalGradient.setColorAt(0,Qt:white);,conicalGradient.setColorAt(1,Qt:blue);,painter.setBrush(conicalGradient);,painter.drawRect(0,0,100,100);,为了实现自定义填充,还可以使用,QPixmap,或者,QImage,对象进行纹理填充。两种图像分别使用,setTexture(),和,setTextureImage(),函数加载纹理。,36,37,绘制文本,文本绘制,使用,QPainter,进行文本绘制,基本文本绘制,带选项的文本绘制,带返回信息的文本绘制,38,drawText(QPoint,QString),drawText(QRect,QString,QTextOptions),drawText(QRect,flags,QString,QRect*),使用字体,Qt,提供了,QFont,类,来表示字体,当创建,QFont,对象时,,Qt,会使用指定的字体,如果没有对应的字体,,Qt,将寻找一种最接近的已安装字体,Font family,Size,Bold/Italic/Underline/Strikeout/,字体信息可以通过,QFontInfo,取出,并可用,QFontMetrics,取得字体的相关数据。,使用,QApplication:setFont(),可以设置应用程序默认的字体,当,QPainter,绘制指定的字体中不存在的字符时将绘制一个空心的正方行。,39,Font Family,在构造函数中指定字体,得到可用字体列表,40,QFont font(Helvetica);,font.setFamily(Times);,QFontDatabase database;,QStringList families=database.families();,Font Size,字体尺寸可以用像素尺寸(,pixel size,)或点阵尺寸(,point size,),41,QFont font(Helvetica);,font.setPointSize(14);/14 points high,/depending on the paint devices dpi,font.setPixelSize(10);/10 pixels high,字体效果,可以激活字体效果,QWidget:font,函数和,QPainter:font,函数,返回,现有字体的,const,引用,因而需要先拷贝现有,font,,再做修改,42,Normal,bold,italic,strike out,underline,overline,QFont tempFont=w-font();,tempFont.setBold(true);,w-setFont(tempFont);,测量文本大小,QFontMetrics,可用于测量,文本和,font,的大小,boundingRect,函数可用于测量,文本块的大小,43,QImage image(200,200,QImage:Format_ARGB32);QPainter painter(qDebug(height:%d,fm.boundingRect(0,0,200,0,Qt:AlignLeft|Qt:TextWordWrap,loremIpsum).height();,中文显示问题,使用,QTextCodec,类,#include,QTextCodec:setCodecForTr(QTextCodec:codecForName(GB2312);,int ret=QMessageBox:warning(0,tr(PathFinder),tr(,您真的想要退出?,),QMessageBox:Yes|QMessageBox:No);,44,45,图像处理,图像处理,Qt,提供了,4,个处理图像的类。,QImage,,,QPixmap,,,QBitmap,,,QPicure,。它们有着各自的特点。,QImage,优化了,I/O,操作,可以直接存取操作像素数据。,QPixmap,优化了在屏幕上显示图像的性能。,QBitmap,从,QPixmap,继承,只能表示两种颜色。,QPicture,是可以记录和重启,QPrinter,命令的类。,46,转换,在,QImage,和,QPixmap,之间转换,47,QImage QPixmap:toImage();,QPixmap QPixmap:fromImage(const QImage,读入和保存,如下代码使用,QImageReader,和,QImageWriter,类进行,这些类在保存时通过文件的扩展名确定文件格式,48,QPixmap pixmap(image.png);,pixmap.,save,(image.jpeg);,QImage image(image.png);,image.,save,(image.jpeg);,在,QImage,上绘制,QImage,是,QPaintDevice,的子类,因而,QPainter,可以在其上绘制,49,QImage image(100,100,QImage:Format_ARGB32);,QPainter painter(,painter.setBrush(Qt:red);,painter.fillRect(image.rect(),Qt:white);,painter.drawRect(,image.rect().adjusted(20,20,-20,-20);,image.save(image.jpeg);,在,QPixmap,上绘制,QPixmap,是,QPaintDevice,的子类,因而,QPainter,可以在其上绘制,主要用于屏幕绘制,50,void MyWidget:imageChanged(const QImage&image),pixmap=QPixmap:fromImage(image);,update();,void MyWidget:paintEvent(QPaintEvent*),QPainter painter(this);,painter.drawPixmap(10,20,pixmap);,51,坐标系统与坐标变换,坐标系统,Qt,坐标系统由,QPainter,控制,同时也由,QPaintDevice,和,QPaintEngine,类控制。,Qt,绘图设备默认坐标,原点是左上角,,,X,轴向右增长,,,Y,轴向下增长,,默认的单位在基于像素的设备上是像素,在打印机设备上是,1/72,英寸,(0.35,毫米,),QPainter,的逻辑坐标与,QPainterDevice,的物理坐标之间的映射由,QPainter,的变换矩阵,worldMatrix(),、视口,viewport(),和窗口,window(),处理。,未进行坐标变换的情况下,逻辑坐标和物理坐标是一致的,52,坐标值的表示方法,如果不进行坐标变换,直接进行绘图,可用,QPainter,的,window(),函数取得绘图窗口,然后在此绘图窗口内进行绘制,使用,QPoint,QSize,和,QRect,表示,坐标值,和,区域,QPoint:point(x,y),QSize:size(width,height),QRect:point,和,size,(x,y,width,height),QPointF/QSizeF/QRectF,用于表示,浮点数坐标,53,坐标变换,通常,QPainer,在设备的坐标系统上绘制图形,但,QPainter,也支持坐标变换。,QPainter:scale(),函数:比例变换,QPainter:rotate(),函数:旋转变换,QPainter:translate(),函数:平移变换,QPainter:shear(),函数:图形进行扭曲变换,所有变换操作的变换矩阵都可以通过,QPainter:wordMatrix(),函数取出。不同的变换矩阵可以使用堆栈保存。,用,QPainter:save(),保存变换矩阵到堆栈,,用,QPainter:restore(),函数,将其弹出堆栈,。,54,坐标变换,坐标变换的顺序很重要,在做平移变换、旋转变换和扭曲变换时,原点也很重要,55,p.setBrush(Qt:red);,p.drawRect(200,20,120,120);,p.translate(0,100);,p.drawRect(200,20,120,120);,p.rotate(35);,p.drawRect(200,20,120,120);,p.setBrush(Qt:red);,p.drawRect(200,20,120,120);,p.rotate(35);,p.drawRect(200,20,120,120);,p.translate(0,100);,p.drawRect(200,20,120,120);,坐标变换的保存和恢复,通过,save,和,restore,函数,可以将坐标变换的状态保存和恢复,56,QPoint rotCenter(50,50);,qreal angle=42;,p.,save,();,p.translate(rotCenter);,p.rotate(angle);,p.translate(-rotCenter);,p.setBrush(Qt:red);,p.setPen(Qt:black);,p.drawRect(25,25,50,50);,p.,restore,();,p.setPen(Qt:NoPen);,p.setBrush(QColor(80,80,80,150);,p.drawRect(25,25,50,50);,应用变换,画红色矩形,画灰色矩形,2.5D,坐标变换,可以以任何坐标轴做旋转操作,以产生,3D,效果,57,p.setBrush(Qt:gray);p.setRenderHint(QPainter:Antialiasing);,p.drawRect(100,100,100,100);,QTransform t;,t.translate(150,0);,t.rotate(60,Qt:YAxis);,p.setTransform(t,true);,p.setBrush(Qt:red);,p.drawRect(-50,100,100,100);,视口和窗口,视口,表示,物理坐标,下的任意矩形。而,窗口,表示在,逻辑坐标,下的相同矩形。,视口由,QPainter,的,viewport(),函数获取,窗口由,QPainter,的,window(),函数获取,默认情况下,逻辑坐标与物理坐标,是相同的,,与绘图设备上的矩形也是一致的。,使用,窗口视口变换,可以使逻辑坐标符合自定义要求,这个机制通常用来完成,设备无关的绘图代码,。,通过调用,QPainter:setWindow(),函数可以完成坐标变换,设置窗口或视口矩形实际上是执行线性变换。本质上是窗口四个角映射到对应的视口四个角,反之亦然。因此,应注意保持视口和窗口,x,轴和,y,轴之间的比例变换一致,从而保证变换不会导致绘制变形。,58,59,绘图举例:表盘,表盘,自定义绘制,可以与键盘和鼠标交互,60,表盘,画表盘的背景,61,void CircularGauge:paintEvent(QPaintEvent*ev),QPainter p(this);,int extent;,if(width()height(),extent=height()-20;,else,extent=width()-20;,p.translate(width()-extent)/2,(height()-extent)/2);,p.setPen(Qt:white);,p.setBrush(Qt:black);,p.drawEllipse(0,0,extent,extent);,.,画背景圆形,将油表放在,中心位置,表盘,画表盘的刻度,62,void CircularGauge:paintEvent(QPaintEvent*ev),.,p.translate(extent/2,extent/2);,for(int angle=0;angle=270;angle+=45),p.save();,p.rotate(angle+135);,p.drawLine(extent*0.4,0,extent*0.48,0);,p.restore();,.,注意,save,和,restore,函数,简单调用,rotate(45),会增大舍入误差,表盘,画表盘的指针,63,void CircularGauge:paintEvent(QPaintEvent*ev),.,p.rotate(m_value+135);,QPolygon polygon;,polygon QPoint(-extent*0.05,extent*0.05),QPoint(-extent*0.05,-extent*0.05),type()=QEvent:KeyPress),if(QKeyEvent*ke=static_cast(ev),if(ke-key()=Qt:Key_0),if(o-metaObject()-indexOfProperty(value)!=-1),o-setProperty(value,0);,return true;,return false;,返回,true,,停止,对该事件的响应,安装事件过滤器,调用,installEventFilter,函数,由于该,filter,对象是应用于属性(,property,)的,它可以用于任何具有该属性的对象,如,QSlider,QDial,QSpinBox,等,如果勇于尝试,可以为,QApplication,添加事件过滤器,66,ComposedGauge compg;,CircularGauge circg;,KeyboardFilter filter;,compg.installEventFilter(,circg.installEventFilter(,课堂小结,67,思考题,68,作业题(工程打包上传至课间区),时钟设计(表盘、指针),可选方法:,全部用绘图函数;,贴图;,69,预习内容,第,5,章,QT5,主窗体,70,
展开阅读全文