1. 程式人生 > 實用技巧 >《QT Creator快速入門》第十章:2D繪製(2)

《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用來設定視口物理座標。