Qt图形与图片

来源:互联网 发布:抢购手机有什么软件 编辑:程序博客网 时间:2024/04/29 10:31
6.1.1 区别概述
     Qt提供了很多关于获取窗体位置及显示区域大小的函数,如x( )y( )pos( )rect( )size( )geometry( )等,统称为“位置相关函数”或“位置函数”。
6.2.1  绘图框架设计
  (1) 利用QPainter绘制图形,基本图形的draw函数


2)利用QPainterPath绘制简单图形。
     利用QPainterPath绘制简单图形,QPainterPath类为QPainter类提供了一个存储容器,里面包含了所要绘制的内容的集合及绘制的顺序,如长方形、多边形、曲线等各
种任意图形。 cubicTo()函数绘制的是贝赛尔曲线


     利用QPainterPath类可以实现QPainter类的draw()函数能够实现的所有图形。例如,对于QPainter::drawRect()函数,除了可用上面介绍的QPainterPath::addRect()的方式实现,还可以用如下方式实现:
     QPainterPathpath;
     path.moveTo(0,0);
     path.lineTo(200,0);
     path.lineTo(200,100);
     path.lineTo(0,100);
     path.lineTo(0,0);
其中,
     lshapeComboBox->addItem(tr("Line"),PaintArea::Line)QComboBoxaddItem()函数可以仅插入文本,也可同时插入与文本相对应的具体数据,
通常为枚举型数据,便于后面操作时确定选择的是哪个数据。
     lpenStyleComboBox->addItem(tr("SolidLine"),static_cast<int>(Qt::SolidLine))选用不同的参数,对应画笔的不同风格。



     l penCapComboBox->addItem(tr("SquareCap"),Qt::SquareCap)选用不同的参数,对应画笔顶帽的不同风格



     l penJoinComboBox->addItem(tr("BevelJoin"),Qt::BevelJoin)选用不同的参数,对应画笔连接点的不同风格



     l fillRuleComboBox->addItem(tr("Odd Even"),Qt::OddEvenFill)QtQPainterPath类提供了两种填充规则,分别是Qt::OddEvenFillQt::WindingFill



     其中,Qt::OddEvenFill填充规则判断的依据是从图形中某一点画一条水平线到图形外,若这条水平线与图形边线的交点数目为奇数,则说明此点位于图形的内部;
若交点数目为偶数,则此点位于图形的外部




     而Qt::WindingFill填充规则的判断依据则是从图形中某一点画一条水平线到图形外,每个交点外边线的方向可能向上,也可能向下,将这些交点数累加,方向相反
的相互抵消,若最后结果不为0则说明此点在图形内,若最后结果为0则说明在图形外



      l spreadComboBox->addItem(tr("PadSpread"),QGradient::PadSpread)铺展效果有三种,分别为QGradient::PadSpreadQGradient::RepeatSpreadQGradient::ReflectSpread。其中,PadSpread是默认的铺展效果,也是最常见的铺展效果,没有被渐变覆盖的区域
填充单一的起始颜色或终止颜色;RepeatSpread效果与ReflectSpread效果只对线性渐变和圆形渐变起作用



     l brushStyleComboBox->addItem(tr("SolidPattern"),static_cast<int>(Qt::SolidPattern))选用不同的参数,对应画刷的不同风格



项目运行效果




paintarea.h

#ifndef PAINTAREA_H
#define PAINTAREA_H
#include <QWidget>
#include <QPen>
#include <QBrush>
class PaintArea : public QWidget
{
    Q_OBJECT
public:
    explicit PaintArea(QWidget *parent = 0);
    enum Shape{Line, Rectangle, RoundRect, Ellipse, Polygon,
              Polyline, Points, Arc, Path, Text, Pixmap};
    void setShape(Shape);   //设置形状
    void setPen(QPen);      //设置画笔
    void setBrush(QBrush);  //设置画刷
    void setFillRule(Qt::FillRule); //设置填充模式
    void paintEvent (QPaintEvent *);  //设置重画模式
signals:
public slots:
private:
    Shape shape;
    QPen pen;
    QBrush brush;
    Qt::FillRule fillRule;
};
#endif // PAINTAREA_H


paintarea.cpp


