第6章 Qt 5图形与图片

一、Qt 5位置相关函数

Qt提供了很多关于获取窗体位置及显示区域大小的函数,如x()、y()和pos()、rect()、size()、geometry()等,统称为“位置相关函数”或“位置函数”。几种主要位置函数及其之间的区别如图6.1所示。

 其中,

 x()、y()和pos()函数的作用都是获得整个窗体左上角的坐标位置。

 frameGeometry()函数与geometry()函数相对应。frameGeometry()函数是获得整个窗体的左上顶点和长、宽值,而geometry()函数获得的是窗体内中央区域的左上顶点坐标及长、宽值。

 直接调用width()和height()函数获得的是中央区域的长、宽值。

 rect()、size()函数获得的结果也都是对于窗体的中央区域而言的。size()函数获得的是窗体中央区域的长、宽值。

rect()函数与geometry()函数相同,返回一个QRect对象,这两个函数获得的长、宽值是相同的,都是窗体中央区域的长、宽值,只是左上顶点的坐标值不一样。geometry()函数获得的左上顶点坐标是相对于父窗体而言的坐标,而rect()函数获得的左上顶点坐标始终为(0,0)。

1、“实例”位置函数的应用

【例】(难度一般)(CH601)设计界面,当改变对话框的大小或移动对话框时,调用各个函数所获得的信息也相应地发生变化,从变化中可得知各函数之间的区别。 具体实现步骤如下。

(1)新建Qt Widgets Application(详见1.3.1节),项目名称为“Geometry”,基类选择“QDialog”,类名命名为“Geometry”,取消“创建界面”复选框的选中状态。单击“下一步”按钮,最后单击“完成”按钮,完成该项目工程的建立。

(2)Geometry类继承自QDialog类,在头文件中声明所需的控件(主要为QLabel类)及所需要的函数。 打开“geometry.h”头文件,添加如下代码。

#ifndef GEOMETRY_H
#define GEOMETRY_H

#include <QDialog>
#include <QLabel>
#include <QGridLayout>
class Geometry : public QDialog
{
    Q_OBJECT

public:
    Geometry(QWidget *parent = 0);
    ~Geometry();
    void updateLabel();
private:
    QLabel *xLabel;
    QLabel *xValueLabel;
    QLabel *yLabel;
    QLabel *yValueLabel;
    QLabel *FrmLabel;
    QLabel *FrmValueLabel;
    QLabel *posLabel;
    QLabel *posValueLabel;
    QLabel *geoLabel;
    QLabel *geoValueLabel;
    QLabel *widthLabel;
    QLabel *widthValueLabel;
    QLabel *heightLabel;
    QLabel *heightValueLabel;
    QLabel *rectLabel;
    QLabel *rectValueLabel;
    QLabel *sizeLabel;
    QLabel *sizeValueLabel;
    QGridLayout *mainLayout;
protected:
    void moveEvent(QMoveEvent *);//重载移动事件,响应对话框的移动事件,使得窗体被移动时能够同步更新个函数的显示结果
    void resizeEvent(QResizeEvent *);//重载窗口尺寸调整事件,响应对话框的大小调整事件,使得窗体大小改变时,能够同步更新各函数的显示结果
};

#endif // GEOMETRY_H

(3)在构造函数中完成控件的创建及初始化工作,打开“geometry.cpp”文件,添加如下代码。 updateLabel()函数完成获得各位置函数的信息并显示功能,具体代码。

#include "geometry.h"

