您的位置:首页 > 编程语言 > Qt开发

Qt图形与图片

2015-11-04 13:03 866 查看
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)QComboBox的addItem()函数可以仅插入文本,也可同时插入与文本相对应的具体数据,

通常为枚举型数据,便于后面操作时确定选择的是哪个数据。

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)Qt为QPainterPath类提供了两种填充规则,分别是Qt::OddEvenFill和Qt::WindingFill



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

若交点数目为偶数,则此点位于图形的外部



而Qt::WindingFill填充规则的判断依据则是从图形中某一点画一条水平线到图形外,每个交点外边线的方向可能向上,也可能向下,将这些交点数累加,方向相反

的相互抵消,若最后结果不为0则说明此点在图形内,若最后结果为0则说明在图形外



l spreadComboBox->addItem(tr("PadSpread"),QGradient::PadSpread)铺展效果有三种,分别为QGradient::PadSpread、QGradient::RepeatSpread和QGradient::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中只加入了QtGui、QtCore模块的库,所以必须在工程文件“.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);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: