Qt图形视图框架二--图元创建

  Qt图形视图(Graphics View)内置了一下图元:直线图元(QGraphicsLineItem)、椭圆图元(QGraphicsEllipseItem)、多边形图元(QGraphicsPolygonItem)、文本图元(QGraphicsTextItem)、图片图元(QGraphicsPixmapItem)、矩形图元(QGraphicsRectItem)。用户也可以继承QGraphicsItem实现符合自己需要的图元。 本文将给出图元常用的创建方式。

1.椭圆图元(QGraphicsEllipseItem)

  QGraphicsEllipseItem 表示一个带有填充和轮廓的椭圆,也可以使用它的椭圆段(见 startAngle()、spanAngle())。

  要设置 item 的椭圆,可以传递一个 QRectF 到 QGraphicsEllipseItem 的构造函数,或调用 setRect()。rect() 返回当前椭圆的几何形状。QGraphicsEllipseItem 坐标示意图如下:
  Qt图形视图框架二--图元创建_第1张图片
  Qt图形视图框架二--图元创建_第2张图片

  QGraphicsEllipseItem 使用 rect 和画笔宽度,为 boundingRect()、shape() 和 contains() 提供了一个合理的实现。paint() 函数使用 item 关联的画笔和画刷来绘制椭圆,可以通过调用 setPen() 和 setBrush() 来设置。

示例:

void addEllipseItem()   //在场景中加入一个椭圆形图元
{
    QGraphicsEllipseItem *item = new QGraphicsEllipseItem(QRectF(0, 0, 80, 60));
    item->setPen(Qt::NoPen);
    item->setBrush(QColor(qrand()%256, qrand()%256, qrand()%256));
    item->setFlag(QGraphicsItem::ItemIsMovable);  // 设置图元属性,支持鼠标拖拽

    scene->addItem(item);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}
2.多边形图元(QGraphicsPolygonItem)

  要设置 item 的多边形,传递 QPolygonF 到 QGraphicsPolygonItem 的构造函数,或调用 setPolygon() 函数。polygon() 返回当前的多边形。坐标示意图如下:
  Qt图形视图框架二--图元创建_第3张图片

  QGraphicsPolygonItem 使用多边形和画笔宽度,为 boundingRect()、shape() 和 contains() 提供了一个合理的实现。paint() 函数使用 item 关联的画笔和画刷绘制多边形,可以通过调用 setPen() 和 setBrush() 函数进行设置。

示例:

void addPolygonItem()   //在场景中加入一个多边形图元
{
    QVector<QPoint> v;
    v<<QPoint(30,-15)<<QPoint(0,-30)<<QPoint(-30,-15)<<QPoint(-30,15)<<QPoint(0,30)<<QPoint(30,15);
    QGraphicsPolygonItem *item = new QGraphicsPolygonItem(QPolygonF(v));
    item->setBrush(QColor(qrand()%256,qrand()%256,qrand()%256));
    item->setFlag(QGraphicsItem::ItemIsMovable);

    scene->addItem(item);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}
3.文本图元(QGraphicsTextItem)

  QGraphicsTextItem 类提供了一个格式化的文本项,可以添加到 QGraphicsScene 中。

  要设置 item 的文本,可以传递 QString 到 QGraphicsTextItem 的构造函数,或调用 setHtml()/setPlainText()。

  QGraphicsTextItem 使用文本的格式化大小和相关联的字体,为 boundingRect()、shape() 和 contains() 提供了一个合理的实现。可以通过调用 setFont() 设置字体。

  可以通过使用 setTextInteractionFlags() 设置 Qt::TextEditorInteraction 标志来使 item 可编辑。

  item 的首选文本宽度可以使用 setTextWidth() 设置,并使用 textWidth() 获取。

  注意:为了在中心对齐 HTML 文本,必须设置 item 的文本宽度。否则,可以在设置 item 的文本后调用 adjustSize()。
  
  下图为QGraphicsTextItem的坐标图:
Qt图形视图框架二--图元创建_第4张图片

示例:

void addTextItem()      //在场景中加入一个文字图元
{
    QFont font("Times",16);
    QGraphicsTextItem *item = new QGraphicsTextItem("Hello Qt");
    item->setFont(font);
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setDefaultTextColor(QColor(0, 0, 255));
    scene->addItem(item);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}
