Qt入门及c++复习(使合新手--6)绘图

绘图


QPainter

QPainter 是 Qt 框架中的一个类,用于在各种设备上绘制图形和文本。它是一个低级的绘图接口,提供了丰富的方法来绘制线条、形状、文本和图像等。QPainter 通常与 QWidget 或其子类一起使用,但也可以用于绘制到其他类型的设备上,QPainter可以在继承QPaintDevice类的任何对象进行操作。

QPainter的常见用法是在小部件的绘画事件中:构造和自定义(例如设置笔或画笔)painter,然后画画。

isActive()函数指示画家是否处于活动状态。画家由begin()函数和接受QPaintDevice参数的构造函数激活。end()函数和析构函数将其停用。

以下是使用 QPainter 的一些基本步骤:

  1. 创建 QPainter 对象: 创建一个 QPainter 对象需要一个目标设备上下文(如 QWidgetQImage)作为参数。

    QPainter::QPainter(QPaintDevice *device)
    QPainter painter(this); // 假设当前对象是一个QWidget的子类

  2. 设置画笔和画刷: 使用 QPaintersetPen()setBrush() 方法来设置绘制时使用的画笔和画刷。

    painter.setPen(QPen(Qt::black, 2)); // 设置画笔为黑色,宽度为2
    painter.setBrush(QBrush(Qt::blue)); // 设置画刷为蓝色

  3. 绘制图形: 使用 QPainter 的绘图方法来绘制线条、矩形、圆形等。

    painter.drawLine(10, 10, 100, 100); // 绘制一条从(10, 10)到(100, 100)的线
    painter.drawRect(50, 50, 100, 100); // 绘制一个矩形
    painter.drawEllipse(150, 150, 50, 50); // 绘制一个椭圆

  4. 绘制文本: 使用 QPainterdrawText() 方法来绘制文本。

    painter.drawText(200, 200, "Hello, Qt!");
  5. 绘制图像: 使用 QPainterdrawImage() 方法来绘制图像。

    QImage image("path/to/image.png");
    painter.drawImage(250, 250, image);
  6. 结束绘制: 完成绘制后,不需要手动销毁 QPainter 对象,因为它会自动在作用域结束时被销毁。

使用 QPainter 时,需要注意以下几点:

  • 绘制操作应在 QPainter 对象的作用域内完成,以确保资源正确释放。

  • 绘制操作是不可变的,即绘制完成后不能撤销。

  • 绘制操作是依赖于设备的,不同的设备可能有不同的性能表现。

QPainter 是 Qt 中进行自定义绘图的强大工具,适用于需要精细控制绘制过程的场合。

7.实例

#ifndef WIDGET_H
#define WIDGET_H
​
#include <QWidget>
​
namespace Ui {
class Widget;
}
​
class Widget : public QWidget
{
    Q_OBJECT
​
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    //The common use of QPainter is inside a widget's paint event
    void paintEvent(QPaintEvent *);
​
private:
    Ui::Widget *ui;
};
​
#endif // WIDGET_H
​
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
​
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}
​
Widget::~Widget()
{
    delete ui;
}
​
//The common use of QPainter is inside a widget's paint event
void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    
    //画笔
    QPen pen(QColor(255, 0, 0));
    pen.setWidth(3);
    pen.setStyle(Qt::DashDotLine);
    painter.setPen(pen);
    
    painter.drawLine(QPoint(0, 0), QPoint(100, 100));//线
    painter.drawEllipse(QPoint(100, 100), 20, 20);//圆
    painter.drawEllipse(QPoint(100, 100), 50, 80);//椭圆
    painter.drawRect(100, 100, 30, 30);//矩形
    painter.drawRect(100, 100, 30, 80);
    painter.drawText(100, 100, "I love you, Rick!");
    
    //画刷
    QBrush brush(Qt::green, Qt::Dense3Pattern);
    painter.setBrush(brush);
    
    painter.drawRect(200, 200, 50, 80);
    
    //QConicalGradient与QBrush结合使用,以指定锥形渐变画笔。
    QConicalGradient conicalGradient(QPointF(200, 100), 0);
    conicalGradient.setColorAt(0.2, Qt::cyan);
    conicalGradient.setColorAt(0.4, Qt::black);
    conicalGradient.setColorAt(0.7, Qt::red);
    conicalGradient.setColorAt(1, Qt::yellow);
    painter.setBrush(conicalGradient);
    
    painter.drawEllipse(QPointF(200, 100), 50, 50);
}

