QGraphic学习笔记 - 图文 下载本文

一个小的简单的游戏引出的心得体会

分解实例1 实例描述:

实现一个按钮,按钮继承自QGraphicObject,

头文件:

class myButton : public QGraphicsObject {

Q_OBJECT public:

myButton(int ,int,QString ,QString ,class MainWindow *); QRectF boundingRect() const; void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); protected:

void hoverEnterEvent ( QGraphicsSceneHoverEvent *) ; void hoverLeaveEvent ( QGraphicsSceneHoverEvent *) ; void mousePressEvent ( QGraphicsSceneMouseEvent *); private:

QPixmap pix; QString img;

QString hoverImg; class MainWindow * m;

Phonon::MediaObject *clickMic; signals:

void clickSig(); };

源文件:

myButton::myButton(int x,int y,QString img,QString hoverImg,class MainWindow * m){ this->img=img;

this->hoverImg=hoverImg; pix.load(img);

setPos(x-pix.width()/2,y-pix.height()/2); this->m=m;

setFlags(QGraphicsItem::ItemIsFocusable); setFlags(QGraphicsItem::ItemIsMovable); setAcceptHoverEvents(true);

clickMic=Phonon::createPlayer(Phonon::MusicCategory,

Phonon::MediaSource(\));

}

QRectF myButton::boundingRect() const{

return QRectF(0, 0, pix.width(), pix.height()); }

void myButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){

painter->drawPixmap(0,0,pix.width(), pix.height(),pix); }

void myButton::hoverEnterEvent ( QGraphicsSceneHoverEvent *) { setFocus(Qt::MouseFocusReason);

pix.load(hoverImg); clickMic->play(); update(); }

void myButton::hoverLeaveEvent ( QGraphicsSceneHoverEvent *) { setFocus(Qt::MouseFocusReason); pix.load(img); update(); }

void myButton::mousePressEvent ( QGraphicsSceneMouseEvent *){ emit clickSig(); }

引用文件:

cjScene = new QGraphicsScene;//新建场景指针 cjScene->clear(); myButton *sbtn=new

myButton(width/2,height/2-200,\,\tn2.png\,this);

connect(sbtn,SIGNAL(clickSig()),this,SLOT(guanKaScene())); cjScene->addItem(sbtn); myButton *soundBtn=new

myButton(width/2,height/2,\,\png\,this);

cjScene->addItem(soundBtn); myButton *quitBtn=new

myButton(width/2,height/2+200,\,\2.png\,this);

connect(quitBtn,SIGNAL(clickSig()),this,SLOT(close())); cjScene->addItem(quitBtn);

cjScene->setSceneRect(0,0,width,height);

cjScene->setBackgroundBrush( QPixmap(\).scaled(width,height));

this->setScene(cjScene);

绘制动画精灵1:

void ninjia::play(){

QTimeLine* timeline=new QTimeLine(200); timeline->setFrameRange(1, 4);

connect(timeline,SIGNAL(frameChanged(int)),this,SLOT(move_play(int)));

timeline->start(); }

void ninjia::move_play(int i){ qDebug()<

QString path=\; pix.load(path); return; }

QString path=\+QString::number(i)+\; pix.load(path); }

绘制动画精灵2:

timeline=new QTimeLine(1000);

timeline->setFrameRange(1, maxFrame); timeline->setLoopCount(0);

connect(timeline,SIGNAL(frameChanged(int)),this, SLOT(move_play(int))); timeline->start();

void target::move_play(int i){ qDebug()<

QString path=imgPath+QString::number(i)+\; pix.load(path); }

精灵的碰撞检测:

bool target::isColliding() {

QList item_list = collidingItems(); QGraphicsItem *item;

foreach(item, item_list) {

if(item->data(1)==\){ item->stackBefore(this); }

if((item->data(1)==\||item->data(1)==\)&&(this->boundingRect().y()+this->pos().y()+this->boundingRect().height())<(item->boundingRect().y()+item->pos().y()+item->boundingRect().height())){ this->stackBefore(item); }

if(item->data(1)==\&&item->data(2)!=false){ life=life-((projectile*)item)->gePower(); m->deleteItem((projectile*)item); item->setData(2,false); if(life>0){return true;} m->updateScore(10); this->setData(2,false); return true; } }

return false; }

子弹的发射

void myScene::mousePressEvent( QGraphicsSceneMouseEvent * e ){ projectile *p=new

projectile(x,y,m,angleValue,6,\,m->getAttack()); this->addItem(p); pewMic->pause(); pewMic->play();

QGraphicsScene::mousePressEvent(e); }

子弹的自动移动与移除:

void projectile::advance(int i){

moveBy(cos(angleValue)*speed,sin(angleValue)*speed);

if(this->data(2)==false||pos().x()>this->m->scene()->width()||pos().y()>this->m->scene()->height()||pos().y()<0||pos().x()<0){ drop();//移除本身removeItem(this);

} }

子项目自动运行函数:

void basePropertys::advance(int ){ isColliding(); }

场景中设置文字:

gameScene->setSceneRect(0,0,width,height); setScene(gameScene);

game_score=new QGraphicsTextItem(0, gameScene); game_score->setHtml(\ color = red>分

数:\+QString::number(score)+\);

game_score->setFont(QFont(\, 20, QFont::Bold));

game_score->setPos(10, 10);

game_attack=new QGraphicsTextItem(0, gameScene); game_attack->setHtml(\ color = red>攻击

力:\+QString::number(attackPower)+\);

game_attack->setFont(QFont(\, 20, QFont::Bold)); game_attack->setPos(10, 70);

life_text =new QGraphicsTextItem(0, gameScene); life_text->setHtml(\ color = red>生命:

\+QString::number(attackPower)+\);

life_text->setFont(QFont(\, 20, QFont::Bold));

life_text->setPos(10, 40);

bB=new bloodBar(80,50,this);

gameScene->addItem(bB);

Animation 动画

方法一、items 继承QGraphicsObject,并联合使用QPropertyAnimation

方法二、自定义item,继承QObject 和QGraphicsItem。给item 设置一个定时器,在QObject::timerEvent() 事件中控制动画。

方法三、调用 QGraphicsScene::advance(), 此函数转而调用QGraphicsItem::advance() The QGraphicsObject class provides a base class for all graphics items that require signals, slots and properties.

The class extends a QGraphicsItem with QObject's signal/slot and property mechanisms. It maps many of QGraphicsItem's basic setters and getters to properties and adds notification signals for many of them.

The QGraphicsScene class provides a surface for managing a large number of 2D graphical items.

The class serves as a container for QGraphicsItems. It is used together

with QGraphicsView for visualizing graphical items, such as lines, rectangles, text, or even custom items, on a 2D surface. QGraphicsScene is part of the Graphics View Framework.

通过调用scene()的advance(),则item会调用advance()函数: void MainWindow::updateItems(){ this->scene()->advance(); scene()->update(); }

返回item列表

QList item_list = scene()->items(); QGraphicsItem *item;

foreach(item, item_list) { //操作。。。 }

关卡:

myScene *bscene = new myScene(this);//新建场景指针 game_text=new QGraphicsTextItem(0, bscene); game_text->setHtml(text); game_text->setZValue(1);

game_text->setFont(QFont(\, 50, QFont::Bold)); game_text->setPos(100, 150); setScene(bscene);

游戏结束,文本移动动画:

game_text=new QGraphicsTextItem(0, scene()); game_text->setHtml(text); game_text->setZValue(1);

QTimeLine *timeline=new QTimeLine(800); timeline->setFrameRange(1, 50); timeline->setLoopCount(1);

connect(timeline,SIGNAL(frameChanged(int)),this,SLOT(gameOverPlay(int)));

timeline->start();

void MainWindow::gameOverPlay(int i){

game_text->setFont(QFont(\, i, QFont::Bold)); game_text->setPos(10*i, 150); }

setRenderHint(QPainter::Antialiasing);//防锯齿

setCacheMode(QGraphicsView::CacheBackground);//双缓冲

showFullScreen();//全屏

//三个按钮

cjScene = new QGraphicsScene;//新建场景指针 cjScene->clear(); myButton *sbtn=new

myButton(width/2,height/2-200,\,\tn2.png\,this);

connect(sbtn,SIGNAL(clickSig()),this,SLOT(guanKaScene())); cjScene->addItem(sbtn); myButton *soundBtn=new

myButton(width/2,height/2,\,\png\,this);

cjScene->addItem(soundBtn); myButton *quitBtn=new

myButton(width/2,height/2+200,\,\2.png\,this);

connect(quitBtn,SIGNAL(clickSig()),this,SLOT(close())); cjScene->addItem(quitBtn);

cjScene->setSceneRect(0,0,width,height);

cjScene->setBackgroundBrush( QPixmap(\).scaled(width,height));

setScene(cjScene);

修改后的lxExp.h文件内容: // 前置声明 class ClxImplement; class ClxExp { public: ClxExp();

virtual ~ClxExp(); void DoSomething(); private:

// 声明一个类ClxImplement的指针,不需要知道类ClxImplement的定义 ClxImplement *m_pImpl; };

修改后的lxExp.cpp文件内容: #include \

// 在这里包含类ClxImplement的定义头文件 #include \ClxExp::ClxExp() {

m_pImpl = new ClxImplement; }

ClxExp::~ClxExp() {

if (m_pImpl) delete m_pImpl; }

void ClxExp::DoSomething() {

m_pImpl->DoSomething(); }

对于C++中,类的定义之前声明它,如下实例代码: class B; class A{

//.............................. B * ptr_B;. }; class B{ //.................... };

被提前声明的类在其定义之前,只能使用该类的指针或者引用 。

在类的定义结束(编译器在遇到类定义的右花括号之后),用该类来声明类实例对象,或对象指针,引用都是合法的。 前向声明 超前引用

所谓超前引用是指一个类型在定义之前就被用来定义变量和声明函数。

一般情况下,C/C++要求所有的类型必须在使用前被定义,但是在一些特殊情况下,这种要求无法满足,

例如,在类CMyView中保留了一个非模式对话框对象指针,该对象用于显示/修改一些信息。为了实现对话框

“应用”按钮,把对话框做的修改立刻更新到view界面上,为此,需要在对话框类中需要保存view类的指针,这样 定义关系就变成如下的代码:

#ifndef __MYVIEW_H__ #define __MYVIEW_H__ //这是view类的头函数 #include \ class CMyView::public CView {

protected:

CMyDialog * pDlg; //这里是其他定义 }; #endif

#ifndef __MYDIALOG_H__ #define __MYDIALOG_H__ //这是对话框类的定义 #include \

class CMyDialog::public CDialog {

protected:

CMyView * pView; //其他定义 }; #endif

从编译器角度看,编译MyDialog.CPP时,系统首先定义宏__MYDIALOG_H__,然后包含MyView.h,MyView.h中

的#include \由于__MYDIALOG_H__已经定义,所以不再起作用。在CMyView类的声明中,

CMyDialog* pDlg ;

就会让编译器产生“CMyDialog\类型没有定义之类的错误,编译MyView.CPP文件出现的错误可以类似得到。

更一般的情况,类A和类B需要彼此互相引用,这样必然有一个类会先被定义,而另外一个类后被定义,这样在

先被定义的类引用后被定义的类的时候,就导致了所谓的超前引用。

超前引用导致的错误有以下几种处理办法: 1) 使用类声明

在超前引用一个类之前,首先用一个特殊的语句说明该标识符是一个类名,即将被超前引用。其使用方法是:

a) 用class ClassB;声明即将超前引用的类名 b) 定义class ClassA c) 定义class ClassB; d) 编制两个类的实现代码。

上述方法适用于所有代码在同一个文件中,一般情况下,ClassA和ClassB分别有自己的头文件和cpp文件,这种 方法需要演变成:

a) 分别定义ClassA和ClassB,并在cpp文件中实现之

b) 在两个头文件的开头分别用class ClassB;和class ClassA;声明对方 c) 在两个cpp文件中分别包含另外一个类的头文件

NOTE:这种方法切记不可使用类名来定义变量和函数的变量参数,只可用来定义引用或者指针。

2) 使用全局变量

由于全局变量可以避免超前引用,不用赘述。我的习惯是,把类对象的extern语句加在该类头文件的最后,大家喜欢

怎样写那都没有什么大问题,关键是保证不要在头文件中胡乱包含。 3) 使用基类指针。

这种方法是在引用超前引用类的地方一律用基类指针。而一般情况下,两个互相引用的类并不涉及其基类,因此不会造成

超前引用。以开始的例子说:在CMyDialog类中用CView*代替CMyView*,在CMyView类中用CDialog*代替CMyDialog*,这样必然 不会造成超前引用。

说明:本文中,为了叙述方便,把class AClass;语句成为类AClass的声明,把class AClass开始的对AClass的类成员变量、

成员函数原型等的说明称为类的定义,而把在CPP中的部分称为类的定义。如果大家对这三个词有不同的理解,请按照自己的本意 把这三个词换成相应的词来理解。

写自己的Item,要先了解QGraphicsItem的相关属性及操作有哪些,哪些是必须要重写的,哪些是可以选的:

透明度鼠标悬浮事件鼠标双击,移动,释放的事件旋转度缩放系数截获事件滚动item void QGraphicsItem::moveBy ( qreal dx, qreal dy )

向x,y方向上移动dx,dy的距离,等价于调用setPos(pos()+QpointF(dx,dy))

写自己的item图形,首先应该继承QGraphicsItem,然后重写他的两个纯虚公共函数,boundingRect()和paint(),第一个函数返回绘制item大概的区域,第二个函数用来绘制item内容:

void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QRectF boundingRect() const;

boundingRect()函数有很多用处,场景在boundingRect()来建立它的item的index,视图view使用它来剪切可见的item,在重新绘制item时候,来决定相互重叠的部分,此外,item的碰撞检测机制也使用的boundingRect()来提供一个高效的定点,在collidesWithItem()更好的碰撞算法建立在调用函数shape(),shape()函数以QpainterPath类型返回item的精准的轮廓。

一般的,场景不希望item的boundingRect()和shape()变化,除非该item被通告,如果想通过一些方法改变item的形状,首先应该调用QgraphicsScene()来允许场景QgraphicsScene来刷新它的item记录。 碰撞检测可以通过下面两种方法来完成

1、重写shape()函数来返回item的精准轮廓,依靠默认的collidesWithItem()来做外形交集。如果item轮廓和复杂时候,这个消耗是很大的

2、重写collidesWithItem(),提供一个自己的item和轮廓碰撞的算法

Contains()函数可以调用,用来决定一个item是否包含一个点。这个函数也可以重写,contains()函数默认的方法是通过调用shape()来完成的。

Items中也可以包含其他的items,也可以被别的items包含,所有的items可以有一个父亲item和一串孩子items,除非一个item没有父亲,否则它的位置是在父亲坐标中,父亲items遗传他的位置和转换给孩子item 转换

QgraphicsItem支持投射转换,有很多方法来改变item的转换,对于简单的转换,可以调用函数setRotation()或者setScale(),可以传递一个转换矩阵给函数setTransform(),对于一些更复杂的转换,可以通过调用函数setTransformations()来设置一系列组合的转换。 Item转换从父亲到孩子进行聚集,因此如果一个父亲和孩子item都旋转90度,那么孩子就旋转了180度,相似的,如果父亲item放大了2X倍,那么孩子item就被方法4X倍,

一个item的转换不影响他的外观,所有和外观有关的函数(例如contains(),update()和所有的映射mapping函数)将会在本地坐标中操作,更方便的,QgraphicsItem提供函数sceneTransform(),将会返回item所有的转换矩阵,scenePos()将会返回item在场景坐标中的位置,重新设置item的矩阵,调用函数resetTransform()

一般的转换回产生一个不同的结果,这取决于转换应用的顺序,例如,如果你放大一个转换,然后再旋转它,可能和你先旋转它得到的结果不一样,你设置转换属性的顺序并不影响转换的结果,(也就是仍旧会按照你的转换命令去转换,只是最后得到的图形不一样而已),QgraphicsItem经常应用一个合适的顺序如下:

绘图painting

paint()函数被QgrapicsView类调用来绘制item的内容,item默认是没有背景或者填充颜色的。在函数中没有被绘制的所有区域都将会发亮,可以调用update()来重绘item,可以选择传递需要重绘的矩形区域(不是必须的)。取决于item在view中是否可见,item可能会也可能不会重绘,QgraphicsItem里面没有和Qwidget::repaint()函数等价的

item通过view来绘制,从父items开始,然后是自items,以上升的栈的顺序,可以通过调用setZValue()设置item的栈顺序,通过zValue()来测试,具有低z-values的item比具有高z-value的item先绘制,栈顺序应用于兄弟items,父items总是比子items更早绘制。 排序sort

所有的items都按照一个已经声明的,稳定的顺序来绘制,这个顺序也决定了当你在场景中点击鼠标时候,哪个items最先接受鼠标的输入。一般的,你不需要担心排序问题,因为所有的items都按照一个在场景中声明的自然的顺序

在一个栈中,子item在父item的上面,兄弟item按照插入场景的顺序来入栈,如果你先添加了item A ,然后是item B,然后是item C ,这样栈中的顺序从下往上就是A,B,C Drag and Drop Robot例子中展示了该robot的栈顺序,躯干顺序是根item(其他所有的item都是躯干item的子item或者后代item),然后是头item被绘制,由于它是躯干item的子item列表中的第一个item,然后是左臂膀上面的那部分item,下面那个臂膀item是上面臂膀item的子item,所以会在和3号item同等级的兄弟item绘制完后被绘制,接着就是右边上面的的臂膀item,就是5号item。

。可以调用setZvalue()来设置一个item的相对亦另一个向上,向下或者兄弟栈顺序。默认的Z值是0,具有同样的Z值的item会按照插入的顺序来入栈。

。可以调用stackBefore()来备份孩子item的列表,这可以直接更正item的顺序。 。如果想让孩子item在父item的后面,也就是先绘制孩子item,然后在绘制父item,怎么办呢?可以设置ItemStacksBehindParent属性给这个item,利用函数setFlag(); 两个兄弟item的顺序也决定了他们的子item 和后代item的顺序,如果一个父item的在两个父item的后面,那么他所有的孩子items都在另一个父item的孩子items后面。 事件Event

QgraphicsItem从场景中通过sceneEvent()函数来接受事件,这个函数通过一些方便的操作分散大部分事件

ContextMenuEvent()函数接受上下文菜单事件

FocusInEvent()和focusOutEvent()函数接受焦点进出事件

hoverEnterEvent(), hoverMoveEvent(), and hoverLeaveEvent() 接受鼠标悬浮 移动和离开事件

