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
paintarea.cpp
mainwidget.h
mainwidget.cpp
main.cpp
6.3 Qt5的双缓存机制
QMainWindow对象作为主窗口,QToolBar对象作为工具栏,QWidget对象作为主窗口的中央窗体centralWidget,也就是绘图区
运行效果
drawwidget.h
drawwidget.cpp
mainwindow.h
mainwindow.cpp
main.cpp
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
svgwidget.cpp
svgwindow.h
svgwindow.cpp
}
mainwindow.h
mainwindow.cpp
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);
}
相关文章推荐
- Qt菜单\工具栏
- Qt TextEdit 使用
- QTP的退出函数
- 在ubuntu下使用Qt5.4连接mysql数据库出现错误
- Qt在线安装
- timerEvent()事件跟QTimer类之间的疑问
- 基于QML开发的二维码生成的QML插件
- QT pro文件介绍
- PyQt4(简单布局)
- 基于MQTT+WCF 实现Web 接口转即时服务
- Qt 5 常见错误汇总
- 在unity3d中接受MQTT消息协议数据C# .net,M2Mqtt
- MQTT协议笔记之头部信息
- PyQt4 学习笔记7之控件II
- 运用QRegExp 解析字符串
- 设置QTabWidget中tab页的大小
- QT5入门之30-控件
- qt移植到arm上的过程
- Qtcreator4.8+Ubuntu14.04 fcitx无法输入中文
- QT中QPainter的使用及矩形、圆形等常见图形的画法