抗锯齿与坐标系变换
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
​
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}
​
Widget::~Widget()
{
    delete ui;
}
​
void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
​
    /*
    //1.Antialliasing, translate
    painter.setPen(QPen(Qt::red, 15));
    painter.drawEllipse(QPoint(200, 150), 100, 100);
    
    painter.setRenderHints(QPainter::Antialiasing);//抗锯齿
    painter.translate(200, 0);//图形平移变换
    painter.drawEllipse(QPoint(200, 150), 100, 100);
    */
​
    //2.rotate旋转
    /*
    painter.setPen(QPen(Qt::red, 10));
    painter.drawLine(QPoint(10, 10), QPoint(100, 100));
    painter.save();
    painter.translate(200, 0);
    painter.rotate(90);
    painter.setPen(QPen(Qt::blue, 10));
    painter.drawLine(QPoint(10, 10), QPoint(100, 100));
    painter.restore();
    */
​
    //3.scale缩放
    /*
    painter.setPen(QPen(Qt::red));
    painter.setBrush(Qt::yellow);
    painter.drawRect(50, 50, 50, 50);
    painter.save();
    painter.scale(0.5, 0.5);
    painter.setBrush(Qt::green);
    painter.drawRect(50, 50, 50, 50);
    painter.restore();
    */
​
    //4.shear
    painter.setPen(QPen(Qt::blue));
    painter.setBrush(Qt::yellow);
    painter.drawRect(50, 50, 50, 50);
    painter.save();
    painter.shear(0.5, 0.5);
    painter.setBrush(Qt::gray);
    painter.drawRect(50, 50, 50, 50);
    painter.restore();
​
}
​

void QPainter::setRenderHint(QPainter:RenderHint hint,bool on=true)

如果on为true,则在画家上设置给定的渲染提示;否则清除渲染提示。

void QPainter::translate(const QPointF&offset)

按给定的偏移量转换坐标系;即,将给定的偏移量加到点上。

void QPainter::translate(const QPoint&offset)

这是一个重载函数。按给定的偏移量转换坐标系。

void QPainter::translate(qreal dx,qreal dy)

这是一个重载函数。将坐标系转换为向量(dx,dy)。

void QPainter::save()

保存当前画家状态(将状态推送到堆栈上)。save()后面必须跟有相应的restore();end()函数解除堆栈的绑定。

void QPainter::restore()

恢复当前画家状态(从堆栈中弹出已保存的状态)。

void QPainter::rotate(qreal angle)

顺时针旋转坐标系。给定的角度参数以度为单位。

void QPainter::scale(qreal sx,qreal sy)

按(sx,sy)缩放坐标系。

void QPainter::shear(qreal sh,qreal sv)

通过(sh,sv)剪切坐标系。


绘制字体与路径
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QTimer>
#include <QPainterPath>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}
​
Widget::~Widget()
{
    delete ui;
}
​
​
void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
​
    //QFont font("华文琥珀", 20, QFont::Bold, true);
    QFont font("宋体", 30, QFont::Bold, true);
    font.setUnderline(true);
​
    painter.setFont(font);
    painter.setPen(Qt::blue);
    painter.drawText(50, 50, "I love you Rick!");
    //QPainter painter(this);
​
    QPainterPath path;
​
    path.moveTo(50, 250);
    path.lineTo(50,200);
    path.lineTo(100, 100);
    path.addEllipse(QPoint(100, 100), 30, 30);
    painter.setPen(Qt::red);
    painter.drawPath(path);
​
    path.translate(200, 0);
    painter.setPen(Qt::blue);
    painter.drawPath(path);
}

void QPainterPath::moveTo(const QPointF &point)

将当前点移动到给定点,隐式地开始一个子路径并关闭上一个子路径。

void QPainterPath::lineTo(const QPointF&endPoint)

添加一条从当前位置到给定端点的直线。绘制线条后,当前位置将更新为线条的终点。


绘制曲线
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
​
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
​
    resize(1600, 900);
    setStyleSheet("background-color: balck");
}
​
Widget::~Widget()
{
    delete ui;
}
​
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPen pen;
​
    pen.setColor(Qt::green);
    painter.setPen(pen);