inputMethodEvent()函数处理输入法事件,

keyPressEvent() and keyReleaseEvent()事件处理键盘按下和松开事件 mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), and mouseDoubleClickEvent()处理鼠标按下,移动,松开,双击事件

也可以为一些item过滤一些事件通过安装过滤器,这个和QT一般的事件过滤器不一样,一般的过滤器只工作在Qobject和它的子类,通过调用installSceneEventFilter()为item安装了过滤器后,被过滤的事件将会被虚函数sceneEventFilter().捕捉到,可以通过调用函数removeSceneEventFilter().来去除掉事件过滤器

Custom Data数据

有些时候为item注册一些数值很有用,做一个普通的item或者标准的item,可以调用setData()来为任一个item设置值,这个值使用key-value对,(key是整形,value是变种数据Qvarient)来得到item的数据,通过调用data(),

1、QVariant QGraphicsItem::itemChange ( GraphicsItemChange change, const QVariant & value ) [virtual protected]

这个函数被QGraphicsItem调用用来标明items的一些状态改变了,通过重载这个函数,可以对自己定义事件响应,在一些情况下,可以做一些调整。

参数change是改变的那个item的改变状态参数,value是一个新的数据,他的类型取决于change,

change是QGraphicsItem::GraphicsItemChange的枚举变量

enum GraphicsItemChange { ItemEnabledChange, ItemEnabledHasChanged, ItemMatrixChange, ItemPositionChange, ..., ItemScenePositionHasChanged } 例如:

QVariant Component::itemChange(GraphicsItemChange change, const QVariant &value)

{

if (change == ItemPositionChange && scene()) { // value is the new position. QPointF newPos = value.toPointF(); QRectF rect = scene()->sceneRect(); if (!rect.contains(newPos)) {

// Keep the item inside the scene rect.

newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left()))); newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top()))); return newPos; } }

return QGraphicsItem::itemChange(change, value); }

默认的函数什么都不做,只返回value

注意:在使用这个函数时候,在函数内部调用函数时候要小心,因为这可能导致一些意想不到的结果,例如:你不能再这个函数里面调用setPos()在change是ItemPositionChange时候,由于setPos()函数将会再次调用itemChange(ItemPositionChange),如此就一直循环下去了。

2、void QGraphicsItem::setFlag ( GraphicsItemFlag flag, bool enabled = true ) void QGraphicsItem::setFlags ( GraphicsItemFlags flags )

把flags设置为item的属性,如果item获得了光标,但是flags没有使能ItemsFocusable,这个item

将会丢失光标,同样的,当item被选择到,但是没有使能ItemsSelectable,这个item会自动的失去 选择。

默认的,所有的flags都是不可用的。(QGraphicsWidget 为了获得位置变化默认使能了 ItemSendsGeometryChanges) 相近的函数

GraphicsItemFlags QGraphicsItem::flags () const

返回item的所有使能的flags,例如,如果flags里面包含了ItemIsFocusable,这个item可以接受 输入光标

3、QPainterPath QGraphicsItem::shape () const [virtual]

以QPainterPath返回item在local坐标中的形状,这个形状可以用来做很多事情,包括碰撞侦测,

打击测试,还有用来 QGraphicsScene::items() 函数

默认的函数调用boundingRect()返回一个简单的矩形形状,但是子类可以重载这个函数,为非矩形

的item返回一个更加精准的形状,例如一个圆形的item可以选择返回一个椭圆形,用来获得更好的

碰撞侦测效果。代码:

QPainterPath RoundItem::shape() const {

QPainterPath path;

path.addEllipse(boundingRect()); return path; }

形状的轮廓线可以通过绘制时候的pen来变化

4、QRectF QGraphicsItem::boundingRect () const [pure virtual]

这个纯虚函数用矩形声明了item的边界轮廓,所有的绘制都必须限定在item的矩形边框内。 QGraphicsView使用这个方法来决定item是否需要重绘

尽管item的形状可以是任意的,但是边框一直都是矩形,不影响items的变换

如果想改变items的边框,应该首先调用prepareGeometryChange(),这将通知场景scene即将发生的变化,这样场景可以刷新item的位置下标。否则,场景将不会察觉到item的变化,结果也未知。

如果要重绘item时候,重载这个函数来让QGraphicsView来决定item的边界区域, 注意:由于绘制边界时候的边界轮廓线,在这个矩形区域内包含画笔pen宽度的一半很重要,不需

要补偿画图走样 例如

QRectF CircleItem::boundingRect() const {

qreal penWidth = 1;

return QRectF(-radius - penWidth / 2, -radius - penWidth / 2, diameter + penWidth, diameter + penWidth); }

同样的一个返回item轮廓的函数

QRegion QGraphicsItem::boundingRegion ( const QTransform & itemToDeviceTransform ) const

返回该item的轮廓区域,返回的区域的坐标系统依赖于参数itemToDeviceTransform,如果你传递一个Qtransform对象作为参数,那么函数将返回本地坐标系统区域

返回的区域是item内容可见的一个大概的轮廓,尽管计算起来很浪费空间和时间,但是比boundingRect()更精准,而且当重绘时候,它还能避免不必要的重绘。对像线或者简单的多边形来说非常有效。

也可以调节轮廓区域的粒度通过调用setBoundingRegionGranularity(),默认的粒度是0,这时候item的区域和轮廓矩形一样的。

itemToDeviceTransform是从item坐标系统到设备坐标系统的一个转换。如果你想让这个函数返回一个场景坐标区域,可以用函数sceneTransform()作为参数。 相关函数qreal QGraphicsItem::boundingRegionGranularity () const 返回item的轮廓区域粒度

5、void QGraphicsItem::setPos ( const QPointF & pos )

在父对象坐标系统中设置item的位置为pos,对没有父对象的items,pos使用的场景的坐标系统,

6、QPointF QGraphicsItem::scenePos () const

返回该item在场景中的坐标点,等价于调用函数mapToScene(0, 0). 7、QPointF QGraphicsItem::pos () const

返回item在父坐标系中的位置,如果没有父坐标系,那么返回在场景坐标系中的位置,此时等价于调用scenePos (),可以直接调用scenePos ()来获取该item在场景中的位置,从而忽略其父对象。

8、enum QGraphicsItem::CacheMode

设置绘图的缓冲模式,默认是没有缓冲,如果使用缓冲区的话,在重绘时候,非常快

设置缓冲模式使用函数QGraphicsItem::setCacheMode(). 9、bool QGraphicsItem::acceptDrops () const

如果item能够接受拖拽事件,就返回真,否则返回假,默认的不能接受拖拽事件 同类函数

void QGraphicsItem::setAcceptDrops ( bool on )

如果On是真的话,就设置item可以接受拖拽事件,否则对拖拽事件是透明的,也就是不能响应拖拽,默认是不响应的。

10、bool QGraphicsItem::acceptHoverEvents () const

如果可以接受鼠标悬浮在他上面的事件,就返回真,否则返回假。默认也是不接受该事件的。 同样的用于设置是否接受该事件的函数

void QGraphicsItem::setAcceptHoverEvents ( bool enabled ) 如果enabled为真,就接受,否则就不接受。

11、Qt::MouseButtons QGraphicsItem::acceptedMouseButtons () const

返回这个item所能接受的鼠标事件的鼠标键,默认的是所有的鼠标键事件都能接受。 同样的使用函数void QGraphicsItem:: setAcceptedMouseButtons ( Qt::MouseButtons buttons )来设置接受的鼠标键事件,如果想忽略某个鼠标键事件,可以用setAcceptedMouseButtons(0)

12、void QGraphicsItem::advance ( int phase ) [virtual]

这个虚函数被QGraphicsScene::advance()调用两次,第一次调用,所有的items都调用,使用参数phase=0,表示场景中所有的items都将advance(前进),然后所有的items都将调用,使用参数phase=1,重写这个函数,可以来刷新你的item,如果你需要简单的场景控制动画。

默认的该函数什么事都不做

如果想写动画,可以使用两种方法,一个使用QGraphicsItemAnimation,,或多重继承Qobject和QgraphicsItem,然后使用QObject::startTimer() 和 QObject::timerEvent().来使item成动画。

13、QList QGraphicsItem::childItems () const

返回孩子item的一个链表,这些items按照栈顺序排列,考虑了item的插入顺序和Z-values 14、QRectF QGraphicsItem::childrenBoundingRect () const

返回这个item的所有子孙items的本地坐标系统轮廓矩形。这个矩形包括了这个item所有的子孙item,如果这个item不含有子孙item,这个函数将返回一个空的矩形。

返回的矩形不包括item本身的轮廓矩形,只返回子孙item的矩形轮廓,如果你想包含item本身的矩形区域,可以使用QRectF::operator|()把boundingRect()和hildrenBoundingRect()或起来。

这个函数很复杂,它决定了返回轮廓的大小通过重复所有子孙item 15、void QGraphicsItem::clearFocus ()

去除item的光标,如果原来有光标焦点,当焦点失去时候,事件focus out event会发送给这个item,提示他将会失去焦点。

Item只有设置了ItemsFocusable属性,或者widget设置了合适的焦点策略,才能接受键盘焦点。

16、bool QGraphicsItem::collidesWithItem ( const QGraphicsItem * other, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape ) const [virtual] 如果这个item和另一个item碰撞就返回真,mode是应用于其他item的,默认是Qt::IntersectsItemShape,如果其他的item和这个item相互影响或者包含,被包含于这个item的形状(详见Qt::ItemSelectionMode)。