Geometry::Geometry(QWidget *parent)
    : QDialog(parent)
{
    setWindowTitle(tr("Geometry"));
    xLabel =new QLabel(tr("x():"));
    xValueLabel =new QLabel;
    yLabel =new QLabel(tr("y():"));
    yValueLabel =new QLabel;
    FrmLabel =new QLabel(tr("Frame:"));
    FrmValueLabel =new QLabel;
    posLabel =new QLabel(tr("pos():"));
    posValueLabel =new QLabel;
    geoLabel =new QLabel(tr("geometry():"));
    geoValueLabel =new QLabel;
    widthLabel =new QLabel(tr("width():"));
    widthValueLabel =new QLabel;
    heightLabel =new QLabel(tr("height():"));
    heightValueLabel =new QLabel;
    rectLabel =new QLabel(tr("rect():"));
    rectValueLabel =new QLabel;
    sizeLabel =new QLabel(tr("size():"));
    sizeValueLabel =new QLabel;
    mainLayout =new QGridLayout(this);
    mainLayout->addWidget(xLabel,0,0);
    mainLayout->addWidget(xValueLabel,0,1);
    mainLayout->addWidget(yLabel,1,0);
    mainLayout->addWidget(yValueLabel,1,1);
    mainLayout->addWidget(posLabel,2,0);
    mainLayout->addWidget(posValueLabel,2,1);
    mainLayout->addWidget(FrmLabel,3,0);
    mainLayout->addWidget(FrmValueLabel,3,1);
    mainLayout->addWidget(geoLabel,4,0);
    mainLayout->addWidget(geoValueLabel,4,1);
    mainLayout->addWidget(widthLabel,5,0);
    mainLayout->addWidget(widthValueLabel,5,1);
    mainLayout->addWidget(heightLabel,6,0);
    mainLayout->addWidget(heightValueLabel,6,1);
    mainLayout->addWidget(rectLabel,7,0);
    mainLayout->addWidget(rectValueLabel,7,1);
    mainLayout->addWidget(sizeLabel,8,0);
    mainLayout->addWidget(sizeValueLabel,8,1);
    updateLabel();
}

void Geometry::updateLabel()
{
    QString xStr;                      	//获得x()函数的结果并显示
    xValueLabel->setText(xStr.setNum(x()));
    QString yStr;                      	//获得y()函数的结果并显示
    yValueLabel->setText(yStr.setNum(y()));
    QString frameStr;                   //获得frameGeometry()函数的结果并显示
    QString tempStr1,tempStr2,tempStr3,tempStr4;
    frameStr = tempStr1.setNum(frameGeometry().x())+","+
         tempStr2.setNum(frameGeometry().y())+","+
         tempStr3.setNum(frameGeometry().width())+","+
        tempStr4.setNum(frameGeometry().height());
    FrmValueLabel->setText(frameStr);
    QString positionStr;            	//获得pos()函数的结果并显示
    QString tempStr11,tempStr12;
    positionStr =tempStr11.setNum(pos().x())+","+
            tempStr12.setNum(pos().y());
    posValueLabel->setText(positionStr);
    QString geoStr;               		//获得geometry()函数的结果并显示
    QString tempStr21,tempStr22,tempStr23,tempStr24;
    geoStr =tempStr21.setNum(geometry().x())+","+
         tempStr22.setNum(geometry().y())+","+
         tempStr23.setNum(geometry().width())+","+
         tempStr24.setNum(geometry().height());
    geoValueLabel->setText(geoStr);
    QString wStr,hStr;                  //获得width()、height()函数的结果并显示
    widthValueLabel->setText(wStr.setNum(width()));
    heightValueLabel->setText(hStr.setNum(height()));
    QString rectStr;                    //获得rect()函数的结果并显示
    QString tempStr31,tempStr32,tempStr33,tempStr34;
    rectStr =tempStr31.setNum(rect().x())+","+
          tempStr32.setNum(rect().y())+","+
          tempStr33.setNum(/*rect().width()*/width())+","+
          tempStr34.setNum(height()/*rect().height()*/);
    rectValueLabel->setText(rectStr);
    QString sizeStr;                    //获得size()函数的结果并显示
    QString tempStr41,tempStr42;
    sizeStr =tempStr41.setNum(size().width())+","+
          tempStr42.setNum(size().height());
    sizeValueLabel->setText(sizeStr);
}

void Geometry::moveEvent(QMoveEvent *)
{
    updateLabel();
}