#include "paintarea.h"
#include <QPainter>
/*
 * 设置图形显示区域的背景色及最小显示尺寸
*/
PaintArea::PaintArea(QWidget *parent) : QWidget(parent)
{
    setPalette (QPalette(Qt::white));
    setAutoFillBackground (true);
    setMinimumSize (400, 400);
}
void PaintArea::setShape (Shape s)
{
    shape = s;
    update ();
}
void PaintArea::setPen (QPen p)
{
    pen = p;
    update ();
}
void PaintArea::setBrush (QBrush b)
{
    brush = b;
    update();
}
void PaintArea::setFillRule (Qt::FillRule rule)
{
    fillRule = rule;
    update ();
}
/*
 * 重新绘制窗体
*/
void PaintArea::paintEvent (QPaintEvent *)
{
    QPainter p(this);
    p.setPen (pen);
    p.setBrush (brush);
    QRect rect(50, 100, 300, 200);  //设定一个长方形区域
    static const QPoint points[4] = //创建一个QPoint的数组,包含四个点,为画多边形,多边线及点做准备
    {
        QPoint(150, 100),
        QPoint(300, 150),
        QPoint(350, 250),
        QPoint(100, 300)
    };
    int startAngle = 30 * 16;           //设置弧线的起始角度
    int spanAngle = 120 * 16;           //设置弧线的结束角度
    QPainterPath path;                  //新建一个QPainterPath对象为画路径做准备
    path.addRect (150, 150, 100, 100);  //x, y, w, h
    path.moveTo (100, 100);             //将坐标移动到(100 100)位置
    //绘制贝塞尔曲线
    path.cubicTo (300, 100, 200, 200, 300, 300);
    path.cubicTo (100, 300, 200, 200, 100, 100);
    path.setFillRule (fillRule);        //调用填充模式函数
    switch(shape)
    {
    case Line:      //直线
        p.drawLine (rect.topLeft (), rect.bottomRight ()); break;
    case Rectangle: //长方形
        p.drawRect (rect); break;
    case RoundRect: //圆角长方形
        p.drawRoundRect (rect); break;
    case Ellipse:   //椭圆形
        p.drawEllipse (rect); break;
    case Polygon:   //多边形
        p.drawPolygon (points, 4); break;
    case Polyline:  //点
        p.drawPoints (points, 4); break;
    case Arc:       //弧
        p.drawArc (rect, startAngle, spanAngle); break;
    case Path:      //路径
        p.drawPath (path);  break;
    case Text:      //文字
        p.drawText (rect, Qt::AlignCenter, tr("Hello Qt word!")); break;
    case Pixmap:
        p.drawPixmap (150, 150, QPixmap("butterfly.png")); break;
    default:
        break;
    }
}

mainwidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include <QLabel>
#include <QComboBox>
#include <QSpinBox>
#include <QPushButton>
#include <QGridLayout>
#include <QGradient>
#include "paintarea.h"
class MainWidget : public QWidget
{
    Q_OBJECT
public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget();
private:
    PaintArea *paintArea;
    QLabel *shapeLabel;         //形状标签
    QComboBox *shapeComboBox;   //形状下拉框
    QLabel *penColorLabel;      //画笔颜色标签
    QFrame *penColorFrame;      //画笔颜色画板
    QPushButton *penColorBtn;   //画笔颜色按钮
    QLabel *penWidthLabel;      //画笔宽度标签
    QSpinBox *penWidthSpinBox;  //画笔宽度数字显示框
    QLabel *penStyleLabel;      //画板风格标签
    QComboBox *penStyleComboBox;//画笔风格下拉框
    QLabel *penCapLabel;        //画笔顶帽标签
    QComboBox *penCapComboBox;  //画笔顶帽下拉框
    QLabel  *penJoinLabel;      //画笔连接点标签
    QComboBox *penJoinComboBox; //画笔连接点下拉框
    QLabel *fillRuleLabel;      //填充模式标签
    QComboBox *fillRuleComboBox;//填充模式下拉框
    QLabel *spreadLabel;        //铺展效果标签
    QComboBox *spreadComboBox;  //铺展效果下拉框
    QGradient::Spread spread;   //
    QLabel *brushColorLabel;    //笔刷颜色标签
    QComboBox *brushColorComboBox;  //笔刷颜色下拉框
    QFrame *brushColorFrame;        //笔刷颜色风格
    QPushButton *brushColorBtn; //笔刷颜色按钮
    QLabel *brushStyleLabel;    //笔刷风格标签
    QComboBox *brushStyleComboBox;  //笔刷风格下拉框
    QGridLayout *rightLayout;   //右侧布局指针
protected slots:
    void showshape(int);        //显示图形
    void showpencolor();        //显示画笔颜色
    void showpenwidth(int);     //显示画笔宽度
    void showpenstyle(int);     //显示画笔风格
    void showpencap(int);       //显示画笔顶帽
    void showpenjoin(int);      //显示画笔连接点
    void showfillrule();        //显示填充颜色
    void showspreadstyle();     //显示铺展效果
    void showbrushcolor();      //显示画刷颜色
    void showbrushstyle(int);   //显示画刷风格
};
#endif // MAINWIDGET_H


mainwidget.cpp