4.矩形图元(QGraphicsRectItem)

  QGraphicsRectItem 类提供了一个矩形项,可以添加到 QGraphicsScene 中。

  要设置 item 的矩形,可以传递一个 QRectF 到 QGraphicsRectItem 的构造函数,或调用 setRect() 函数。rect() 返回当前矩形。

  Qt图形视图框架二--图元创建_第5张图片
  QGraphicsRectItem 使用矩形和画笔宽度,为 boundingRect()、shape() 和 contains() 提供了一个合理的实现。paint() 函数使用 item 关联的画笔和画刷绘制矩形,可以通过调用 setPen() 和 setBrush() 函数来设置。

  注意:无效矩形(例如,宽度或高度为负)的呈现是未定义的。如果不能确定使用的是有效的矩形(例如,如果使用来自不可靠源的数据创建的矩形),那么应该使用 QRectF::normalized() 创建标准化的矩形,然后使用它们。

示例:  

void addRectItem()      //在场景中加入一个长方形图元
{
    QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0,0,60,60));
    QPen pen;
    pen.setWidth(3);
    pen.setColor(QColor(qrand()%256,qrand()%256,qrand()%256));
    item->setPen(pen);
    item->setBrush(QColor(qrand()%256,qrand()%256,qrand()%256));
    item->setFlag(QGraphicsItem::ItemIsMovable);

    scene->addItem(item);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}
5.图片图元(QGraphicsPixmapItem)

  QGraphicsPixmapItem 类提供了一个图像项,可以添加到 QGraphicsScene 中。

  要设置 item 的图像,可以传递 QPixmap 到 QGraphicsPixmapItem 的构造函数,或调用 setPixmap() 函数,pixmap() 返回当前的图像。

  QGraphicsPixmapItem 使用 pixmap 的可选 alpha 掩码,为 boundingRect()、shape() 和 contains() 提供了一个合理的实现。

  默认情况下图像在 item 的 (0, 0) 坐标处绘制,由 offset() 返回。可以通过调用 setOffset() 更改绘图偏移量。如下图所示:
  Qt图形视图框架二--图元创建_第6张图片

  可以通过调用 setTransformationMode() 设置图像的变换模式,默认情况下,使用 Qt::FastTransformation,它提供了快速、不平滑的缩放。Qt::SmoothTransformation 在 painter 上启用 QPainter::SmoothPixmapTransform,质量取决于平台和视口。结果通常不如调用 QPixmap::scale() 直接,调用 transformMode() 获取项目的当前转换模式。

示例:

void addAlphaItem()     //在场景中加入一个透明蝴蝶图片
{
    QGraphicsPixmapItem *item =scene->addPixmap(QPixmap("image.png"));
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}
6.自定义图元

  自定义图元主要有一下几点需要注意:
  1.必须继承自QGraphicsItem
  2.必须实现虚方法QRectF QGraphicsItem::boundingRect() const,此方法主要是为图元限定区域范围;
  3.若需要绘图的话需要重写方法void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);,此方法跟QWidget中的void paintEvent()作用相同;
  4.若在图元内部实现定时器之类的则需要继承相应的父类才行。
  
  下面实现一个可以闪烁的自定义图元:
  
FlashItem.h

#ifndef FLASHITEM_H
#define FLASHITEM_H

#include 
#include 
#include 

class FlashItem : public QObject,public QGraphicsItem
{
    Q_OBJECT
public:
    explicit FlashItem(QObject *parent = 0);
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
    void timerEvent(QTimerEvent *);
private:
    bool flash;
    QTimer *timer;
signals:

public slots:

};

#endif // FLASHITEM_H

FlashItem.cpp

#include "flashitem.h"

FlashItem::FlashItem(QObject *parent) :
    QObject(parent)
{
    flash=true;
    setFlag(ItemIsMovable);  // 使当前图元支持鼠标拖拽
    startTimer(1000);        // 启动定时器,定时间隔为1S
}

QRectF FlashItem::boundingRect() const
{
    qreal adjust = 2;
    return QRectF(-10-adjust,-10-adjust,43+adjust,43+adjust);
}

void FlashItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setPen(Qt::NoPen);
    painter->setBrush(Qt::darkGray);
    painter->drawEllipse(-7,-7,40,40);

    painter->setPen(QPen(Qt::black,0));
    painter->setBrush(flash?(Qt::red):(Qt::yellow));
    painter->drawEllipse(-10,-10,40,40);
}

void FlashItem::timerEvent(QTimerEvent *)
{
    flash=!flash;
    update();
}
7.工程代码

  下面为整个工程的代码,本文所采用的是Qt5.6.1版本。