void Geometry::resizeEvent(QResizeEvent *)
{
    updateLabel();
}

Geometry::~Geometry()
{

}

重新定义QWidget的moveEvent()函数,响应对话框的移动事件,使得窗体在被移动时能够同步更新各函数的显示结果,具体代码如下:

void Geometry::moveEvent(QMoveEvent *)
{
    updateLabel();
}

重新定义QWidget的resizeEvent()函数,响应对话框的大小调整事件,使得在窗体大小发生改变时,也能够同步更新各函数的显示结果,具体代码如下:

void Geometry::resizeEvent(QResizeEvent *)
{
    updateLabel();
}

(4)运行程序,效果如图6.2所示。

 二、Qt 5基础图形的绘制

【例】(难度中等)(CH602)设计界面,区分各种形状及画笔颜色、画笔线宽、画笔风格、画笔顶帽、画笔连接点、填充模式、铺展效果、画刷颜色、画刷风格设置等。

1、绘图框架设计

利用QPainter绘制各种图形使用的框架的实例如图6.3所示。

 此实例的具体实现包含两个部分的内容:一是用于画图的区域PaintArea类,二是主窗口MainWidget类。绘制各种图形实例的框架如图6.4所示。

具体实现步骤如下。

(1)新建Qt Widgets Application(详见1.3.1节),项目名称为“PaintEx”,基类选择“QWidget”,类名命名为“MainWidget”,取消“创建界面”复选框的选中状态。单击“下一步”按钮,最后单击“完成”按钮,完成该项目工程的建立。

(2)添加该工程的提供实现绘图区的函数所在的文件,在“PaintEx”项目名上单击鼠标右键,在弹出的快捷菜单中选择“添加新文件...”选项,在弹出的对话框中选择“C++ Class”选项。单击“Choose...”按钮,在弹出的对话框的“Base class”下拉列表框中选择基类名“QWidget”,在“Class name”文本框中输入类的名称“PaintArea”。

(3)单击“下一步”按钮,单击“完成”按钮,添加文件“paintarea.h”和文件“paintarea.cpp”。

 2、绘图区的实现

打开“paintarea.h”头文件,添加如下代码

#ifndef PAINTAREA_H
#define PAINTAREA_H

#include <QWidget>
#include <QPen>
#include <QBrush>
class PaintArea : public QWidget
{
    Q_OBJECT
public:
    enum Shape{Line,Rectangle,RoundRect,Ellipse,Polygon,Polyline,Points,Arc,Path,Text,Pixmap};
    explicit PaintArea(QWidget *parent = 0);
    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”具体实现文件,PaintArea类的构造函数用于完成初始化工作,设置图形显示区域的背景色及最小显示尺寸,具体代码如下:

#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);						//新建一个QPainter对象
    p.setPen(pen);							//设置QPainter对象的画笔
    p.setBrush(brush);						//设置QPainter对象的画刷
    QRect rect(50,100,300,200);				//设置一个左上角(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);
    path.moveTo(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.drawPolyline(points,4); 	break;
        case Points:                        //点
            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!"));break;
        case Pixmap:                         //图片
            p.drawPixmap(150,150,QPixmap("butterfly.png")); 	break;
        default: 	break;
    }
}

int startAngle=30*16、int spanAngle =120*16:

其中,参数startAngle表示起始角,为弧形的起始点与圆心之间连线与水平方向的夹角;参数spanAngle表示的是跨度角,为弧形起点、终点分别与圆心连线之间的夹角,如图6.5所示。

(1)利用QPainter绘制图形(Shape)。 Qt为开发者提供了丰富的绘制基本图形的draw()函数,如图6.6所示。

(2)利用QPainterPath绘制简单图形。

利用QPainterPath绘制简单图形,QPainterPath类为QPainter类提供了一个存储容器,里面包含了所要绘制的内容的集合及绘制的顺序,如长方形、多边形、曲线等各种任意图形。当需要绘制此预先存储在QPainterPath对象中的内容时,只需调用QPainter类的drawPath()函数即可。 QPainterPath类提供了许多函数接口,可以很方便地加入一些规则图形。例如,addRect()加入一个方形,addEllipse()函数加入一个椭圆形,addText()函数加入一个字符串,addPolygon()函数加入一个多边形等。同时,QPainterPath类还提供了addPath()函数,用于加入另一个QPainterPath对象中保存的内容。

 QPainterPath对象的当前点自动处在上一部分图形内容的结束点上,若下一部分图形的起点不在此结束点,则需调用moveTo()函数将当前点移动到下一部分图形的起点。 cubicTo()函数绘制的是贝赛尔曲线,如图6.7所示。

 

利用QPainterPath类可以实现QPainter类的draw()函数能够实现的所有图形。例如,对于QPainter::drawRect()函数,除可用上面介绍的QPainterPath::addRect()的方式实现外,还可以用如下方式实现:

QPainterPath path;
path.moveTo(0,0);
path.lineTo(200,0);
path.lineTo(200,100);
path.lineTo(0,100);
path.lineTo(0,0);

3、主窗口的实现

主窗口类MainWiget继承自QWidget类,包含完成各种图形参数选择的控制区的声明、一系列设置与画图相关参数的槽函数的声明,以及一个绘图区PaintArea对象的声明。

打开“mainwidget.h”头文件,添加如下代码。

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>
#include "paintarea.h"
#include <QLabel>
#include <QComboBox>
#include <QSpinBox>
#include <QPushButton>
#include <QGridLayout>
#include <QGradient>
class MainWidget : public QWidget
{
    Q_OBJECT

public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget();
private:
    PaintArea *paintArea;
    QLabel *shapeLabel;
    QComboBox *shapeComboBox;
    QLabel *penWidthLabel;
    QSpinBox *penWidthSpinBox;
    QLabel *penColorLabel;
    QFrame *penColorFrame;
    QPushButton *penColorBtn;
    QLabel *penStyleLabel;
    QComboBox *penStyleComboBox;
    QLabel *penCapLabel;
    QComboBox *penCapComboBox;
    QLabel *penJoinLabel;
    QComboBox *penJoinComboBox;
    QLabel *fillRuleLabel;
    QComboBox *fillRuleComboBox;
    QLabel *spreadLabel;
    QComboBox *spreadComboBox;
    QGradient::Spread spread;
    QLabel *brushStyleLabel;
    QComboBox *brushStyleComboBox;
    QLabel *brushColorLabel;
    QFrame *brushColorFrame;
    QPushButton *brushColorBtn;
    QGridLayout *rightLayout;
protected slots:
    void ShowShape(int);
    void ShowPenWidth(int);
    void ShowPenColor();
    void ShowPenStyle(int);
    void ShowPenCap(int);
    void ShowPenJoin(int);
    void ShowSpreadStyle();
    void ShowFillRule();
    void ShowBrushColor();
    void ShowBrush(int);
};

#endif // MAINWIDGET_H

MainWiget类的构造函数中创建了各参数选择控件,打开“mainwiget.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);		//QComboBox的addItem()函数可以仅插入文本,也可同时插入与文本相对应的具体数据,通常为枚举型数据,便于后面操作时确定选择的是哪个数据。
    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()),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);  //Qt为QPainterPath类提供了两种填充规则,分别是Qt::OddEvenFill和Qt::WindingFill
    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);														 //铺展效果有三种,分别为QGradient::PadSpread、QGradient::RepeatSpread和QGradient:: ReflectSpread。
    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 (ShowBrush(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());        //显示默认的图形
}

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));
    ShowBrush(brushStyleComboBox->currentIndex());
}

void MainWidget::ShowBrush(int value)
{
    //获得画刷的颜色
    QColor color = brushColorFrame->palette().color(QPalette:: Window);
    Qt::BrushStyle style = Qt::BrushStyle(brushStyleComboBox-> itemData(
        value,Qt::UserRole).toInt());					//获得所选的画刷风格,若选择的是渐变或者纹理图案,则需要进行一定的处理
    if(style == Qt::LinearGradientPattern)				//主窗口的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)			//主窗口的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)		//主窗口的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));
    }
}