#include "mainwidget.h"
#include <QColorDialog>
MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    paintArea = new PaintArea;
    shapeLabel = new QLabel(tr("形状:"));
    shapeComboBox = new QComboBox;
    shapeComboBox->addItem (tr("Line"), PaintArea::Line);
    shapeComboBox->addItem (tr("Rectangle"), PaintArea::Rectangle);
    shapeComboBox->addItem (tr("RoundedRect"), PaintArea::RoundRect);
    shapeComboBox->addItem (tr("Ellipse"), PaintArea::Ellipse);
    shapeComboBox->addItem (tr("Polygon"), PaintArea::Polygon);
    shapeComboBox->addItem (tr("Polyline"), PaintArea::Polyline);
    shapeComboBox->addItem (tr("Points"), PaintArea::Points);
    shapeComboBox->addItem (tr("Arc"), PaintArea::Arc);
    shapeComboBox->addItem (tr("Path"), PaintArea::Path);
    shapeComboBox->addItem (tr("Text"), PaintArea::Text);
    shapeComboBox->addItem (tr("Pixmap"), PaintArea::Pixmap);
    connect (shapeComboBox, SIGNAL(activated(int)), this, SLOT(showshape(int)));
    //设置画笔颜色
    penColorLabel = new QLabel(tr("画笔颜色:"));
    penColorFrame = new QFrame;
    penColorFrame->setFrameStyle (QFrame::Panel | QFrame::Sunken);
    penColorFrame->setAutoFillBackground (true);            //设置自动填充背景色
    penColorFrame->setPalette (QPalette(Qt::blue));         //画板初始颜色蓝色
    penColorBtn = new QPushButton(tr("更改"));
    connect (penColorBtn, SIGNAL(clicked(bool)), this, SLOT(showpencolor()));
    //设置画笔宽度
    penWidthLabel = new QLabel(tr("画笔宽度:"));
    penWidthSpinBox = new QSpinBox;
    penWidthSpinBox->setRange (0, 20);
    connect (penWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(showpenwidth(int)));
    //设置画笔风格
    penStyleLabel = new QLabel(tr("画笔风格:"));
    penStyleComboBox = new QComboBox;
    penStyleComboBox->addItem(tr("SolidLine"),static_cast<int>(Qt::SolidLine));
    penStyleComboBox->addItem(tr("DashLine"),static_cast<int>(Qt::DashLine));
    penStyleComboBox->addItem(tr("DotLine"),static_cast<int>(Qt::DotLine));
    penStyleComboBox->addItem(tr("DashDotLine"),static_cast<int>(Qt::DashDotLine));
    penStyleComboBox->addItem(tr("DashDotDotLine"),static_cast<int>(Qt::DashDotDotLine));
    penStyleComboBox->addItem(tr("CustomDashLine"),static_cast<int>(Qt::CustomDashLine));
    connect(penStyleComboBox,SIGNAL(activated(int)),this,SLOT (showpenstyle(int)));
    //设置画笔顶帽
    penCapLabel = new QLabel(tr("画笔顶帽:"));
    penCapComboBox = new QComboBox;
    penCapComboBox->addItem (tr("SquareCap"), Qt::SquareCap);
    penCapComboBox->addItem (tr("FlatCap"), Qt::FlatCap);
    penCapComboBox->addItem (tr("RoundCap"), Qt::RoundCap);
    connect (penCapComboBox, SIGNAL(activated(int)), this, SLOT(showpencap(int)));
    //设置画笔连接点
    penJoinLabel  = new QLabel(tr("画笔连接点:"));
    penJoinComboBox = new QComboBox;
    penJoinComboBox->addItem (tr("BevelJoin"), Qt::BevelJoin);
    penJoinComboBox->addItem (tr("MiterJoin"), Qt::MiterJoin);
    penJoinComboBox->addItem (tr("RoundJoin"), Qt::RoundJoin);
    connect(penJoinComboBox, SIGNAL(activated(int)), this, SLOT(showpenjoin(int)));
    //设置填充模式
    fillRuleLabel = new QLabel(tr("填充模式:"));
    fillRuleComboBox = new QComboBox;
    fillRuleComboBox->addItem (tr("Odd Even"), Qt::OddEvenFill);
    fillRuleComboBox->addItem (tr("Winding"), Qt::WindingFill);
    connect (fillRuleComboBox, SIGNAL(activated(int)), this, SLOT(showfillrule()));
    //设置铺展效果
    spreadLabel = new QLabel(tr("铺展效果:"));
    spreadComboBox = new QComboBox;
    spreadComboBox->addItem (tr("PadSpread"), QGradient::PadSpread);
    spreadComboBox->addItem (tr("RepeatSpread"), QGradient::RepeatSpread);
    spreadComboBox->addItem(tr("ReflectSpread"),QGradient:: ReflectSpread);
    connect(spreadComboBox,SIGNAL(activated(int)),this,SLOT (showspreadstyle()));
    //设置画刷颜色
    brushColorLabel = new QLabel(tr("画刷颜色:"));        //画刷颜色选择控件
    brushColorFrame = new QFrame;
    brushColorFrame->setFrameStyle(QFrame::Panel|QFrame::Sunken);
    brushColorFrame->setAutoFillBackground(true);
    brushColorFrame->setPalette(QPalette(Qt::green));
    brushColorBtn =new QPushButton(tr("更改"));
    connect(brushColorBtn,SIGNAL(clicked()),this,SLOT (showbrushcolor()));
    //设置画刷风格
    brushStyleLabel =new QLabel(tr("画刷风格:"));      //画刷风格选择下拉列表框
    brushStyleComboBox =new QComboBox;
    brushStyleComboBox->addItem(tr("SolidPattern"),static_cast<int>(Qt::SolidPattern));
    brushStyleComboBox->addItem(tr("Dense1Pattern"),static_cast<int>(Qt::Dense1Pattern));
    brushStyleComboBox->addItem(tr("Dense2Pattern"),static_cast<int>(Qt::Dense2Pattern));
    brushStyleComboBox->addItem(tr("Dense3Pattern"),static_cast<int>(Qt::Dense3Pattern));
    brushStyleComboBox->addItem(tr("Dense4Pattern"),static_cast<int>(Qt::Dense4Pattern));
    brushStyleComboBox->addItem(tr("Dense5Pattern"),static_cast<int>(Qt::Dense5Pattern));
    brushStyleComboBox->addItem(tr("Dense6Pattern"),static_cast<int>(Qt::Dense6Pattern));
    brushStyleComboBox->addItem(tr("Dense7Pattern"),static_cast<int>(Qt::Dense7Pattern));
    brushStyleComboBox->addItem(tr("HorPattern"),static_cast<int>(Qt::HorPattern));
    brushStyleComboBox->addItem(tr("VerPattern"),static_cast<int>(Qt::VerPattern));
    brushStyleComboBox->addItem(tr("CrossPattern"),static_cast<int>(Qt::CrossPattern));
    brushStyleComboBox->addItem(tr("BDiagPattern"),static_cast<int>(Qt::BDiagPattern));
    brushStyleComboBox->addItem(tr("FDiagPattern"),static_cast<int>(Qt::FDiagPattern));
    brushStyleComboBox->addItem(tr("DiagCrossPattern"),static_cast<int>(Qt:: DiagCrossPattern));
    brushStyleComboBox->addItem(tr("LinearGradientPattern"),static_cast<int>(Qt:: LinearGradientPattern));
    brushStyleComboBox->addItem(tr("ConicalGradientPattern"),static_cast<int>(Qt:: ConicalGradientPattern));
    brushStyleComboBox->addItem(tr("RadialGradientPattern"),static_cast<int>(Qt:: RadialGradientPattern));
    brushStyleComboBox->addItem(tr("TexturePattern"),static_cast<int>(Qt::TexturePattern));
    connect(brushStyleComboBox,SIGNAL(activated(int)),this,SLOT (showbrushstyle(int)));
    rightLayout = new QGridLayout;  //控制面板布局
    rightLayout->addWidget(shapeLabel,0,0);
    rightLayout->addWidget(shapeComboBox,0,1);
    rightLayout->addWidget(penColorLabel,1,0);
    rightLayout->addWidget(penColorFrame,1,1);
    rightLayout->addWidget(penColorBtn,1,2);
    rightLayout->addWidget(penWidthLabel,2,0);
    rightLayout->addWidget(penWidthSpinBox,2,1);
    rightLayout->addWidget(penStyleLabel,3,0);
    rightLayout->addWidget(penStyleComboBox,3,1);
    rightLayout->addWidget(penCapLabel,4,0);
    rightLayout->addWidget(penCapComboBox,4,1);
    rightLayout->addWidget(penJoinLabel,5,0);
    rightLayout->addWidget(penJoinComboBox,5,1);
    rightLayout->addWidget(fillRuleLabel,6,0);
    rightLayout->addWidget(fillRuleComboBox,6,1);
    rightLayout->addWidget(spreadLabel,7,0);
    rightLayout->addWidget(spreadComboBox,7,1);
    rightLayout->addWidget(brushColorLabel,8,0);
    rightLayout->addWidget(brushColorFrame,8,1);
    rightLayout->addWidget(brushColorBtn,8,2);
    rightLayout->addWidget(brushStyleLabel,9,0);
    rightLayout->addWidget(brushStyleComboBox,9,1);
    QHBoxLayout *mainLayout = new QHBoxLayout(this);    //整体布局
    mainLayout->addWidget (paintArea);
    mainLayout->addLayout (rightLayout);
    mainLayout->setStretchFactor (paintArea, 1);
    mainLayout->setStretchFactor (rightLayout, 0);
    showshape (shapeComboBox->currentIndex ());         //显示默认图形
}
MainWidget::~MainWidget()
{
}
void MainWidget::showshape (int value)
{
    PaintArea::Shape shape = PaintArea::Shape(shapeComboBox->itemData (value, Qt::UserRole).toInt ());
    paintArea->setShape (shape);
}
void MainWidget::showpencolor ()
{
    QColor color = QColorDialog::getColor(static_cast<int>(Qt::blue));
    penColorFrame->setPalette(QPalette(color));
    int value = penWidthSpinBox->value();
    Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(),Qt::UserRole).toInt());
    Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(),Qt::UserRole).toInt());
    Qt::PenJoinStyle join=Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(),Qt::UserRole).toInt());
    paintArea->setPen(QPen(color,value,style,cap,join));
}
void MainWidget::showpenwidth (int value)
{
    QColor color = penColorFrame->palette ().color (QPalette::Window);
    Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(),Qt::UserRole).toInt());
    Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(),Qt::UserRole).toInt());
    Qt::PenJoinStyle join=Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(),Qt::UserRole).toInt());
    paintArea->setPen(QPen(color,value,style,cap,join));
}
void MainWidget::showpenstyle (int stylevalue)
{
    QColor color = penColorFrame->palette ().color (QPalette::Window);
    int value = penWidthSpinBox->value ();
    Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData (stylevalue, Qt::UserRole).toInt ());
    Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData (penCapComboBox->currentIndex (), Qt::UserRole).toInt ());
    Qt::PenJoinStyle join = Qt::PenJoinStyle(penJoinComboBox->itemData (penJoinComboBox->currentIndex (), Qt::UserRole).toInt ());
    paintArea->setPen (QPen(color, value, style, cap, join));
}
void MainWidget::showpencap (int capvalue)
{
    QColor color = penColorFrame->palette().color(QPalette::Window);
    int value = penWidthSpinBox->value();
    Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(),Qt::UserRole).toInt());
    Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(capvalue,Qt::UserRole).toInt());
    Qt::PenJoinStyle join=Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(),Qt::UserRole).toInt());
    paintArea->setPen(QPen(color,value,style,cap,join));
}
void MainWidget::showpenjoin (int joinvalue)
{
    QColor color = penColorFrame->palette().color(QPalette::Window);
    int value = penWidthSpinBox->value();
    Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(),Qt::UserRole).toInt());
    Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(),Qt::UserRole).toInt());
    Qt::PenJoinStyle join=Qt::PenJoinStyle(penJoinComboBox->itemData(joinvalue,Qt::UserRole).toInt());
    paintArea->setPen(QPen(color,value,style,cap,join));
}
void MainWidget::showfillrule ()
{
    Qt::FillRule rule = Qt::FillRule(fillRuleComboBox->itemData (fillRuleComboBox->currentIndex (), Qt::UserRole).toInt ());
    paintArea->setFillRule (rule);
}
void MainWidget::showspreadstyle ()
{
    spread = QGradient::Spread(spreadComboBox->itemData (spreadComboBox->currentIndex (), Qt::UserRole).toInt ());
}
void MainWidget::showbrushcolor ()
{
    QColor color = QColorDialog::getColor (static_cast<int>(Qt::blue));
    brushColorFrame->setPalette (QPalette(color));
    showbrushstyle (brushStyleComboBox->currentIndex ());
}
void MainWidget::showbrushstyle (int value)
{
    QColor color = brushColorFrame->palette().color(QPalette::Window);
    Qt::BrushStyle style = Qt::BrushStyle(brushStyleComboBox->itemData(value,Qt::UserRole).toInt());
    //线性渐变
    if(style == Qt::LinearGradientPattern)
    {
        QLinearGradient linearGradient(0,0,400,400);
        linearGradient.setColorAt(0.0,Qt::white);
        linearGradient.setColorAt(0.2,color);
        linearGradient.setColorAt(1.0,Qt::black);
        linearGradient.setSpread(spread);
        paintArea->setBrush(linearGradient);
    }//圆形渐变
    else if(style == Qt::RadialGradientPattern)
    {
        QRadialGradient radialGradient(200,200,150,150,100);
        radialGradient.setColorAt(0.0,Qt::white);
        radialGradient.setColorAt(0.2,color);
        radialGradient.setColorAt(1.0,Qt::black);
        radialGradient.setSpread(spread);
        paintArea->setBrush(radialGradient);
    }//锥形渐变
    else if(style == Qt::ConicalGradientPattern)
    {
        QConicalGradient conicalGradient(200,200,30);
        conicalGradient.setColorAt(0.0,Qt::white);
        conicalGradient.setColorAt(0.2,color);
        conicalGradient.setColorAt(1.0,Qt::black);
        paintArea->setBrush(conicalGradient);
    }//纹理渐变
    else if(style == Qt::TexturePattern)
    {
        paintArea->setBrush(QBrush(QPixmap("butterfly.png")));
    }
    else
    {
        paintArea->setBrush(QBrush(color,style));
    }
}