​
    painter.drawArc(25, 25, 1550, 1550, 0 * 16, 180 * 16);
    painter.drawArc(180, 180, 1240, 1240, 0 * 16, 180 * 16);
    painter.drawArc(335, 335, 930, 930, 0 * 16, 180 * 16);
    painter.drawArc(490, 490, 620, 620, 0 * 16, 180 * 16);
    painter.drawArc(645, 645, 310, 310, 0 * 16, 180 * 16);
}
​

void QPainter::drawArc(const QRectF &rectangle,int startAngle,int spanAngle)

绘制由给定矩形、startAngle和spanAngles定义的弧。 起始角度和跨度角度必须以1/16度为单位指定,即一个完整的圆等于5760(16*360)。角度的正值表示逆时针方向,负值表示顺时针方向。零度在3点钟位置。

void QPainter::drawArc(int x,int y,int width,int height,int startAngle,int spanAngle)

绘制由从(x,y)开始的矩形定义的弧,具有指定的宽度和高度,以及给定的startAngle和spanAngle。


手动调用绘图事件处理函数(实现秒针)
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QTimer>
​
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
​
    angle = 0;
​
    QTimer *timer = new QTimer(this);
    timer->start(1000);
    connect(timer, &QTimer::timeout, [&](){update();});
}
​
Widget::~Widget()
{
    delete ui;
}
​
void Widget::paintEvent(QPaintEvent *)
{
    angle += 6;
    if(angle == 360)
        angle = 0;
​
    QPainter painter(this);
​
    painter.setRenderHint(QPainter::Antialiasing);
    painter.translate(width()/2, height()/2);
    painter.drawEllipse(QPoint(0, 0), 120, 120);
    painter.rotate(angle);
    painter.drawLine(QPoint(0, 0), QPoint(100, 0));
​
}

屏幕录制 2024-07-25 222715


QPaintDevice

QPaintDevice的绘图功能目前由QWidget、QImage、QPixmap、QGLPixelBuffer、QPicture和QPrinter子类实现。

Qt提供了四个类来处理图像数据:QImage、QPixmap、QBitmap和QPicture。QImage针对I/O、直接像素访问和操作进行了设计和优化,而QPixmap则针对在屏幕上显示图像进行了设计与优化。QBitmap只是一个继承QPixmap的便利类,确保深度为1。如果QPixmap对象确实是位图,则isQBitmap()函数返回true,否则返回false。最后,QPicture类是一个记录和重放QPainter命令的绘图设备。

  1. QPixmap

    • 用于表示一个像素图,尽管 QPixmap 的接口是平台无关的,但其底层实现可能会依赖于特定的平台特性。例如,不同操作系统上的图像处理库可能不同,Qt 会根据运行的平台使用相应的库。

    • 支持图像的简单操作,如缩放和旋转。

    • 通常用于在窗口小部件上显示图像。

    • 只能在主线程中使用。

  2. QPicture

    • 包含一系列图形项,如线条、形状和文本。

    • 可以把这些项绘制到任何QPainter设备上。

    • 适合用于存储和重放图形操作,例如,当需要将相同的图形绘制到不同的窗口或打印机时。

    • 存储形式是二进制形式。

  3. QImage

    • 表示一个用于高级图像处理的像素图。

    • 支持多种图像格式和深度(1、4、8、12、15、16、24、30、32位)。

    • 提供了广泛的像素级操作功能,如像素读写、图像转换等。

    • 适合用于图像的生成、编辑和复杂变换,多用于图片的传输。

  4. QBitmap

    • QPixmap的子类,表示一个单色或多色的位图。

    • 主要用于创建蒙版和掩码,用于图像的透明处理。

    • 通常与QPixmap一起使用,来定义图像的透明部分。

这些类在Qt中的使用场景和特点如下:

  • 当需要在窗口部件上显示图像时,使用QPixmap

  • 当需要记录和重放一系列图形操作时,使用QPicture

  • 当需要进行高级图像处理,如像素级操作时,使用QImage

  • 当需要创建图像的透明效果或掩码时,使用QBitmap