main.cpp

#include "MainWindow.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;

    w.show();

    return a.exec();
}

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include 
#include 
#include 
#include 

class MainWindow : public QMainWindow
{
    Q_OBJECT    
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void initScene();                       //初始化场景

    void addEllipseItem();              //在场景中加入一个椭圆形图元
    void addPolygonItem();              //在场景中加入一个多边形图元
    void addTextItem();                 //在场景中加入一个文字图元
    void addRectItem();                 //在场景中加入一个长方形图元
    void addAlphaItem();                //在场景中加入一个透明蝴蝶图片
    void addFlashItem();
    void addAnimationItem();

private:
    QGraphicsScene *scene;

    QAction *newAct;
    QAction *clearAct;
    QAction *exitAct;
    QAction *addEllipseItemAct;
    QAction *addPolygonItemAct;
    QAction *addTextItemAct;
    QAction *addRectItemAct;
    QAction *addAlphaItemAct;
    QAction *addFlashItemAct;
    QAction *addAnimItemAct;
};

#endif // MAINWINDOW_H

MainWindow.cpp

#include "MainWindow.h"
#include "FlashItem.h"
#include 
#include 

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    scene = new QGraphicsScene;
    scene->setSceneRect(-200,-200,400,400);

    initScene();     //初始化场景

    QGraphicsView *view = new QGraphicsView;
    view->setScene(scene);
    view->setMinimumSize(400,400);
    view->show();

    setCentralWidget(view);
    resize(550,450);
    setWindowTitle(tr("Graphics Items"));
}

MainWindow::~MainWindow()
{
}

void MainWindow::initScene()   //初始化场景
{
    addEllipseItem();
    addPolygonItem();
    addTextItem();
    addRectItem();
    addAlphaItem();
    addFlashItem();
}

void MainWindow::addEllipseItem()   //在场景中加入一个椭圆形图元
{
    QGraphicsEllipseItem *item = new QGraphicsEllipseItem(QRectF(0,0,80, 60));
    item->setPen(Qt::NoPen);
    item->setBrush(QColor(qrand()%256, qrand()%256, qrand()%256));
    item->setFlag(QGraphicsItem::ItemIsMovable);

    scene->addItem(item);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}

void MainWindow::addPolygonItem()   //在场景中加入一个多边形图元
{
    QVector v;
    v<30,-15)<0,-30)<30,-15)<30,15)<0,30)<30,15);
    QGraphicsPolygonItem *item = new QGraphicsPolygonItem(QPolygonF(v));
    item->setBrush(QColor(qrand()%256,qrand()%256,qrand()%256));
    item->setFlag(QGraphicsItem::ItemIsMovable);

    scene->addItem(item);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}

void MainWindow::addTextItem()      //在场景中加入一个文字图元
{
    QFont font("Times",16);
    QGraphicsTextItem *item = new QGraphicsTextItem("Hello Qt");
    item->setFont(font);
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setDefaultTextColor(QColor(0, 0, 255));
    scene->addItem(item);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}

void MainWindow::addRectItem()      //在场景中加入一个长方形图元
{
    QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0,0,60,60));
    QPen pen;
    pen.setWidth(3);
    pen.setColor(QColor(qrand()%256,qrand()%256,qrand()%256));
    item->setPen(pen);
    item->setBrush(QColor(qrand()%256,qrand()%256,qrand()%256));
    item->setFlag(QGraphicsItem::ItemIsMovable);

    scene->addItem(item);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}

void MainWindow::addAlphaItem()     //在场景中加入一个透明蝴蝶图片
{
    QGraphicsPixmapItem *item =scene->addPixmap(QPixmap("image.png"));
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}

void MainWindow::addFlashItem()     //在场景中加入一个闪烁图元
{
    FlashItem *item = new FlashItem;
    scene->addItem(item);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}

FlashItem.h
  本文上面已经给出完整的实现。

FlashItem.cpp
  本文上面已经给出完整的实现。

.pro文件

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = GraphicsItem
TEMPLATE = app

SOURCES += main.cpp\
        mainwindow.cpp \
    flashitem.cpp \
    startitem.cpp

HEADERS  += mainwindow.h \
    flashitem.h \
    startitem.h
8.运行结果

  运行结果如下所示:
Qt图形视图框架二--图元创建_第7张图片

你可能感兴趣的:(Qt,qt,图形视图,Graphics,View,图元)