一点一滴成长

导航

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

1、抗锯齿渲染

    由于历史原因,QRect::right()和QRect::bottom()的返回值会偏离矩形真实的右下角,推荐使用QRectF来代替QRect,或者使用x() + width()和y() + height()来确定QRect的右下角。

    默认情况下,绘制会产生锯齿,可以使用QPainter::setRenderHint(RenderHint hint, bool on = true)来打开抗锯齿渲染,其中hint指定渲染方式,如QPainter::Antialiasing。

    例如以下为关闭和打开QPainter::Antialiasing抗锯齿渲染的效果:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawRect(1, 2, 20, 10);

    QPainter painter(this);
    painter.drawLine(2, 7, 6, 1);
}

    

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.drawRect(1, 2, 20, 10);
    
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.drawLine(2, 7, 6, 1);
}

    

 2、坐标变换

    坐标变换有基本变换、窗口-视口变换。

    ①、基本变换

    平移坐标系统:QPainter::translate()
    旋转坐标系统:QPainter::rotate()
    缩放坐标系统:QPainter::scale()
    扭曲坐标系统:QPainter::shear()
    保存当前坐标系统:QPainter::save()
    恢复保存的坐标系统:QPainter::restore()

   下面为使用示例:

void Widget::paintEvent(QPaintEvent * event)
{
    QPainter painter(this);
    painter.fillRect(rect(), Qt::white);

    painter.setPen(QPen(Qt::red, 11));
    painter.drawLine(QPoint(5, 6), QPoint(100, 99));

    painter.translate(200, 150);//将坐标系统平移,使(200, 150)作为坐标原点
    //painter.translate(-200, -150);//这样可以还原原点为(0, 0)
    painter.setPen(QPen(Qt::darkBlue, 11));
    painter.setRenderHint(QPainter::Antialiasing);
    painter.drawLine(QPoint(5, 6), QPoint(100, 99));

    painter.save();//保存painter的当前状态
    painter.rotate(90);//将坐标系统顺时针旋转90度
    painter.setPen(QPen(Qt::cyan, 11));
    painter.drawLine(QPoint(5, 6), QPoint(100, 99));
    painter.restore();//恢复painter到以前的状态

    painter.fillRect(-50, -50, 100, 50, QBrush(Qt::darkGreen));
    painter.save();
    painter.scale(0.5, 0.4);//将坐标系统进行缩放,水平为0.5倍,垂直为0.4倍
    painter.fillRect(-50, -50, 100, 50, QBrush(Qt::yellow));
    painter.restore();

    painter.setPen(Qt::blue);
    painter.setBrush(Qt::darkYellow);
    painter.drawEllipse(QRect(60, -100, 50, 50));
    painter.save();
    painter.shear(1.5, -0.7);//将坐标系统进行扭曲
    painter.setBrush(Qt::darkGray);
    painter.drawEllipse(QRect(60, -100, 50, 50));
    painter.restore();
}
View Code

    

    连续进行多个坐标转换的时候使用QTransform会更高效,下面使用QTimer定时器和QTransform坐标转换,模拟了简单时钟显示:

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    QTimer* timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));//信号和槽
    timer->start(1000);
}

void Widget::paintEvent(QPaintEvent * event)
{
    static int angle = 0;
    angle += 10;
    if(angle == 360)
        angle = 0;

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);//抗锯齿
    int sideMin = qMin(width(), height());

    QTransform transform;
    transform.translate(width() / 2, height() / 2);//移动坐标原点至中心点
    transform.rotate(angle);//将坐标系统顺时针旋转, 每次增加10°
    transform.scale(sideMin / 300, sideMin / 300);//将坐标系统缩放,以适应窗口放大
    painter.setWorldTransform(transform);//进行坐标转换

    painter.drawEllipse(-120, -120, 240, 240);//画圆
    painter.drawLine(0, 0, 100, 0);//画指针
}
View Code

    

     ②、窗口-视口转换

    使用QPainter的绘制函数进行绘制的时候使用的是逻辑坐标,它们最后会被转换为绘图设备的物理坐标来进行绘制。窗口是指逻辑坐标下的一个矩形,视口是物理坐标下的一个矩形。

    QPainter::setWindow用来设置窗口的逻辑坐标,QPainter::setViewport用来设置视口物理坐标。

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