MainWidget::~MainWidget()
{

}

运行结果

 三、Qt 5双缓冲机制

1、原理与设计

【例】(难度中等)(CH603)实现一个简单的绘图工具,可以选择线型、线宽、颜色等基本要素,如图6.18所示。QMainWindow对象作为主窗口,QToolBar对象作为工具栏,QWidget对象作为主窗口的中央窗体,也就是绘图区,如图6.19所示。

 具体实现步骤如下。

(1)新建Qt Widgets Application (详见1.3.1节),项目名称为“DrawWidget”,基类选择“QMainWindow”,类名命名默认为“MainWindow”,取消“创建界面”复选框的选中状态。单击“下一步”按钮,最后单击“完成”按钮,完成该项目工程的建立。

(2)添加该工程的提供实现绘图区的函数所在的文件。在“DrawWidget”项目名上单击鼠标右键,在弹出的快捷菜单中选择“添加新文件...”选项,在弹出的对话框中选择“C++ Class”选项。单击“Choose...”按钮,在弹出的对话框的“Base class”下拉列表框中选择基类名“QWidget”,在“Class name”文本框中输入类的名称“DrawWidget”。

(3)单击“下一步”按钮,单击“完成”按钮,添加文件“drawwidget.h”和文件“drawwidget.cpp”。

1.1绘图区的实现

DrawWidget类继承自QWidget类,在类声明中对鼠标事件mousePressEvent()和mouseMoveEvent()、重画事件paintEvent()、尺寸变化事件resizeEvent()进行了重定义。setStyle()、setWidth()及setColor()函数主要用于为主窗口传递各种与绘图有关的参数。

(1)打开“drawwidget.h”头文件,添加的代码。

#ifndef DRAWWIDGET_H
#define DRAWWIDGET_H

#include <QWidget>
#include <QtGui>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QResizeEvent>
#include <QColor>
#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

(2)打开“drawwidget.cpp”文件,DrawWidget构造函数完成对窗体参数及部分功能的初始化工作,具体代码如下:

#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
{
    startPos = e->pos();
}
void DrawWidget::mouseMoveEvent(QMouseEvent *e)
{
    QPainter *painter = new QPainter;		//新建一个QPainter对象
    QPen pen;								//新建一个QPen对象
    pen.setStyle((Qt::PenStyle)style);		//设置画笔的线型
    pen.setWidth(weight);					//设置画笔的线宽值
    pen.setColor(color);					//设置画笔的颜色
    painter->begin(pix);					//
    painter->setPen(pen);					//将QPen对象应用到绘制对象中
    //绘制从startPos到鼠标当前位置的直线
    painter->drawLine(startPos,e->pos());
    painter->end();
    startPos =e->pos();				//更新鼠标的当前位置,为下次绘制做准备
    update();						//重绘绘制区窗体
}
void DrawWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.drawPixmap(QPoint(0,0),*pix);
}
void DrawWidget::resizeEvent(QResizeEvent *event)
{
    if(height()>pix->height()||width()>pix->width())	
    {
        QPixmap *newPix = new QPixmap(size());	//创建一个新的QPixmap对象
        newPix->fill(Qt::white);                //填充新QPixmap对象newPix的颜色为白色背景色
        QPainter p(newPix);
        p.drawPixmap(QPoint(0,0),*pix);         //在newPix中绘制原pix中的内容
        pix = newPix;                           //将newPix赋值给pix作为新的绘制图形接收对象
    }
    QWidget::resizeEvent(event);                //完成其余的工作
}
void DrawWidget::clear()
{
    QPixmap *clearPix =new QPixmap(size());
    clearPix->fill(Qt::white);
    pix = clearPix;
    update();
}

1.2主窗口的实现

