《QT Creator快速入門》第十章:2D繪製(2)
阿新 • • 發佈:2020-09-11
1、抗鋸齒渲染
由於歷史原因,QRect::right()和QRect::bottom()的返回值會偏離矩形真實的右下角,推薦使用QRectF來代替QRect,或者使用x() + width()和y() + height()來確定QRect的右下角。
預設情況下,繪製會產生鋸齒,可以使用QPainter::setRenderHint(RenderHint hint, bool on = true)來開啟抗鋸齒渲染,其中hint指定渲染方式,如QPainter::Antialiasing。
例如以下為關閉和開啟QPainter::Antialiasing抗鋸齒渲染的效果:
voidWidget::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::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用來設定視口物理座標。