main.cpp

#include "mainwidget.h"
#include <QApplication>
#include <QFont>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QFont f("ZYSong18030", 12);
    a.setFont (f);
    MainWidget w;
    w.show();
    return a.exec();
}

6.3 Qt5的双缓存机制
     
     QMainWindow对象作为主窗口,QToolBar对象作为工具栏,QWidget对象作为主窗口的中央窗体centralWidget,也就是绘图区



运行效果



drawwidget.h

#ifndef DRAWWIDGET_H
#define DRAWWIDGET_H
#include <QWidget>
#include <QPixmap>
#include <QPoint>
#include <QPainter>
#include <QPalette>
class DrawWidget : public QWidget
{
    Q_OBJECT
public:
    explicit DrawWidget(QWidget *parent = 0);
    void mousePressEvent (QMouseEvent *);
    void mouseMoveEvent (QMouseEvent *);
    void paintEvent (QPaintEvent *);
    void resizeEvent (QResizeEvent *);
signals:
public slots:
    void setstyle(int);
    void setwidth(int);
    void setcolor(QColor);
    void clear();
private :
    QPixmap *pix;       //定义一个画板指针
    QPoint startpos;
    QPoint endpos;
    int style;
    int weight;
    QColor color;
};
#endif // DRAWWIDGET_H