主窗口类MainWindow继承自QMainWindow类,只包含一个工具栏和一个中央窗体。首先,声明一个构造函数、一个用于创建工具栏的函数createToolBar()、一个用于进行选择线型风格的槽函数ShowStyle()和一个用于进行颜色选择的槽函数ShowColor()。然后,声明一个DrawWidget类对象作为主窗口的私有变量,以及声明代表线型风格、线宽选择、颜色选择及清除按钮的私有变量。 (1)打开“mainwindow.h”文件,添加如下代码。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QToolButton>
#include <QLabel>
#include <QComboBox>
#include <QSpinBox>
#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

(2)打开“mainwindow.cpp”文件,MainWindow类的构造函数完成初始化工作,各个功能见注释说明,具体代码如下:

#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);             		//初始化颜色
}

void MainWindow::createToolBar()
{
    QToolBar *toolBar = addToolBar("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()),this,SLOT(ShowColor()));
    clearBtn =new QToolButton();               	//创建清除按钮
    clearBtn->setText(tr("清除"));
    connect(clearBtn,SIGNAL(clicked()),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);
    //使用标准颜色对话框QColorDialog获得一个颜色值
    if(color.isValid())
    {
       //将新选择的颜色传给绘制区,用于改变画笔的颜色值
        drawWidget->setColor(color);
        QPixmap p(20,20);
        p.fill(color);
        colorBtn->setIcon(QIcon(p));		//更新颜色选择按钮上的颜色显示
    }
}

MainWindow::~MainWindow()
{

}

 四、显示Qt 5 SVG格式图片

SVG的英文全称是Scalable Vector Graphics,即可缩放的矢量图形。它是由万维网联盟(World Wide Web Consortium,W3C)在2000年8月制定的一种新的二维矢量图形格式,也是规范中的网格矢量图形标准,是一个开放的图形标准。

SVG格式的特点如下。

(1)基于XML。

(2)采用文本来描述对象。

(3)具有交互性和动态性。

(4)完全支持DOM。

【例】(难度一般)(CH604)通过利用QSvgWidget类和QSvgRender类实现一个SVG图片浏览器,显示以“.svg”结尾的文件以介绍SVG格式图片显示的方法,如图6.20所示。 此实例由三个层次的窗体构成,如图6.21所示。

 在完成此功能的程序中使用与SVG相关的类,必须在程序中包含SVG相关的头文件:    

#include <QtSvg>

由于Qt默认生成的Makefile中只加入了QtGui、QtCore模块的库,所以必须在工程文件“.pro”中加入一行代码:  

 QT += svg

这样才可在编译时加入QtSvg的库。

具体实现步骤如下。

(1)新建Qt Widgets Application(详见1.3.1节),项目名称为“SVGTest”,基类选择“QMainWindow”,类名命名默认为“MainWindow”,取消“创建界面”复选框的选中状态。单击“下一步”按钮,最后单击“完成”按钮,完成该项目工程的建立。

(2)下面添加该工程的提供实现一个带滚动条显示区域的函数所在的文件。在“SVGTest”项目名上单击鼠标右键,在弹出的快捷菜单中选择“添加新文件...”选项,在弹出的对话框中选择“C++ Class”选项。单击“Choose...”按钮,在弹出的对话框的“Base class”文本框中输入基类名“QScrollArea”(手工添加),在“Class name”文本框中输入类的名称“SvgWindow”。

(3)单击“下一步”按钮,单击“完成”按钮,添加文件“svgwindow.h”和文件“svgwindow.cpp”。

(4)添加该工程的提供实现显示SVG图片的函数所在的文件。在“SVGTest”项目名上单击鼠标右键,在弹出的快捷菜单中选择“添加新文件...”选项,在弹出的对话框中选择“C++ Class”选项。单击“Choose...”按钮,在弹出的对话框的“Base class”文本框中输入基类名“QSvgWidget”(手工添加),在“Class name”文本框中输入类的名称“SvgWidget”。

(5)单击“下一步”按钮,单击“完成”按钮,添加文件“svgwidget.h”和文件“svgwidget.cpp”。

(6)打开“svgwidget.h”头文件。SvgWidget类继承自QSvgWidget类,主要显示SVG图片。具体代码如下

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

#endif // SVGWIDGET_H

(7)打开“svgwidget.cpp”文件,SvgWidget构造函数获得本窗体的QSvgRenderer对象。具体代码如下:

#include "svgwidget.h"

SvgWidget::SvgWidget(QWidget *parent):QSvgWidget(parent)
{
    render =renderer();
}

void SvgWidget::wheelEvent(QWheelEvent *e)
{
    const double diff=0.1;						//diff的值表示每次滚轮滚动一定的值,图片大小改变的比例
    QSize size =render->defaultSize();			//该行代码及下面两行代码用于获取图片显示区的尺寸,以便进行下一步的缩放操作
    int width =size.width();
    int height =size.height();
    if(e->delta()>0) 							//利用QWheelEvent的delta()函数获得滚轮滚动的距离值,通过此值来判断滚轮滚动的方向。若delta()值大于零,则表示滚轮向前(远离用户的方向)滚动;若小于零则表示向后(靠近用户的方向)滚动
    {
       //对图片的长、宽值进行处理,放大一定的比例
       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()操作
}

(8)SvgWindow类继承自QScrollArea类,是一个带滚动条的显示区域。在SvgWindow实现中包含SvgWidget类的头文件。SvgWindow类使图片在放大到超过主窗口大小时,能够通过拖曳滚动条的方式进行查看。

打开“svgwindow.h”头文件,具体代码如下:

#ifndef SVGWINDOW_H
#define SVGWINDOW_H

#include <QScrollArea>
#include "svgwidget.h"
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 scrollBarValuesOnMousePress;
};

#endif // SVGWINDOW_H

(9)SvgWindow类的构造函数,构造SvgWidget对象,并调用QScrollArea类的setWidget()函数设置滚动区的窗体,使svgWidget成为SvgWindow的子窗口。 打开“svgwindow.cpp”文件,具体代码如下:

#include "svgwindow.h"

SvgWindow::SvgWindow(QWidget *parent):QScrollArea(parent)
{
    svgWidget =new SvgWidget;
    setWidget(svgWidget);
}
void SvgWindow::setFile(QString fileName)
{
    svgWidget->load(fileName);						//将新的SVG文件加载到svgWidget中进行显示
    QSvgRenderer *render =svgWidget->renderer();
    svgWidget->resize(render->defaultSize());		//使svgWidget窗体按SVG图片的默认尺寸进行显示
}
void SvgWindow::mousePressEvent(QMouseEvent *event)
{
    mousePressPos =event->pos();
    scrollBarValuesOnMousePress.rx()=horizontalScrollBar()->value();
    scrollBarValuesOnMousePress.ry()=verticalScrollBar()->value();
    event->accept();
}
void SvgWindow::mouseMoveEvent(QMouseEvent *event)
{
    horizontalScrollBar()->setValue(scrollBarValuesOnMousePress.x()-event->pos().x()+mousePressPos.x());		//对水平滑动条的新位置进行设置
    verticalScrollBar()->setValue(scrollBarValuesOnMousePress.y()-event->pos().y()+mousePressPos.y());          //对垂直滑动条的新位置进行设置
    horizontalScrollBar()->update();
    verticalScrollBar()->update();
    event->accept();
}

(10)主窗口MainWindow继承自QMainWindow类,包含一个菜单栏,其中有一个“文件”菜单条,包含一个“打开”菜单项。打开“mainwindow.h”头文件,具体代码如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#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

(11)在MainWindow构造函数中,创建一个SvgWindow对象作为主窗口的中央窗体。打开“mainwindow.cpp”文件,具体代码如下:

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setWindowTitle(tr("SVG Viewer"));
    createMenu();
    svgWindow =new SvgWindow;
    setCentralWidget(svgWindow);
}

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);
}

MainWindow::~MainWindow()
{

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值