qt5-入门-2D绘图-坐标与绘图设备

参考:
C++ GUI Programming with Qt 4, Second Edition

本地环境:
win10专业版,64位,Qt 5.12


上一篇:
qt5-入门-2D绘图-基础-CSDN博客
https://blog.csdn.net/pxy7896/article/details/138284671


坐标系

QPainter默认坐标原点在屏幕左上角,水平向右是x增长的方向,垂直向下是y增长的方向。每个像素占据了一个1x1的方块。这样的坐标系其实是 half-pixel,指像素(x, y)的中心其实是在(x + 0.5, y + 0.5)上。比如要在(0, 0)绘制一个像素,其实是像素的左上角在(0, 0),因此这个像素的中心在(0.5, 0.5)。

上一节提到反走样,那个可以让曲线变得更平滑,但是反走样本身是需要一定的计算量的,所以默认是关闭的。而且反走样因为增加了像素,所以是无法精确控制到某一个像素的。

只有在禁止反走样时,才有0.5像素的偏移。如果使用了反走样,实际上,为了使(x, y)处产生一个像素,实际会在这个点的四方( (x-0.5, y-0.5)、(x-0.5, y+0.5)、(x+0.5, y-0.5)、(x+0.5, y+0.5) )各绘制一个像素,只是颜色/亮度不同。

下面比较一下关闭与开启反走样带来的区别:
在这里插入图片描述
可以看到,当把起点平移0.5像素后,pen width = 1和3时,反走样开启与否带来的差异已经被消除了。

viewport & window

viewport与window机制可以绘制与绘图设备的大小和分辨率无关的图形。使用QPainter绘制时,传给QPainter的是逻辑坐标,Qt会将逻辑坐标转换成物理坐标然后绘制。
逻辑坐标是window用的,物理坐标是viewport用的。
通常,视口和窗口的坐标是一致的。比如一个600 x 800的 widget,默认情况下,视口和窗口都是一个320 x 200的矩形,原点都在(0, 0),此时,视口和窗口的坐标是相同的。
但如果使用setWindow做这样的设置:painter.setWindow(-50, -50, 100, 100);就表示将(-50, -50)对应到物理坐标的(0, 0),后两个参数指明了window的长和高,虽然逻辑坐标系下是长100高100,但实际在物理坐标系中表示长320,宽200。
在这里插入图片描述
那么可以用比例简单算一下,如上图所示。

QPainter还提供一个“世界坐标转换”,但是转变的是坐标系。可以平移、旋转、剪切什么的。

QTransform的好处是,当有很多个图形需要做同一套变换时,可以设好一个transform,直接套用。如果只有一个需要变换的话,完全可以用painter.translate(-50.0, -50.0);这样的语句。

    void paintEvent(QPaintEvent *event) {
        QPainter painter(this);
        QFont font("Courier", 24);
        painter.setFont(font);
        painter.drawText(50, 50, "Test");

        QTransform transform;
        transform.translate(+50.0, +50.0);
        transform.rotate(+45.0);
        painter.setWorldTransform(transform);
        painter.drawText(50, 50, "Test");
    }

在这里插入图片描述

绘图设备

绘图设备是指继承了QPainterDevice的子类,包括QPixmap QBitmap QImage QPicture

  • QPixmap是专为图像设计的,针对图像的显示做了优化。是使用底层的绘制系统绘制的,无法提供像素级别的操作
    // 可以将图像绘制到指定位置
    QPainter painter(this); 
    QPixmap pixmap("Cat.png"); 
    painter.drawPixmap(10, 10, 128, 128, pixmap); 
    
  • QBitmapQPixmap的子类,只有黑白两种颜色
  • QImage为图像的像素级访问做了优化,是独立于硬件的绘制系统,是跨平台的
  • QPicture可以记录和重现QPainter的各条命令,是与平台无关的
    QPicture picture;
    QPainter painter;
    painter.begin(&picture);              // paint in picture
    QFont font("Courier", 24);
    painter.setFont(font);
    painter.drawText(50, 50, "Test");
    painter.end();
    picture.save("drawing.pic");
    
    // 如果要重现
    QPicture picture;
    picture.load("path/drawing.pic");          // load picture
    QPainter painter(this); // 我是在paintEvent中用的,所以写了this
    painter.begin(&picture);              // paint in picture
    painter.drawPicture(0, 0, picture); // draw the picture at (0,0)
    painter.end();
    
  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值