drawwidget.cpp

#include "drawwidget.h"
#include <QtGui>
#include <QPen>
DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent)
{
    setAutoFillBackground (true);   //设置窗体背景色
    setPalette (QPalette(Qt::white));
    pix = new QPixmap(size());      //此QPixmap对象用来准备随时接受绘制的内容
    pix->fill (Qt::white);          //填充背景色为白色
    setMinimumSize (600, 400);      //设置绘制区窗体的最小尺寸
}
/*
 * 接收主窗体传来的线性风格参数
*/
void DrawWidget::setstyle (int s)
{
    style = s;
}
/*
 * 接收主窗体传来的线宽数值
*/
void DrawWidget::setwidth (int w)
{
    weight = w;
}
/*
 * 接收主窗体传来的画笔颜色值
*/
void DrawWidget::setcolor (QColor c)
{
    color = c;
}
void DrawWidget::mousePressEvent (QMouseEvent *e)
{
    startpos = e->pos();
}
/*
 * 鼠标一旦移动就更新画笔的风格、宽度、颜色
 * 开始绘制、首先获取画笔、设置画笔、绘画
 * 绘制完后跟新startpos位置
 *
*/
void DrawWidget::mouseMoveEvent (QMouseEvent *e)
{
    QPainter *painter = new QPainter;
    QPen pen;
    pen.setStyle ((Qt::PenStyle)style);
    pen.setWidth (weight);
    pen.setColor (color);
    painter->begin (pix);
    painter->setPen (pen);
    painter->drawLine (startpos, e->pos ());
    painter->end ();
    startpos = e->pos ();   //更新鼠标的位置
    update ();
}
/*
 * 重画函数paintEvent()完成绘制窗体的更新工作,只需调用drawPixmap()
 * 函数将用于接收图形绘制的QPixmap对象绘制在绘制区窗体控件上即可。
*/
void DrawWidget::paintEvent (QPaintEvent *)
{
    QPainter painter(this);
    painter.drawPixmap (QPoint(0, 0), *pix);
}
/*
 * 当窗体的大小发生变化时,效果看起来虽然像是绘制区大小改变了,但实际能够进行绘制的区域仍然没有改变
 * 因为绘图的大小并没有改变,还是原来绘制窗口的大小,所以在窗体尺寸变化时应及时调整用于绘制的QPixmap
 * 对象的尺寸大小
 * 首先判断改变窗口的大小是否大于原窗体的长和宽
 * 创建一个新的QPixmap对象,填充新QPixmap对象的newPix的颜色为白色背景色
 * 新创建的p画笔指向newPix画布里面
 * 在newPix中绘制原pix中的内容
 * 将newPix赋值给pix作为新的绘制图形接收对象
*/
void DrawWidget::resizeEvent (QResizeEvent *event)
{
    if(height () > pix->height () || width() > pix->width ())
    {
        QPixmap *newPix = new QPixmap(size());
        newPix->fill (Qt::white);
        QPainter p(newPix);
        p.drawPixmap (QPoint(0, 0), *pix);
        pix = newPix;
    }
    QWidget::resizeEvent(event);
}
/*
 * 清除函数只需调用一个新的、干净的QPixmap对象代替pix,并调用update()重绘即可
*/
void DrawWidget::clear ()
{
    QPixmap *clearPix = new QPixmap(size());
    clearPix->fill (Qt::white);
    pix = clearPix;
    update ();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QComboBox>
#include <QSpinBox>
#include <QToolButton>
#include "drawwidget.h"
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void createToolBar();   //创建工具栏
public slots:
    void showstyle();
    void showcolor();
private:
    DrawWidget *drawWidget;
    QLabel *styleLabel;
    QComboBox *styleComboBox;
    QLabel *widthLabel;
    QSpinBox *widthSpinBox;
    QToolButton *colorBtn;
    QToolButton *clearBtn;
};
#endif // MAINWINDOW_H


