Qt 中图像的绘制

Qt中的绘图类

以下是常见的绘图类

绘图 QPainter QBrush
QFont
QPen
QColor
QPaintDevice QGLFramebufferObject
QGLPixelBuffer
QOpenGLPaintDevice
QPagedPaintDevice QPdfWriter
QPrinter
QPaintDeviceWindow QOpenGLWindow
QRasterWindow
QRasterWindow
QRasterWindow
QImage
QPicture
QPixmap QBitmap
QPaintEngine

Qt中常见2D绘图的介绍

Qt有个绘画系统,这个系统是能够使用相同的API在屏幕和打印设备上进行绘画,主要基于主要基于QPainter、QPaintDevice和QPaintEngine类。

QPainter用于执行绘图操作,QPaintDevice是可以使用QPainter在其上绘制的二维空间的抽象,QPaintEngine提供了画家用于在不同类型的设备上绘制的接口。QPaintEngine类由QPainter和QPaintDevice内部使用,并且对应用程序程序员隐藏,除非他们创建自己的设备类型。

QPainter介绍

QPainter提供了全面的函数来完成大多数GUI绘图程序所需的功能。它可以画任何东西,从简单的线条到复杂的形状圆和和弦。它还可以绘制对齐的文本和像素图。通常,它在“自然”坐标系中绘制,但它也可以进行视图和世界变换。QPainter可以对继承QPaintDevice类的任何对象进行操作。

QPainter的常见用途是在小部件的绘画事件中:构造和自定义(例如设置笔或画笔)画家。然后画画。请记住在绘制后销毁QPainter对象。例如:

void SimpleExampleWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setPen(Qt::blue);
    painter.setFont(QFont("Arial", 30));
    painter.drawText(rect(), Qt::AlignCenter, "Qt");
}

QPainter的核心功能是绘图,但该类还提供了几个功能,允许您自定义QPainter设置及其渲染质量,以及其他启用剪裁的功能。此外,可以通过指定画家的构图模式来控制不同形状如何合并在一起。

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

注意:当paintdevice是一个小部件时,QPainter只能在paintEvent()函数内部或在paintEvent()调用的函数中使用。

QPaintDevice介绍

QPaintDevice类是可以绘制的对象的基类,即QPainter可以在任何QPaintDivice子类上绘制。QPaintDevice的绘图功能由QWidget、QImage、QPixmap、QPicture、QPrinter和QOpenGLPaintDevice实现。

警告:Qt要求在创建任何绘制设备之前存在QGuiApplication对象。绘制设备访问窗口系统资源,并且在创建应用程序对象之前不会初始化这些资源。

QWidget

QWidget是所有界面控件元素的基类。QWidget可以捕获鼠标、键盘和其他事件并且可以在界面字自己绘制自己显示界面。

QImage

QImage类为I/O以及直接像素访问和操作而设计和优化提供了一种独立于硬件的图像表示。QImage支持多种图像格式,包括单色、8位、32位和阿尔法混合图像。

使用QImage作为绘制设备的一个优点是,可以以独立于平台的方式保证任何绘制操作的像素精度。另一个好处是绘画可以在当前GUI线程之外的另一个线程中执行。

QPixmap

QPixmap类是为在屏幕上显示图像设计和优化提供的一种屏幕外图像表示。与QImage不同,像素图中的像素数据是内部的,由底层窗口系统管理,即只能通过QPainter功能或将QPixmap转换为QImage来访问像素。

为了使用QPixmap优化绘图,Qt提供了QPixmapCache类,该类可用于存储生成成本高昂的临时像素图,而无需使用超过缓存限制的存储空间。

Qt还提供了QBitmap便利类,继承了QPixmap。QBitmap保证单色(1位深度)像素图,主要用于创建自定义QCursor和QBrush对象,构建QRegion对象。

QPicture

QPicture类是一个用于记录和回放QPainter命令绘画设备。图片以独立于平台的格式将画家命令序列化到IO设备。QPicture也与分辨率无关,即QPicture可以显示在不同的设备上(例如svg、pdf、ps、打印机和屏幕)看起来相同。

Qt提供了QPicture::load()和QPicture::save()函数,以及用于加载和保存图片的流式操作符。

Qt中坐标系的转换

在Qt中通常QPainter在设置自己额度坐标系(通常是像素)上运行。默认坐标系的坐标原点是在左上角。为了绘图方便QPainter提供了一系列的坐标转换函数。

最常用的变换是缩放、旋转、平移和剪切。使用scale()函数按给定偏移量缩放坐标系,使用rotate()函数顺时针旋转坐标系,并使用translate()平移坐标系(即向点添加给定偏移量)。也可以使用shear()函数围绕原点扭曲坐标系。

绘图设备的物理坐标系是基本的坐标系(默认坐标系),可以通过QPainter中函数进行转换为逻辑坐标。在此基础上Qt还提供了视口坐标系和窗口坐标系。视口坐标系表示的绘图设备的任意一个矩形区域的物理坐标,默认情况下视口就等于绘图设备的整个矩形区域。

视口与窗口是同一个矩形,只不过窗口用的是逻辑坐标系,坐标原点为视口的中心点。

Qt中图像的绘制

painter有绘制像素图/图像的函数,即drawPixmap()、drawImage()和drawTiledPixmap()。drawPixmap()和drawImage()都会产生相同的结果,只是drawPixmap()在屏幕上更快,而drawImages()在QPrinter或其他设备上可能更快。

为了使用QPainter获得最佳渲染效果,您应该使用独立于平台的QImage作为绘制设备;即使用QImage将确保结果在任何平台上具有相同的像素表示。

Qt中绘图例子

以上介绍了Qt中一些绘图的相关知识,如果需要了解详细内容可以查看qt的官方文档。

绘图步骤:

1、创建QPainter对象,可以在创建构造的时候传入绘图设备。可以在不使用参数在需要绘图的时候使用begin函数传入绘图设备,在绘制结束之后使用end函数结束绘图,不然或出现卡死的状态。

2、使用QPainter中的绘图函数进行绘图。

1、在QWidget中绘制

在Qt中绘制图像有两种情况,第一种就是绘制的当前窗口就是QWidget,因此只需要在重载paintEvent函数即可在此函术中使用painter画家画图。

另一种就是给当前窗口中的子窗体QWidget绘制图像,这时候也有两种方式:

1、自定义一个父类继承QWidget,并将当前窗口中QWidget窗口提升为自定义的QWidget类,在自定义的QWidget类中重载paintEvent函数实现绘图。

    //1、创建画家QPainter widget
    m_painter = new QPainter();
void MainWindow::paintEvent(QPaintEvent *)
{
    drawForWidget();
}

void MainWindow::drawForWidget()
{
    m_painter->begin(this);
    //提供画笔
    QPen pen;
    pen.setColor(QColor(Qt::red));
    pen.setWidth(3);
    m_painter->setPen(pen);
    //绘制一条直线
    m_painter->drawLine(0,0,20,20);
    m_painter->end();
}

2、使用事件过滤器,首先在QWidget中插入事件过滤器,之后再当前窗体所在父窗口的cpp文件中重载事件过滤器,通过事件过滤器中的判断实现绘图。在此之前还需要再父类的绘图事件函数中发出绘图事件。

    //1、创建画家QPainter widget
    m_painter = new QPainter();
    ui->widget->installEventFilter(this);
void MainWindow::paintEvent(QPaintEvent *)
{
    drawForWidget();
}


void MainWindow::drawForWidget()
{
    m_painter->begin(ui->widget);
    //提供画笔
    QPen pen;
    pen.setColor(QColor(Qt::red));
    pen.setWidth(3);
    m_painter->setPen(pen);
    //绘制一条直线
    m_painter->drawLine(0,0,20,20);
    m_painter->end();
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == ui->widget && event->type() == QEvent::Paint)//发生绘图事件,且是在widget上发生的
            {
            QPainter painter(ui->widget);
            // 设置画笔样式
            QPen pen(Qt::red);
            pen.setWidth(3);
            painter.setPen(pen);

            // 绘制圆形
            QRectF rectangle(10.0, 20.0, 80.0, 80.0);    // 圆形所在矩形位置和大小
            painter.drawEllipse(rectangle);

            return true;
            }
        else
            return false;
}

2、在Image绘图设备中绘图

Qt中在Image中绘制图片的时候方法和之前的步骤一样,唯一有区别的地方就是在QImage中绘制图的时候不需要在paintEvent绘图事件中执行。在函数任意调用的到的地方执行即可。

void MainWindow::drawForImage()
{
    QImage m_image;
    m_image = QImage(100,100, QImage::Format_ARGB32/*_Premultiplied*/);
    QPainter pt(&m_image);
    //提供画笔
    QPen pen;
    pen.setColor(QColor(Qt::red));
    pen.setWidth(3);
    pt.setPen(pen);
    //绘制一条直线
    pt.drawLine(10,0,10,100);//绘制直线
    pt.drawEllipse(QRect(10,0,100,100));//绘制椭圆
    pt.drawText(10,10,"绘制在Image");
    m_image.save("C:\\Users\\admin\\Desktop\\ship\\output.jpg");//保存到本地文件
    ui->label->setPixmap(QPixmap::fromImage(m_image));//显示到界面
}

在这里使用QImage绘图的是有会有一个问题:

问题:QPainter::begin: Paint device returned engine == 0, type: 3

出现原因:是由于创建QImage对象的时候没有给图像指定大小,出现的问题。

解决办法:在创建QImage绘图设备的时候指定QImage对象的大小。

3、在QPixmap中绘制图

Qt中在QImage和QPixmap绘图思路和方法一样,只不过是绘图设备不一样而已。

    //1、创建画家QPainter widget
    m_painter = new QPainter();
void MainWindow::drawForQPixmap()
{
    QPixmap pixmap(200,200);
    m_painter->begin(&pixmap);
    //提供画笔
    QPen pen;
    pen.setColor(QColor(Qt::red));
    pen.setWidth(3);
    m_painter->setPen(pen);
    //绘制一条直线
    m_painter->drawLine(10,10,10,100);//绘制直线
    m_painter->drawEllipse(QRect(50,50,200,200));//绘制椭圆
    m_painter->drawText(20,10,"绘制在pixmap");
    pixmap.save("C:\\Users\\admin\\Desktop\\ship\\pixmap.jpg");//保存到本地文件
    ui->label->setPixmap(pixmap);//显示到界面

}

其他

在qt绘图中涉及到了很多类和,其中主要涉及的有QPainter、QWidget、QImage、QPixmap、QColor、QPen、QBrush等相关类。如果想绘制更精致更好的曲线需要详细去了解相关的类。以上例子只是做了一个最基础、最简单的绘图。

你可能感兴趣的:(Qt笔记,qt,开发语言)