1、QPainter
使用QPainter来进行绘制操作,常用的有:
QPainter::drawPoint:绘制点
QPainter::drawLine:绘制线
QPainter::drawRect:绘制矩形
QPainter::drawRoundedRect:绘制圆角矩形
QPainter::drawPolyline:绘制折线,即多个首尾相连的线
QPainter::drawPolygon:绘制折线形,即多边形
QPainter::drawEllipse:绘制圆形
QPainter::drawArc:绘制圆弧
QPainter::drawPie:绘制扇形
QPainter::drawChord:绘制弦
QPainter::drawConvexPolygon:绘制凸多边形
QPainter可以剪切一个矩形、区域、路径,分别使用setClipRect()、setClipRegion()、setClipPath()函数来实现,然后就只能在剪切的区域内进行绘制,超出剪切区域的话不会显示绘制的内容:
void Widget::Widget::paintEvent(QPaintEvent* pe) { QPainter painter(this); painter.setClipRect(10, 0, 20, 10); painter.drawText(10, 10, "test"); //注意y坐标是绘制文字的baseline }
void MainWindow::paintEvent(QPaintEvent* pe) { QPainter painter(this); QBrush brush(QColor(255, 0, 0));//画刷颜色为红色,画刷填充模式为Qt::SolidPattern painter.setBrush(brush); painter.setPen(Qt::blue); //画笔颜色为蓝色 painter.drawRect(50, 50, 100, 80); }
drawRect()的绘制位置有时会有些特殊,下面是使用画笔宽度分别为1 (默认)、2、3的情况下进行的边框绘制代码:
void MainWindow::paintEvent(QPaintEvent* pe) { QPainter painter(this); //画笔宽度为1的话(默认),实际绘制的大小会比传入的大小+1 QPen pen(Qt::red, 1); painter.setPen(pen); painter.drawRect(QRect(0, 0, width() - 1, height() - 1)); //画笔宽度为2的话,实际绘制的位置会比传入的位置-1,大小会比传入的大小+2 QPen pen(Qt::red, 2); painter.setPen(pen); painter.drawRect(QRect(1, 1, width() - 2, height() - 2)); //画笔宽度为2的话,实际绘制的位置会比传入的位置-1,大小会比传入的大小+3 QPen pen(Qt::red, 3); painter.setPen(pen); painter.drawRect(QRect(1, 1, width() - 3, height() - 3)); }
2、paintEvent()
一般在重绘事件处理函数paintEvent中进行绘制工作,如绘制线:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { QPainter painter; painter.begin(this); painter.drawLine(QPoint(0, 0), QPoint(100, 100)); painter.end(); }
也可以在QPainter对象的构造函数中直接传入QPaintDevice,不用再调用begin和end:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { QPainter painter(this); painter.drawLine(QPoint(0, 0), QPoint(100, 100)); }
3、画笔
可以使用画笔来改变线条的颜色、宽度、风格等:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { //使用画笔绘制线 QPainter painter(this); QPen pen; pen.setColor(Qt::red);//画笔颜色 pen.setWidth(10);//画笔宽度 pen.setStyle(Qt::DashLine);//画笔类型:实线Qt::SolidLine、虚线Qt::DashLine、点线Qt::DotLine等 pen.setCapStyle(Qt::RoundCap);//画笔端点风格,直形Qt::FlatCap,圆形Qt::RoundCap //pen.setJoinStyle(Qt::RoundJoin);//两个线条端点连接的风格 painter.setPen(pen); painter.drawLine(QPoint(0, 0), QPoint(100, 100)); }
其中QPen::setJoinStyle()可以设置两条线相交的风格,其不同参数的效果如下所示:
绘制矩形和圆弧:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { QPainter painter(this); QPen pen(Qt::green, 3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);//在构造函数中设置画笔颜色、宽度等 painter.setPen(pen); QRectF rectF(70.0, 40.0, 80.0, 60.0);//所在矩形 int startAngle = 0 * 16;//起始角度 * 16,0度为3点钟方向 int spanAngle = 180 * 16;//跨越角度 * 16,逆时针 painter.drawRect(rectF); pen.setColor(Qt::red);//改变画笔颜色 painter.setPen(pen); painter.drawArc(rectF, startAngle, spanAngle); }
4、画刷
画刷有多种填充模式,如下所示:
可以用QBrush()、setStyle()、setTexture()来设置或改变画刷的填充模式。下面为先设置画笔为绿色,然后使用不同的画刷类型来绘制矩形,圆形,四边形,最后还原画刷为初始再绘制一个矩形:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { QPainter painter(this); QPen pen(QColor(0, 255, 0)); pen.setWidth(2); painter.setPen(pen); QBrush brush(QColor(0, 0, 255));//画刷颜色为蓝色,画刷填充模式为Qt::SolidPattern painter.setBrush(brush); painter.drawRect(60, 20, 50, 40); brush.setStyle(Qt::Dense4Pattern);//画刷填充模式为Qt::Dense4Pattern painter.setBrush(brush); painter.drawEllipse(120, 20, 50, 50); brush.setTexture(QPixmap("F://draw.png"));//设置画刷纹理为使用一个图片 painter.setBrush(brush); static const QPointF points[4] = { QPointF(170.0, 80.0), QPointF(190.0, 10.0), QPointF(250.0, 30.0), QPointF(290.0, 70.0) }; painter.drawPolygon(points, 4); brush.setStyle(Qt::NoBrush);//画刷填充模式为Qt::NoBrush painter.setBrush(brush); painter.drawRect(300, 20, 50, 40); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::Widget::paintEvent(QPaintEvent* pe) { QPainter painter(this); QBrush brush(QColor(255, 0, 0)); painter.setBrush(brush); //绘制三角形 const QPoint points[3] = { QPoint(100, 20), QPoint(150, 40), QPoint(200, 20) }; painter.drawPolygon(points, 3); const QPoint points2[4] = { QPoint(100, 60), QPoint(150, 80), QPoint(200, 60) }; painter.drawPolyline(points2, 3); }
可以使用fillRect()来直接绘制一块矩形区域,使用eraseRect()来擦除一块矩形区域:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { QPainter painter(this); painter.fillRect(60, 20, 150, 100, QBrush(Qt::darkYellow)); }
5、渐变色
QGradient渐变色类用来跟QBrush一起来实现渐变色填充,QGradient有三个派生类,即三种渐变色填充方式:QLinearGradient线性渐变、QRadialGradient辐射渐变、QConicalGradient锥形渐变。
①、QLinearGradient线性渐变
QLinearGradient线性渐变就是在开始点和结束点之间填充颜色,使用如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { //矩形区域 QRect r(20, 20, 260, 260); //线性渐变,设置起点和终点 QLinearGradient linearGradient(QPoint(r.left(), 0), QPoint(r.right(), 0)); //设置一半黄色,一半红色 linearGradient.setColorAt(0, Qt::yellow); linearGradient.setColorAt(1, Qt::red); //添加渐变到QPainter QPainter painter(this); painter.setBrush(linearGradient); //绘制矩形 painter.drawRect(r); }
我们修改开始点和结束点的代码和效果如下:
QLinearGradient linearGradient(QPoint(0, r.top()), QPoint(0, r.bottom()));
再次修改开始点和结束点的代码和效果如下:
QLinearGradient linearGradient(r.topLeft(), r.bottomRight());
还可以设置多种颜色:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { //矩形区域 QRect r(20, 20, 260, 260); //线性渐变,设置起点和终点 QLinearGradient linearGradient(QPoint(r.left(), 0), QPoint(r.right(), 0)); //设置三分之一黄色,三分之一红色,三分之一绿色 linearGradient.setColorAt(0, Qt::yellow); linearGradient.setColorAt(0.5, Qt::red); linearGradient.setColorAt(1, Qt::green); //添加渐变到QPainter QPainter painter(this); painter.setBrush(linearGradient); //绘制矩形 painter.drawRect(r); }
还可以对Cpen进行渐变色设置,使绘制的线条、文字等也呈渐变色显示,代码及效果如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { //线性渐变,设置起点和终点 QLinearGradient linearGradient(QPoint(30, 0), QPoint(210, 0)); //设置一半黄色,一半红色 linearGradient.setColorAt(0, Qt::yellow); linearGradient.setColorAt(1, Qt::red); //添加渐变到Qen QPainter painter(this); painter.setPen(QPen(linearGradient, 5)); //绘制线条和文字 painter.drawLine(30, 80, 210, 80); painter.drawText(30, 130, "Welcome to the world of QT!"); }
还可以使用QLinearGradient::setSpread()用来设置渐变区域以外区域的颜色模式。
②、QRadialGradient辐射渐变
QRadialGradient的构造函数QRadialGradient ( const QPointF & center, qreal radius, const QPointF & focalPoint )分别用来初始化圆心,半径,和焦点。然后分别由焦点向圆环、圆环向焦点填充各自的颜色。焦点位置为0, 圆环位置为1,示例代码及效果如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { QRadialGradient radialGradient(QPointF(200, 190), 50, QPointF(200, 190));//设置圆心,半径,和焦点 radialGradient.setColorAt(0, QColor(255, 0, 0));//设置焦点颜色 radialGradient.setColorAt(1, QColor(0, 0, 0));//设置圆环颜色 QPainter painter(this); painter.setBrush(radialGradient); painter.drawEllipse(QPointF(200, 190), 50, 50); }
修改焦点位置的代码及效果如下:
QRadialGradient radialGradient(QPointF(200, 190), 80, QPointF(250, 190));//设置圆心,半径,和焦点
③、锥形渐变QConicalGradient
锥形渐变QConicalGradient的示例代码及效果如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent* ) { QConicalGradient conicaGradient(QPointF(350, 190), 60); conicaGradient.setColorAt(0.2, Qt::cyan); conicaGradient.setColorAt(0.9, Qt::black); QPainter painter(this); painter.setBrush(conicaGradient); painter.drawEllipse(QPointF(350, 190), 50, 50); }
6、绘制路径
创建一个QPainterPath路径对象后就会以坐标原点为当前点,可以通过moveTo()改变当前点,通过lineTo()、arcTo()、QuadTo()、cublicTo()将直线、弧线、二次贝塞尔曲线、三次贝塞尔曲线加入到路径中,这时候当前点会自动改变为这些图形的终点。还可以使用addRect()、addEllipse()、addText()、addPath()等添加图形或文字:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::Widget::paintEvent(QPaintEvent* pe) { QPainterPath path; path.moveTo(20, 80); path.lineTo(20, 30);//绘制直线 path.cubicTo(80, 0, 50, 50, 80, 80);//绘制贝塞尔曲线 QPainter painter(this); painter.drawPath(path); }
根据三个点(起点、中间点、终点)绘制的贝塞尔曲线:
根据四个点(起点、两个中间点、终点)绘制的贝塞尔曲线 :
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent *event) { QPainter painter(this); QPainterPath path; //添加一条直线 path.moveTo(50, 280); path.lineTo(50, 230); //添加一条贝塞尔曲线 path.cubicTo(QPointF(105, 40), QPointF(115, 80), QPointF(120, 60)); //添加一条直线:从贝塞尔曲线终点到(130, 130) path.lineTo(130, 130); //添加一个圆:以(130, 130)为圆点 path.addEllipse(QPoint(130, 130), 30, 30); //绘制路径 painter.drawPath(path); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::Widget::paintEvent(QPaintEvent* pe) { QPainter painter(this); QBrush brush(QColor(255, 0, 0)); painter.setBrush(brush); //绘制线条+三角形 QPainterPath path; path.moveTo(150, 80); path.lineTo(150, 120); QPolygonF poy({QPointF(100.0, 120.0), QPointF(150.0, 140.0), QPointF(200.0, 120.0), QPointF(100.0, 120.0)}); path.addPolygon(poy); painter.drawPath(path); }
QPainter::translate()可以平移坐标系统。
填充路径的时候有两种模式:Qt::OddEvenFill(默认)、Qt::WindingFill,两种填充效果的代码及效果如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void Widget::paintEvent(QPaintEvent *event) { QPainter painter(this); QPainterPath path; path.addEllipse(10, 50, 100, 100); path.addRect(50, 100, 100, 100); painter.setBrush(Qt::cyan); painter.drawPath(path); painter.translate(180, 0); path.setFillRule(Qt::WindingFill); painter.drawPath(path); }
7、QRubberBand
利用QRubberBand类可以实现类似我们在桌面上拖动鼠标出现的橡皮筋线,如图所示: