Qt图形视图(Graphics View)内置了一下图元:直线图元(QGraphicsLineItem)、椭圆图元(QGraphicsEllipseItem)、多边形图元(QGraphicsPolygonItem)、文本图元(QGraphicsTextItem)、图片图元(QGraphicsPixmapItem)、矩形图元(QGraphicsRectItem)。用户也可以继承QGraphicsItem实现符合自己需要的图元。 本文将给出图元常用的创建方式。
QGraphicsEllipseItem 表示一个带有填充和轮廓的椭圆,也可以使用它的椭圆段(见 startAngle()、spanAngle())。
要设置 item 的椭圆,可以传递一个 QRectF 到 QGraphicsEllipseItem 的构造函数,或调用 setRect()。rect() 返回当前椭圆的几何形状。QGraphicsEllipseItem 坐标示意图如下:
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);
}
要设置 item 的多边形,传递 QPolygonF 到 QGraphicsPolygonItem 的构造函数,或调用 setPolygon() 函数。polygon() 返回当前的多边形。坐标示意图如下:
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);
}
QGraphicsTextItem 类提供了一个格式化的文本项,可以添加到 QGraphicsScene 中。
要设置 item 的文本,可以传递 QString 到 QGraphicsTextItem 的构造函数,或调用 setHtml()/setPlainText()。
QGraphicsTextItem 使用文本的格式化大小和相关联的字体,为 boundingRect()、shape() 和 contains() 提供了一个合理的实现。可以通过调用 setFont() 设置字体。
可以通过使用 setTextInteractionFlags() 设置 Qt::TextEditorInteraction 标志来使 item 可编辑。
item 的首选文本宽度可以使用 setTextWidth() 设置,并使用 textWidth() 获取。
注意:为了在中心对齐 HTML 文本,必须设置 item 的文本宽度。否则,可以在设置 item 的文本后调用 adjustSize()。
下图为QGraphicsTextItem的坐标图:
示例:
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);
}
QGraphicsRectItem 类提供了一个矩形项,可以添加到 QGraphicsScene 中。
要设置 item 的矩形,可以传递一个 QRectF 到 QGraphicsRectItem 的构造函数,或调用 setRect() 函数。rect() 返回当前矩形。
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);
}
QGraphicsPixmapItem 类提供了一个图像项,可以添加到 QGraphicsScene 中。
要设置 item 的图像,可以传递 QPixmap 到 QGraphicsPixmapItem 的构造函数,或调用 setPixmap() 函数,pixmap() 返回当前的图像。
QGraphicsPixmapItem 使用 pixmap 的可选 alpha 掩码,为 boundingRect()、shape() 和 contains() 提供了一个合理的实现。
默认情况下图像在 item 的 (0, 0) 坐标处绘制,由 offset() 返回。可以通过调用 setOffset() 更改绘图偏移量。如下图所示:
可以通过调用 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);
}
自定义图元主要有一下几点需要注意:
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();
}
下面为整个工程的代码,本文所采用的是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