Qt图形视图(Graphics View)框架二--图元创建

时间:2022-06-16 12:10:27

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

1.椭圆图元(QGraphicsEllipseItem)

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

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

  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图形视图(Graphics View)框架二--图元创建

  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图形视图(Graphics View)框架二--图元创建

示例:

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图形视图(Graphics View)框架二--图元创建
  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图形视图(Graphics View)框架二--图元创建

  可以通过调用 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 <QObject>
#include <QGraphicsItem>
#include <QPainter>

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 <QApplication>

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 <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QMenuBar>
#include <QGraphicsEllipseItem>
#include <QDebug>

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 <QGraphicsItemAnimation>
#include <QTimeLine>

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

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图形视图(Graphics View)框架二--图元创建