默认的函数是就基于外形相互影响,它调用两个item的shape()函数,这将会花费很大时间,你可以在QgraphicsItem子类中重写这个函数,提供一个简单的算法。这样你可以使用自己item的一些参数,这样可以提高碰撞侦测的效果。例如,两个完全没有转换的圆item的碰撞可以通过对比他们的圆心位置和半径

17、bool QGraphicsItem::collidesWithPath ( const QPainterPath & path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape ) const [virtual] 如果item按照path碰撞就返回真,

18、QList QGraphicsItem::collidingItems ( Qt::ItemSelectionMode mode = Qt::IntersectsItemShape ) const 返回和这个item相互碰撞的item的链表 碰撞侦测模式取决于mode,

19/ QGraphicsItem * QGraphicsItem::commonAncestorItem ( const QGraphicsItem * other ) const

返回item最近的祖先item,如果other为0,或者没有祖先item,就返回0 20、bool QGraphicsItem::contains ( const QPointF & point ) const [virtual]

如果item包含了点point就返回TRUE,否则返回FALSE,最常用的是在QgraphicsView中调用,来判断这个item是否在光标下面,如果要重写这个函数,那就尽可能的简单。默认的这个函数调用的shape()函数

21、void QGraphicsItem::contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ) [virtual protected]

右键菜单事件,可以在子类中重写这个函数,event里面包含了事件要具体处理的数据。 如果忽略这个事件,调用函数QEvent::ignore(),事件event将会被传播到任何在该item之下的items,如果没有item响应这个事件,那么场景就忽略这个事件,传递给view视图 通常是响应该事件打开一个右键菜单,例如

void CustomItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {

QMenu menu;

QAction *removeAction = menu.addAction(\ QAction *markAction = menu.addAction(\

QAction *selectedAction = menu.exec(event->screenPos()); // ... }

默认是忽略该事件。

22、QVariant QGraphicsItem::data ( int key ) const

以Qvariant的格式返回item中的数据,当前的item数据对存储任意数据很有用,例如

static const int ObjectName = 0;

QGraphicsItem *item = scene.itemAt(100, 50); if (item->data(ObjectName).toString().isEmpty()) { if (qgraphicsitem_cast(item)) item->setData(ObjectName, \ }

void QGraphicsItem::setData ( int key, const QVariant & value ) 用来设置item的数据

23、QTransform QGraphicsItem::deviceTransform ( const QTransform & viewportTransform ) const

返回item设备的转换矩阵,使用viewportTransform来从场景到设备影射坐标,这个矩阵可以用来从这个item本地坐标到视图口坐标系统映射坐标或者几何图形,如果要映射视图口坐标到本地坐标,首先应该转换返回的这个矩阵。

QGraphicsRectItem rect; rect.setPos(100, 100);

rect.deviceTransform(view->viewportTransform()).map(QPointF(0, 0));

// returns the item's (0, 0) point in view's viewport coordinates

rect.deviceTransform(view->viewportTransform()).inverted().map(QPointF(100, 100));

// returns view's viewport's (100, 100) coordinate in item coordinates

这个函数是结合了到场景的转换和到视图的转换,设备转换可以用来对那些没有进行转换坐标的item计算碰撞。 24、拖拽类函数

void QGraphicsItem::dragEnterEvent ( QGraphicsSceneDragDropEvent * event ) [virtual protected]

void QGraphicsItem::dragLeaveEvent ( QGraphicsSceneDragDropEvent * event ) [virtual protected]

void QGraphicsItem::dragMoveEvent ( QGraphicsSceneDragDropEvent * event ) [virtual protected]

void QGraphicsItem::dropEvent ( QGraphicsSceneDragDropEvent * event ) [virtual protected]

25、qreal QGraphicsItem::effectiveOpacity () const 返回item的有效透明度,这个数值在0.0~~1.0之间

同样的可以用函数void QGraphicsItem::setOpacity ( qreal opacity )来设置透明度, 默认的子item继承父item的透明度

同样可以设置item的属性QGraphicsItem::ItemIgnoresParentOpacity 来忽略父item的透明度对自己的影响

设置子item的属性QGraphicsItem::ItemIgnoresTransformations来忽略视图转换(放大,缩小)等操作对自己的影响,在显示文本时候很有用。

26、void QGraphicsItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * event ) [virtual protected]

void QGraphicsItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ) [virtual protected]

void QGraphicsItem::hoverMoveEvent ( QGraphicsSceneHoverEvent * event ) [virtual protected]

鼠标悬浮事件

27、void QGraphicsItem::mouseDoubleClickEvent ( QGraphicsSceneMouseEvent * event ) [virtual protected]

void QGraphicsItem::mouseMoveEvent ( QGraphicsSceneMouseEvent * event ) [virtual protected]

void QGraphicsItem::mousePressEvent ( QGraphicsSceneMouseEvent * event ) [virtual protected]

void QGraphicsItem::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ) [virtual protected] 鼠标双击,移动,释放的事件

28、QPointF QGraphicsItem::mapFromItem ( const QGraphicsItem * item, const QPointF & point ) const

QPolygonF QGraphicsItem::mapFromItem ( const QGraphicsItem * item, const QRectF & rect ) const

QPainterPath QGraphicsItem::mapFromItem ( const QGraphicsItem * item, const QPainterPath & path ) const

QPolygonF QGraphicsItem::mapFromItem ( const QGraphicsItem * item, qreal x, qreal y, qreal w, qreal h ) const

QPointF QGraphicsItem::mapFromItem ( const QGraphicsItem * item, qreal x, qreal y ) const

QPointF QGraphicsItem::mapFromParent ( const QPointF & point ) const QPolygonF QGraphicsItem::mapFromParent ( const QRectF & rect ) const QPolygonF QGraphicsItem::mapFromParent ( const QPolygonF & polygon ) const QPainterPath QGraphicsItem::mapFromParent ( const QPainterPath & path ) const QPolygonF QGraphicsItem::mapFromParent ( qreal x, qreal y, qreal w, qreal h ) const

QPointF QGraphicsItem::mapFromParent ( qreal x, qreal y ) const QPointF QGraphicsItem::mapFromScene ( const QPointF & point ) const QPolygonF QGraphicsItem::mapFromScene ( const QRectF & rect ) const QPolygonF QGraphicsItem::mapFromScene ( const QPolygonF & polygon ) const QPainterPath QGraphicsItem::mapFromScene ( const QPainterPath & path ) const QPolygonF QGraphicsItem::mapFromScene ( qreal x, qreal y, qreal w, qreal h ) const QPointF QGraphicsItem::mapFromScene ( qreal x, qreal y ) const

QRectF QGraphicsItem::mapRectFromItem ( const QGraphicsItem * item, const QRectF & rect ) const

QRectF QGraphicsItem::mapRectFromItem ( const QGraphicsItem * item, qreal x, qreal y, qreal w, qreal h ) const 。。。。。。。。。。太多了 转换矩阵函数

29、void QGraphicsItem::moveBy ( qreal dx, qreal dy )

向x,y方向上移动dx,dy的距离,等价于调用setPos(pos()+QpointF(dx,dy)) 30/最重要的一个函数

void QGraphicsItem::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ) [pure virtual]