在实际应用中,这些类通常与QPainter一起使用,QPainter是一个绘画类,提供了一系列绘制图形项的方法。例如,在QWidgetpaintEvent函数中,使用QPainter来绘制图像、文本、线条等。

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
​
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
​
    /*   QPixmap
    QPixmap pix(400, 300);
    pix.fill(Qt::white);
    QPainter painter(&pix);
    painter.setPen(Qt::red);
    painter.drawEllipse(QPoint(100, 100), 50 ,50);
    pix.save("D://mypix.jpg");
    */
    //QImage
    QImage img(400, 300, QImage::Format_RGB32);
    img.fill(Qt::white);
    QPainter painter(&img);
    painter.setPen(Qt::red);
    painter.drawEllipse(QPoint(100, 100), 50 ,50);
    img.save("E://myImage.jpg");
}
​
Widget::~Widget()
{
    delete ui;
}
​
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QImage img;
    img.load(":/Image/Image/optimus prime.jpeg");
​
    for(int i = 50; i < 100; i++)
    {
        for(int j = 50; j < 100; j++)
        {
            QRgb rgb = qRgb(255, 0, 0);
            img.setPixel(i, j, rgb);
        }
    }
​
    painter.drawImage(0, 0, img);
}
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QPicture>
#include <QBitmap>
​
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
​
    /*
    //QPicture  可以理解为是一个绘图的容器,里面保存有绘图的纪录和重绘制的指令
    //存储的形式是二进制形式,也就是说我们无法双击打开picture文件
    QPicture pic;
    //QPainter painter(&pic);
    QPainter painter;
    painter.begin(&pic);
    painter.setPen(Qt::red);
    painter.drawEllipse(QPoint(100, 100), 50, 50);
    painter.end();
    pic.save("E://abc.xyz");
    */
​
    QBitmap bm(400, 300);
    QPainter painter(&bm);
    painter.setPen(Qt::red);
    painter.drawEllipse(QPoint(100, 100), 50, 50);
    bm.save("E://bm.jpg");
}
​
Widget::~Widget()
{
    delete ui;
}
​
void Widget::paintEvent(QPaintEvent *)
{
    /*
    QPainter painter(this);
    QPicture pic;
    pic.load("E://abc.xyz");
    painter.drawPicture(0, 0, pic);
    */
    QPainter painter(this);
    QBitmap bm;
    bm.load("E://optimus prime.jpeg");
    painter.drawPixmap(0, 0, bm);
}

QPainterQPainterDevice 区别

QPainterQPaintDeviceQPaintEngine类一起构成了Qt绘画系统的基础。QPainter是用于执行绘图操作的类。QPaintDevice表示可以使用QPainter进行绘图的设备。QPaintEngine提供了画家在不同类型的设备上绘制的界面。如果画家处于活动状态,则device()返回画家正在其上绘制的绘制设备,paintEngine()返回画家当前正在其上操作的绘制引擎。

QPainter

QPainter 是一个绘图类,它提供了一个抽象的接口,用于在各种设备上绘制图形和文本。它是一个高级的绘图对象,可以与多种设备上下文一起使用,比如 QWidgetQImageQPrinter 等。

QPainterDevice

QPainterDevice 是一个抽象基类,定义了与绘图设备相关的接口。它定义了所有绘图设备必须实现的方法和属性,比如:

  • 像素尺寸width()height() 方法返回设备的像素尺寸。

  • 分辨率logicalDpiX()logicalDpiY() 方法返回设备的逻辑分辨率。

  • 颜色深度colorCount() 方法返回设备支持的颜色数量。

  • 绘图设备类型paintDevice() 方法返回设备类型。

区别
  • 功能定位QPainter 是一个绘图工具,提供了绘制操作的方法;而 QPainterDevice 是一个设备接口,定义了绘图设备的基本属性和功能。

  • 使用方式QPainter 通常与具体的绘图设备(如 QWidgetQImage)一起使用,而 QPainterDevice 是这些设备的抽象表示。

  • 抽象层次QPainter 抽象了绘图操作,使得开发者不需要关心具体的设备类型;QPainterDevice 则抽象了设备的基本属性和功能。

示例
// 使用QPainter绘制到QWidget
QWidget widget;
QPainter painter(&widget);
painter.drawLine(10, 10, 100, 100);
​
// 使用QPainter绘制到QImage
QImage image(100, 100, QImage::Format_RGB32);
QPainter painter2(&image);
painter2.drawLine(10, 10, 90, 90);
​
// 获取QPainterDevice的属性
QPainterDevice *device = painter.device();
int width = device->width();
int height = device->height();

通过这种方式,QPainterQPainterDevice 共同构成了 Qt 框架中强大的绘图系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值