mainwindow.cpp

#include "mainwindow.h"
#include <QToolBar>
#include <QColorDialog>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    drawWidget = new DrawWidget;    //新建一个drawWidget对象
    setCentralWidget (drawWidget);  //新建的drawWidget对象作为主窗口的中央窗口
    createToolBar ();               //创建一个工具栏
    setMinimumSize (600, 400);      //设置主窗体的最小尺寸
    showstyle ();       //初始化线型,设置控件中当前值作为初始值
    drawWidget->setwidth (widthSpinBox->value ());  //设置初始线宽
    drawWidget->setcolor (Qt::black);               //设置初始颜色
}
MainWindow::~MainWindow()
{
}
void MainWindow::createToolBar ()
{
    QToolBar *toolBar = addToolBar (tr("Tool"));   //为主窗口创建一个工具栏对象
    styleLabel = new QLabel(tr("线型风格"));
    styleComboBox = new QComboBox;
    styleComboBox->addItem (tr("SolidLine"), static_cast<int>(Qt::SolidLine));
    styleComboBox->addItem (tr("DashLine"), static_cast<int>(Qt::DashLine));
    styleComboBox->addItem (tr("DotLine"), static_cast<int>(Qt::DotLine));
    styleComboBox->addItem (tr("DashDotLine"), static_cast<int>(Qt::DashDotLine));
    styleComboBox->addItem (tr("DashDotDotLine"), static_cast<int>(Qt::DashDotDotLine));
    connect (styleComboBox, SIGNAL(activated(int)), this, SLOT(showstyle()));
    widthLabel = new QLabel(tr("线宽"));
    widthSpinBox = new QSpinBox;
    connect (widthSpinBox, SIGNAL(valueChanged(int)), drawWidget, SLOT(setwidth(int)));
    colorBtn = new QToolButton;
    QPixmap pixmap(20, 20);
    pixmap.fill (Qt::black);
    colorBtn->setIcon (QIcon(pixmap));
    connect (colorBtn, SIGNAL(clicked(bool)), this, SLOT(showcolor()));
    clearBtn = new QToolButton;
    clearBtn->setText (tr("清除"));
    connect (clearBtn, SIGNAL(clicked(bool)), drawWidget, SLOT(clear()));
    toolBar->addWidget (styleLabel);
    toolBar->addWidget (styleComboBox);
    toolBar->addWidget (widthLabel);
    toolBar->addWidget (widthSpinBox);
    toolBar->addWidget (colorBtn);
    toolBar->addWidget (clearBtn);
}
void MainWindow::showstyle ()
{
    drawWidget->setstyle (styleComboBox->itemData (styleComboBox->currentIndex (), Qt::UserRole).toInt ());
}
void MainWindow::showcolor ()
{
    QColor color = QColorDialog::getColor (static_cast<int>(Qt::black), this);
    
    //判断颜色是否有效
    if(color.isValid ())
    {
        drawWidget->setcolor (color);
        QPixmap p(20, 20);
        p.fill (color);
        colorBtn->setIcon (QIcon(p));
    }
}