这个函数通常被view调用,然后再本地坐标系统中绘制item的内容 31、qreal QGraphicsItem::rotation () const 返回item的旋转度,

设置旋转度函数使用setRotation(),

32、qreal QGraphicsItem::scale () const 返回缩放系数

设置缩放使用setScale()

33、bool QGraphicsItem::sceneEvent ( QEvent * event ) [virtual protected] 截获事件,在事件没有分发给各个具体的事件处理函数之前。 相当于bool QObject::event ( QEvent * e ) [virtual]

34、void QGraphicsItem::scroll ( qreal dx, qreal dy, const QRectF & rect = QRectF() ) 滚动item

35、在使item能响应一些事件之前,需要先使能这个功能,例如 void QGraphicsItem::setAcceptDrops ( bool on )

如果on为真,那么就使能拖拽,否则将会忽略拖拽事件。默认是不接受的 void QGraphicsItem::setAcceptHoverEvents ( bool enabled ) 如果on为真,使能鼠标悬浮事件。默认不接受该事件。 void QGraphicsItem::setAcceptTouchEvents ( bool enabled ) 在一些支持触摸的设备上,这个函数将使能触摸事件。 36、void QGraphicsItem::setEnabled ( bool enabled ) 使该item有效,如果enabled为假,则该item不能用了

37、void QGraphicsItem::setGraphicsEffect ( QGraphicsEffect * effect )、 设置item的效果,可以用模糊效果,印象效果,给定颜色绘制效果,透明效果等 详细的可以参见QgraphicsEffect类 38、const int QGraphicsItem::Type

返回该item的类型值,这个值是自己通过定义Type的值,然后使用type()虚函数来返回的,看例子

class QGraphicsPathItem : public QAbstractGraphicsShapeItem { public:

enum { Type = 2 };

int type() const { return Type; } ... };

39、T qgraphicsitem_cast ( QGraphicsItem * item )

如果item是T类型的,把item转换成T类型的item,如果失败,则返回0 如果想让他正确的工作,需要重新实现函数type()来进行判断

会陆陆续续把QGraphicsView QGraphicsScene等于视图框架有关的类的翻译拿出来