QT-QPainter绘制曲线等基本图形
Qt中繪制2D圖形最核心的一個類是QPainter。類QPainter是在設(shè)備類QPaintDevice上繪制幾何圖形(包括直線、曲線、圓形、弧形、矩形等等),其中設(shè)備類QPaintDevice的子類又有QWidget、QImage、QPictrue、QPixmap、QOpenGLPaintDevice等,也即是說,我們可以繼承這些類,通過重寫QPaintEvent事件進(jìn)行重繪,或者用事件過濾器捕獲QPaintEvent事件信息進(jìn)行響應(yīng)重繪也行。
一、原理講解
本文主要總結(jié)用類QPainter繪制直線、矩形、圖片。其中,繪制直線用畫筆類QPen,繪制矩形不但用單畫筆類QPen,還要用到畫刷類QBrush,繪制圖片需要用類QPixmap。
QPen:繪制幾何圖形邊緣的線段顏色、線段寬度、線段各種類型(點畫線、虛線、solid實體線段)等等;
QBrush:填充幾何圖形的調(diào)色板,由顏色和填充風(fēng)格組成。
QPixmap:加載圖片資源,一般是較小的圖片。如果圖片很大,可以用QImage,然后通過QPixmap::fromImage(QImage *)進(jìn)行加載;
1.1繪制直線
繪制直線用到函數(shù)QPainter::drawLine(QPoint,QPoint),步驟如下:
a1:先設(shè)置畫筆QPen線段顏色、線段寬度、線段類型;
a2:確定繪制直線的起點和終點;
a3:初始化QPainter,設(shè)置畫筆QPen,然后調(diào)用函數(shù)QPainter::drawLine()進(jìn)行直線繪制;
核心代碼如下:
#include <QPen>
#include <QPoint>
#include <QPaintEvent>
?
void QCustomWidget::paintEvent(QPaintEvent *event)
{
? ? Q_UNUSED(event);
? ? //繪圖前準(zhǔn)備畫筆、畫刷
? ? QPen pen; //畫筆。繪制圖形邊線,由顏色、寬度、線風(fēng)格等參數(shù)組成
? ? pen.setColor(QColor(255,0,0,255)); ? ?
? ? QPainter painter(this); ? //可在QPaintDevice上繪制各種圖形。QPaintDevice有之類QWidget、QImage、QOpenGLPaintDevice等
? ? painter.setPen(pen); ? ?
? ? painter.drawLine(QPoint(0,0),QPoint(this->rect().width()-50,0)); ? //QPainter繪制直線
}
1.2繪制矩形
繪制矩形用到核心函數(shù)為QPainter::drawRect(),步驟如下:
?
a1:先設(shè)置畫筆QPen線段顏色、線段寬度、線段類型,也就是矩形的邊框;
a2:接著確定畫刷QBrush的填充顏色和填充類型;初始化是,要設(shè)置填充顏色和填充類型(QBrush::setStyle(Qt::SolidPattern);),否則畫刷填充失敗!!!
a3:確定繪制矩形的起點、終點、寬度、高度;
a3:初始化QPainter,設(shè)置畫筆QPen和畫刷QBrush,然后調(diào)用函數(shù)QPainter::drawRect()繪制矩形;
核心代碼如下:
void QCustomWidget::paintEvent(QPaintEvent *event)
{
? ? Q_UNUSED(event);
? ? //繪圖前準(zhǔn)備畫筆、畫刷
? ? QPen pen; //畫筆。繪制圖形邊線,由顏色、寬度、線風(fēng)格等參數(shù)組成
? ? pen.setColor(QColor(255,0,0,255));
? ? QBrush brush; ? //畫刷。填充幾何圖形的調(diào)色板,由顏色和填充風(fēng)格組成
? ? brush.setColor(QColor(0,255,0,120));
? ? brush.setStyle(Qt::SolidPattern);
? ? QPainter painter(this); ? //可在QPaintDevice上繪制各種圖形。QPaintDevice有之類QWidget、QImage、QOpenGLPaintDevice等
? ? painter.setPen(pen);
? ? painter.setBrush(brush);
? ? painter.drawRect(50,50,200,100);
}
1.3繪制圖像
繪制圖像用到核心函數(shù)為QPainter::drawPixmap(),步驟如下:
?
a1:實例一個QPixmap對象,然后加載一幅圖片;
a2:調(diào)用函數(shù)QPainter::drawPixmap()進(jìn)行圖片繪制;
核心代碼如下:
void QCustomWidget::paintEvent(QPaintEvent *event)
{
? ? Q_UNUSED(event); ?
?
? ? QPainter painter(this); ? //可在QPaintDevice上繪制各種圖形。QPaintDevice有之類QWidget、QImage、QOpenGLPaintDevice等
? ??
? ? //繪制圖片
? ? QPixmap pixmap;
? ? pixmap.load((QString(":/resource/image/向右箭頭.jpg")));
? ? painter.drawPixmap(rect().width()-50,0,50,50,pixmap);
}
二、完整實例代碼工程
該工程是一個完整的實例,功能包括用QPainter繪制直線、繪制和填充矩形、繪制圖片、實時輸出窗口QWIdget大小和最大化時的窗口大小尺寸。其中,所有功能都封裝在繼承QWidget的類QCustomWidget,只要調(diào)用QWidget一樣調(diào)用類QCustomWidget就行。
?
2.1新建一個類名為QCustomWidget,分別在qcustomwidget.h、qcustomwidget.cpp中添加如下代碼
qcustomwidget.h
#ifndef QCUSTOMWIDGET_H
#define QCUSTOMWIDGET_H
?
#include <QWidget>
?
class QCustomWidget : public QWidget
{
? ? Q_OBJECT
public:
? ? explicit QCustomWidget(QWidget *parent = nullptr);
?
signals:
?
protected:
? ? void paintEvent(QPaintEvent *event);
?
public slots:
};
?
#endif // QCUSTOMWIDGET_H
?
qcustomwidget.cpp
#include "qcustomwidget.h"
?
#include <QPen>
#include <QBrush>
#include <QPoint>
#include <QPixmap>
#include <QPainter>
#include <QDebug>
?
QCustomWidget::QCustomWidget(QWidget *parent) : QWidget(parent)
{
? ? this->resize(960,640);
// ? ?this->setWindowFlag(Qt::FramelessWindowHint); ? //設(shè)置無邊框
}
?
void QCustomWidget::paintEvent(QPaintEvent *event)
{
? ? Q_UNUSED(event);
? ? //繪圖前準(zhǔn)備畫筆、畫刷
? ? QPen pen; //畫筆。繪制圖形邊線,由顏色、寬度、線風(fēng)格等參數(shù)組成
? ? pen.setColor(QColor(255,0,0,255));
? ? QBrush brush; ? //畫刷。填充幾何圖形的調(diào)色板,由顏色和填充風(fēng)格組成
? ? brush.setColor(QColor(0,255,0,120));
? ? brush.setStyle(Qt::SolidPattern);
? ? QPainter painter(this); ? //可在QPaintDevice上繪制各種圖形。QPaintDevice有之類QWidget、QImage、QOpenGLPaintDevice等
? ? painter.setPen(pen);
? ? painter.setBrush(brush);
? ? painter.drawLine(QPoint(0,0),QPoint(this->rect().width()-50,0)); ? //QPainter繪制直線
? ? painter.drawRect(50,50,200,100);
?
? ? //繪制圖片
? ? QPixmap pixmap;
? ? pixmap.load((QString(":/resource/image/向右箭頭.jpg")));
? ? painter.drawPixmap(rect().width()-50,0,50,50,pixmap);
?
? ? qDebug()<<rand();
}
?
2.2調(diào)用代碼如下
QCustomWidget *customWidget=new QCustomWidget;
customWidget->show();
?
2.3程序運行結(jié)果圖如下
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?最大化前
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?最大化后
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 拖拽圖片
?
/************************
使用qt的QPainter可以繪制出任何你想要的圖形,同時也須要一定的功底;下面介紹動態(tài)正弦曲線(水波效果)的畫法。
為了更好理解,分4部分去理解如何繪制。先介紹畫一個畫三角形,再介紹畫二個畫三角形,然后畫靜態(tài)正弦曲線(水波),最后,畫動態(tài)正弦曲線(水波效果)。主要用到QPainter與QPainterPath類。
一、下面介紹一個畫三角形
文件包含如圖零所示
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖零:包含文件
triangle.pro?
?
QT ? ? ? += core gui
?
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
?
TARGET = triangle
TEMPLATE = app
?
?
SOURCES += \
? ? main.cpp \
? ? triangle.cpp
?
HEADERS ?+= \
? ? triangle.h
triangle.h
?
#ifndef TRIANGLE_H
#define TRIANGLE_H
?
#include <QWidget>
#include <QPainter>
#include <QtMath>
#include <QDebug>
?
class Triangle : public QWidget
{
? ? Q_OBJECT
public:
? ? explicit Triangle (QWidget *parent = 0);
?
protected:
? ? void paintEvent(QPaintEvent *event);
private:
?
};
?
#endif // TRIANGLE_H
main.cpp
?
#include "triangle.h"
#include <QApplication>
?
?
int main(int argc, char *argv[])
{
? ? QApplication a(argc, argv);
?
? ? Triangle myTriangle;
? ? myTriangle.show();
?
? ? return a.exec();
}
triangle.cpp
#include "triangle.h"
Triangle::Triangle(QWidget *parent) : QWidget(parent)
{
}
?
void Triangle::paintEvent(QPaintEvent *event)
{
? ?Q_UNUSED(event);
? ?QPainter painter(this); ?//QWidget為繪圖設(shè)備,創(chuàng)建一個畫刷對象,主要用到設(shè)置顏色和填充模式,brush,setBrush
? ?int width=this->width(); ?//獲取QWidget 窗口的寬度
? ?int height=this->height();//獲取QWidget 窗口的高度
? ?QPainterPath drawtriangle; ?//單獨畫三角形
?
? ?drawtriangle.moveTo(0, height);//左下角,第一點坐標(biāo)為(0,height);
? ?drawtriangle.lineTo(width/2, width/2);//第二點坐標(biāo)為(width/2,width/2)
? ?drawtriangle.lineTo(width, height);//右下角,第三坐標(biāo)(width, height),移動到右下角結(jié)束點,整體形成一個閉合路徑
? ?painter.setBrush(Qt::green); ? //填充綠色
? ?painter.drawPath(drawtriangle); ?//繪制出圖形
}
效果如圖一所示?
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖一:triangle
二、畫兩個三角形
修改上述的triangle.cpp文件 為如下代碼
#include "triangle.h"
Triangle::Triangle(QWidget *parent) : QWidget(parent)
{
}
?
void Triangle::paintEvent(QPaintEvent *event)
{
? ?Q_UNUSED(event);
? ?QPainter painter(this); ?//QWidget為繪圖設(shè)備,創(chuàng)建一個畫刷對象,主要用到設(shè)置顏色和填充模式,brush,setBrush
? ?int width=this->width(); ?//獲取QWidget 窗口的寬度
? ?int height=this->height();//獲取QWidget 窗口的高度
? ?QPainterPath drawtriangle; ?//單獨畫三角形
?
? ?drawtriangle.moveTo(0, height);//左下角,第一點坐標(biāo)為(0,height);
? ?drawtriangle.lineTo(width/4, height/2);//第二點坐標(biāo)為(width/4,height/2)
? ?drawtriangle.lineTo(width/2, height);//第三點坐標(biāo)為(width/2,height)
? ?drawtriangle.lineTo(width*3/4,height/2);//第四點坐標(biāo)為(width*3/4,height/2)
? ?drawtriangle.lineTo(width, height);//右下角,第五坐標(biāo)(width, height),移動到右下角結(jié)束點,整體形成一個閉合路徑
? ?painter.setBrush(Qt::green); ? //填充綠色
? ?painter.drawPath(drawtriangle); ?//繪制出圖形
}
效果如圖二所示?
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖二:兩個三角形
三、畫靜態(tài)正弦曲線(水波)
修改上述的triangle.cpp文件 為如下代碼
#include "triangle.h"
Triangle::Triangle(QWidget *parent) : QWidget(parent)
{
}
?
?
void Triangle::paintEvent(QPaintEvent *event)
{
? ? ?Q_UNUSED(event);
? ? ?QPainter painter(this); ?//QWidget為繪圖設(shè)備,創(chuàng)建一個畫刷對象,主要用到設(shè)置顏色和填充模式,brush,setBrush
? ? ?int width=this->width(); ?//獲取QWidget 窗口的寬度
? ? ?int height=this->height(); //獲取QWidget 窗口的高度
? ? ?//正弦曲線公式 y = A * sin(ωx + φ) + k
? ? ?double w = M_PI/100; ?//w為角速度 ,可以理解為波浪的密度,越大密度越大
? ? ?double A = 20; ? ?// ?A表示振幅,可以理解為水波的高度,越大高度越高
? ? ?double k = 20; ? ?// ?k表示y軸偏移
?
?
? ? ?QPainterPath wave; //波浪區(qū)域
? ? ?wave.moveTo(0, height);//第一點坐標(biāo)為(0,height);
? ? ?double m_offset = 6; //初相位,初值該值不一樣,獲得waveY也不一樣,可試驗該值為不同值的時候,曲線的起始點的區(qū)別 ? ? ? ?//
? ? ?for(int x = 0; x <= width; x+=1) ?//x從0~w的值而改變,從而得到正弦曲線
? ? ?{
? ? ? ? ? double waveY = (double)(A * sin(w * x + m_offset)) + k;// waveY隨著x的值改變而改變,從而得到正弦曲線
? ? ? ? ? wave.lineTo(x, waveY); ? //從上一個繪制點畫一條線到(x,waveY);
? ? ?}
? ? ?wave.lineTo(width, height); //右下角,坐標(biāo)(width, height),移動到右下角結(jié)束點,整體形成一個閉合路徑
? ? ?painter.setBrush(Qt::green); //填充綠色
? ? ?painter.drawPath(wave); ? ? ?//繪制出圖形
}
效果如圖三所示 ?
? ? ? ? ? ? ? ? ? ? ? ?
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖三:正弦曲線(水波) ?
四、畫動態(tài)正弦曲線(水波效果)
相對于靜態(tài)態(tài)正弦曲線,動態(tài)正弦曲線產(chǎn)生水波效果主要依靠,初相位的改變與定時器的刷新?;谏厦娴拇a只需修改“double m_offset = 6;”為“double m_offset += 6”; //初相位改變,增加timerEvent// 定時器事件,定時器的刷新;初相位每次加6,每次曲線的起始點不一樣,加上定時器的刷新,從而產(chǎn)生動態(tài)的效果。
修改上述的triangle.h文件 為如下代碼
?
#ifndef TRIANGLE_H
#define TRIANGLE_H
?
#include <QWidget>
#include <QPainter>
#include <QtMath>
#include <QDebug>
?
class Triangle : public QWidget
{
? ? Q_OBJECT
public:
? ? explicit Triangle (QWidget *parent = 0);
?
protected:
? ? void paintEvent(QPaintEvent *event);
? ? void timerEvent(QTimerEvent *event);
private:
? ? double m_offset;
};
?
#endif // TRIANGLE_H
修改上述的triangle.cpp文件 為如下代碼
#include "triangle.h"
Triangle::Triangle(QWidget *parent) : QWidget(parent)
{ ??
? ? ?this->startTimer(80);
}
?
?
void Triangle::paintEvent(QPaintEvent *event)
{
? ? ?Q_UNUSED(event);
?
? ? ?QPainter painter(this); ?//QWidget為繪圖設(shè)備,創(chuàng)建一個畫刷對象,主要用到設(shè)置顏色和填充模式,brush,setBrush
? ? ?int width=this->width(); ?//獲取QWidget 窗口的寬度
? ? ?int height=this->height(); //獲取QWidget 窗口的高度
? ? ?//正弦曲線公式 y = A * sin(ωx + φ) + k
? ? ?double w = M_PI/100; ?//w為角速度 ,可以理解為波浪的密度,越大密度越大
? ? ?double A = 20; ? ?// ?A表示振幅,可以理解為水波的高度,越大高度越高
? ? ?double k = 20; ? ?// ?k表示y軸偏移
?
?
? ? ?QPainterPath wave; //波浪區(qū)域
? ? ?wave.moveTo(0, height);//第一點坐標(biāo)為(0,height);
? ? ?m_offset += 6; //初相位每次加6,每次曲線的起始點不一樣,加上定時器的刷新,從而產(chǎn)生動態(tài)的效果
? ? ?for(int x = 0; x <= width; x+=1) ?//x從0~w的值而改變,從而得到正弦曲線
? ? ?{
? ? ? ? ? double waveY = (double)(A * sin(w * x + m_offset)) + k;// waveY隨著x的值改變而改變,從而得到正弦曲線
? ? ? ? ? wave.lineTo(x, waveY); ? //從上一個繪制點畫一條線到(x,waveY);
? ? ?}
? ? ?wave.lineTo(width, height); //右下角,坐標(biāo)(width, height),移動到右下角結(jié)束點,整體形成一個閉合路徑
? ? ?painter.setBrush(Qt::green); //填充綠色
? ? ?painter.drawPath(wave); ? ? ?//繪制出圖形
}
void Triangle::timerEvent(QTimerEvent *event)
{
? ? Q_UNUSED(event);
? ? this->update();
}
效果如圖四所示?
?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖四:動態(tài)正弦曲線(水波效果)
?
總結(jié)
以上是生活随笔為你收集整理的QT-QPainter绘制曲线等基本图形的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 哈哈哈,只有程序员才懂的黑色幽默 ...
- 下一篇: Docker 方式安装 Nexus 私服