main.cpp

#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

6.4 Qt5 SVG格式图片的显示
SVG格式的特点如下:
(1)基于XML
(2)采用文本来描述对象
(3)具有交互性和动态性
(4)完全支持DOM
SVG相对于GIF,JPEG格式的优势,SVG是一种矢量图形格式,比GIF,JPEG等栅格格式具有众多优势,如文件小,对于网络而言下载速度快;可以任意缩放而不会破坏
图像的清晰度和细节;图像中的文字独立相对于图像,文字保留可编辑和可搜寻的状态,也没有字体的限制,用户系统即使没有安装某一种字体,也可看到与制作时完
全相同的画面等。
下面通过利用QSvgWidget类和QSvgRender类实现一个SVG图片浏览器




Qt5SVG格式图片的显示由三个层次的窗体构成



在完成此功能的程序中使用与SVG相关的类,必须在程序中包含SVG相关的头文件:
#include <QtSvg>
由于Qt默认生成的Makefile中只加入了QtGuiQtCore模块的库,所以必须在工程文件“.pro”中加入一行代码:
QT +=svg

svgwidget.h

#ifndef SVGWIDGET_H
#define SVGWIDGET_H
#include <QtSvg/QtSvg>
#include <QtSvg/QSvgWidget>
#include <QtSvg/QSvgRenderer>
/*
 * SvgWidget继承QSvgWidget,完成具体的SVG图片的显示工作
*/
class SvgWidget : public QSvgWidget
{
    Q_OBJECT
public:
    SvgWidget(QWidget *parent = 0);
    void wheelEvent(QWheelEvent *); //响应鼠标的滚轮事件,是SVG图片能够通过鼠标滚轮的滚动进行缩放
private:
    QSvgRenderer *render;           //用于图片显示尺寸的确定
};
#endif // SVGWIDGET_H


svgwidget.cpp

