一点一滴成长

导航

《QT Creator快速入门》第十章:2D绘制(1)

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中进行绘制工作,如绘制线:

void Widget::paintEvent(QPaintEvent* )
{
    QPainter painter;
    painter.begin(this);
    painter.drawLine(QPoint(0, 0), QPoint(100, 100));
    painter.end();
}
View Code

      

  也可以在QPainter对象的构造函数中直接传入QPaintDevice,不用再调用begin和end:

void Widget::paintEvent(QPaintEvent* )
{
    QPainter painter(this);
    painter.drawLine(QPoint(0, 0), QPoint(100, 100));
}
View Code

  3、画笔 

   可以使用画笔来改变线条的颜色、宽度、风格等:

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));
}
View Code

     

    其中QPen::setJoinStyle()可以设置两条线相交的风格,其不同参数的效果如下所示:

    

    绘制矩形和圆弧:

    

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);
}
View Code

     

4、画刷

    画刷有多种填充模式,如下所示:

    

     可以用QBrush()、setStyle()、setTexture()来设置或改变画刷的填充模式。下面为先设置画笔为绿色,然后使用不同的画刷类型来绘制矩形,圆形,四边形,最后还原画刷为初始再绘制一个矩形:

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);
}
View Code

    

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);
}
View Code

   

    可以使用fillRect()来直接绘制一块矩形区域,使用eraseRect()来擦除一块矩形区域:

void Widget::paintEvent(QPaintEvent* )
{
    QPainter painter(this);
    painter.fillRect(60, 20, 150, 100, QBrush(Qt::darkYellow));
}
View Code

    

 5、渐变色

     QGradient渐变色类用来跟QBrush一起来实现渐变色填充,QGradient有三个派生类,即三种渐变色填充方式:QLinearGradient线性渐变、QRadialGradient辐射渐变、QConicalGradient锥形渐变。

     ①、QLinearGradient线性渐变

            QLinearGradient线性渐变就是在开始点和结束点之间填充颜色,使用如下:

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);
}
View Code

    

          我们修改开始点和结束点的代码和效果如下:

QLinearGradient linearGradient(QPoint(0, r.top()), QPoint(0, r.bottom()));

    

         再次修改开始点和结束点的代码和效果如下:

QLinearGradient linearGradient(r.topLeft(), r.bottomRight());

        

        还可以设置多种颜色:

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);
}
View Code

    

             还可以对Cpen进行渐变色设置,使绘制的线条、文字等也呈渐变色显示,代码及效果如下:

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!");
}
View Code

         

            还可以使用QLinearGradient::setSpread()用来设置渐变区域以外区域的颜色模式。

      ②、QRadialGradient辐射渐变

           QRadialGradient的构造函数QRadialGradient ( const QPointF & center, qreal radius, const QPointF & focalPoint )分别用来初始化圆心,半径,和焦点。然后分别由焦点向圆环、圆环向焦点填充各自的颜色。焦点位置为0, 圆环位置为1,示例代码及效果如下:

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);
}
View Code

      

            修改焦点位置的代码及效果如下:

QRadialGradient radialGradient(QPointF(200, 190), 80, QPointF(250, 190));//设置圆心,半径,和焦点

     

     ③、锥形渐变QConicalGradient

           锥形渐变QConicalGradient的示例代码及效果如下:

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);
}
View Code

          

6、绘制路径

    创建一个QPainterPath路径对象后就会以坐标原点为当前点,可以通过moveTo()改变当前点,通过lineTo()、arcTo()、QuadTo()、cublicTo()将直线、弧线、二次贝塞尔曲线、三次贝塞尔曲线加入到路径中,这时候当前点会自动改变为这些图形的终点。还可以使用addRect()、addEllipse()、addText()、addPath()等添加图形或文字:

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);
}
View Code

  

   根据三个点(起点、中间点、终点)绘制的贝塞尔曲线:

   根据四个点(起点、两个中间点、终点)绘制的贝塞尔曲线 :

          

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);
}
View Code

    

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);
}
View Code

  

    QPainter::translate()可以平移坐标系统。

    填充路径的时候有两种模式:Qt::OddEvenFill(默认)、Qt::WindingFill,两种填充效果的代码及效果如下:

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);
}
View Code

   

 7、QRubberBand

    利用QRubberBand类可以实现类似我们在桌面上拖动鼠标出现的橡皮筋线,如图所示:

    

posted on 2020-09-11 09:31  整鬼专家  阅读(885)  评论(0编辑  收藏  举报