#include "svgwidget.h"
SvgWidget::SvgWidget(QWidget *parent)
    :QSvgWidget(parent)
{
    render = renderer ();   //获得图片显示的尺寸
}
/*
 * diff的值表示每次滑轮滚动一定的值,图片大小改变的比例
 * render->defaultSize ()获取图片显示区的尺寸大小
 * e->delta()利用QWheelEvent的delta()函数获得滚动滚轮的距离值,通过此值判断滚轮的方向
 * 滚轮向前移动图片长宽增加
 * 滚轮向后移动图片长宽减小
 * 重置图片的长宽
*/
void SvgWidget::wheelEvent (QWheelEvent *e)
{
    const double diff = 0.1;
    QSize size = render->defaultSize ();
    int width = size.width ();
    int height = size.height ();
    if(e->delta () > 0)
    {
        width = int(this->width () + this->width () * diff);
        height = int(this->height () + this->height () * diff);
    }
    else
    {
        width = int(this->width () - this->width () * diff);
        height = int(this->height () - this->height () * diff);
    }
    resize(width, height);      //利用新的长、宽值对图片进行resize()操作
}

svgwindow.h

#ifndef SVGWINDOW_H
#define SVGWINDOW_H
/*
 * SvgWindow继承自QScrollArea类,实现一个带滑动条的显示区域
*/
#include <QScrollArea>
#include "svgwidget.h"
#include <QMenuBar>
class SvgWindow : public QScrollArea
{
    Q_OBJECT
public:
    SvgWindow(QWidget *parent = 0);
    void setFile(QString);
    void mousePressEvent (QMouseEvent *);   //鼠标按下函数
    void mouseMoveEvent (QMouseEvent *);    //鼠标移动函数
private:
    SvgWidget *svgWidget;
    QPoint mousePressPos;               //鼠标按下的位置
    QPoint scrollBarValueOnMousePress;  //鼠标按下是的滚动值
};
#endif // SVGWINDOW_H


svgwindow.cpp

#include "svgwindow.h"
/*
 * 设置滚动条的窗口,使SvgWidget成为SvgWindow的子窗口
*/
SvgWindow::SvgWindow(QWidget *parent)
    : QScrollArea(parent)
{
    svgWidget = new SvgWidget;
    setWidget (svgWidget);
}
/*
 * 将SVG文件加载到svgWidget中进行显示
 * 使svgWidget窗体按SVG图片的默认尺寸进行显示
*/
void SvgWindow::setFile (QString fileName)
{
    svgWidget->load (fileName);
    QSvgRenderer *render = svgWidget->renderer ();
    svgWidget->resize (render->defaultSize ());
}
/*
 * 当鼠标按下时mousePresspos和scrollBarValuesOnMousePress进行初始化
 * QScrollArea类的HorizontalScrollBar()和verticalScrollBar()函数
 * 可以分别获取svgWindow的水平滑动条和垂直滑动条
*/
void SvgWindow::mousePressEvent (QMouseEvent *event)
{
    mousePressPos = event->pos ();
    scrollBarValueOnMousePress.rx () = horizontalScrollBar ()->value ();
    scrollBarValueOnMousePress.ry () = verticalScrollBar ()->value ();
    event->accept ();
}
/*
 * 当鼠标键按下并拖曳鼠标时触发mouseMoveEvent()函数,通过滑动条的位置设置实现图片拖曳的效果
 * 对水平滑动条的新位置进行设置
 * 对垂直滑动条的新位置进行设置
*/
void SvgWindow::mouseMoveEvent (QMouseEvent *event)
{
    horizontalScrollBar()->setValue(scrollBarValueOnMousePress.x() - event->pos().x() + mousePressPos.x());
    verticalScrollBar()->setValue(scrollBarValueOnMousePress.y() - event->pos().y() + mousePressPos.y());
    horizontalScrollBar()->update();
    verticalScrollBar()->update();
    event->accept();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
/*
 * MainWindow继承自QMainWindow类,实现主窗口区域
*/
#include <QMainWindow>
#include "svgwindow.h"
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void createMenu();
public slots:
    void slotOpenFile();
private:
    SvgWindow *svgWindow;   //以便调用相关函数传递选择的文件名
};
#endif // MAINWINDOW_H


mainwindow.cpp

#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setWindowTitle(tr("SVG Viewer"));
    this->resize (600, 400);
    createMenu();
    svgWindow =new SvgWindow;
    setCentralWidget(svgWindow);
}
MainWindow::~MainWindow()
{
}
/*
 * 创建一个打开文件的菜单
*/
void MainWindow::createMenu()
{
    QMenu *fileMenu = menuBar()->addMenu(tr("文件"));
    QAction *openAct = new QAction(tr("打开"),this);
    connect(openAct,SIGNAL(triggered()),this,SLOT(slotOpenFile()));
    fileMenu->addAction(openAct);
}
void MainWindow::slotOpenFile()
{
    QString name = QFileDialog::getOpenFileName(this,"打开","/","svg files(*.svg)");
    svgWindow->setFile(name);
}





1 0