JefferyZhou

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

QT4.4以后的版本(包括4.4)

QT的Scene布局系统,主要构成如下图所示:

Image(133)

  • QGraphicsWidget 通过  QGraphicsWidget::setLayout() 来绑定 QGraphicsLayout
  • 当 Widget 发生 resized 事件的时候,layout自动对widget的孩子进行相应的排列。
  • 因为 QGraphicsLayout 是从 QGraphicsLayoutItem继承来的,所以QGraphicsLayout能够被其他的QGraphicsLayout以及子类进行排列

当前文本中专有名词:

layout                      :布局

geometry                 : 物理形状,物理大小

size hint                   : 类似 geometry, 说明的是UI 的大小信息

item                         : 项目layout中用来排序和布局的单元


layout所属widget      : Widget A 通过接口setLayout(B)绑定  Layout B后,A就是B所属的widget       

QT 建议使用现成的三个布局类来处理日常的工作任务,

如果有需求需要实现自定义的布局类,从 QGraphicsLayout继承,并且需要实现如下的几个接口:

函数:
描述:
备注:

public: virtual void setGeometry(const QRectF &rect);

当 layout的 geometry被设置的时候调用,在自定义layout类的重载实现中可以在函数中保存geometry.

protected: virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const = 0;

返回layout的 size hint(大小预估值)

public: virtual int count() const = 0;

返回layout中item的个数

public: virtual QGraphicsLayoutItem *itemAt(int  index) const = 0;
返回layout中指向索引 index 位置的 item 指针

public: virtual void removeAt(int index) = 0;

从layout中移除index位置的item, 但不摧毁相应的item

布局排版方式:

当layout的geometry变化的时候,layout会立刻重新排版,对layout管理的所有item调用接口setGeometry(),这种重新排版叫做“activing”布局。layout的排版会使得自己的geometry匹配到当前QGraphicsLayoutItem::contentsRect()所管理的区域,QGraphicsLayout会缓存所有它管理的item的大小,避免频繁调用setGeometry()。

布局排版激活方式:

通常有两种方式来激活layout的排版动作,通过调用activate()或者调用invalidate()。区别如下:

用 activate()方式激活的排版会立刻生效,用invalidate()方式是延迟排版的,因为它是通过抛一个LayoutRequest 事件给当前管理的widget,invalidate()同时会清空相关的cache。注意:invalidate()是个虚函数,用户可以重定义它的行为。

layout的事件处理:

QGraphicsLayout 通过接口  virtual void widgetEvent(QEvent *e);监听layout当前管理的widget的事件,widget的事件会先送到QGraphicsLayout进行处理。

layout的构造:

构造一个QGraphicsLayout :

QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutItem *parent)

parent会被传递给,QGraphicsLayoutItem,并且QGraphicsLayoutItem的 isLayout的标志被设置为true,

如果 parent 是一个 QGraphicsWidget, 则当前的 layout 会被 绑定到 parent代表的 Widget 上(Widget上原来的layout会被delete掉)。

成员函数表:

函数:
说明:

void QGraphicsLayout::activate ()
激活layout, 导致 layout 中的所有item立刻重排,对每个item顺序调用setGeometry(),使得layout 管理的所有item 所占区域匹配layout当前属的widget的contensRect(). 注意 layout 属的 widget 也是 layout 的parent.
当前函数依赖 count() 和 itemAt(),
在顺序或者递归调用 activate()的时候,activate 不做任何事情。比如在相应resized,导致的items重排的时候触发activate。
注意layout 会充分利用缓存的几何数据来优化排版过程,要强制性清空这些缓存的话,可以在activate之前调用 invalidate()

void QGraphicsLayout::addChildLayoutItem ( QGraphicsLayoutItem * layoutItem ) [protected]
这个函数是提供给制作自定义layout类时候的一个非常方便的工具函数,这个函数会遍历layoutItem (当layoutItem本身是一个layout的时候)中所有的item,并且重新定位item的parent为当前layout的最近的QGraphicsWidget。
如果layoutItem已经在另外一个layout中,也回把layoutItem从原layout移除。
如果自定义的layout类想要特殊的行为,可以重载当前函数。
这个函数由Qt 4.6 引入

int QGraphicsLayout::count () const [pure virtual]
纯虚函数,子类必须实现。

void QGraphicsLayout::getContentsMargins ( qreal * left, qreal * top, qreal * right, qreal * bottom ) const [virtual]
重载 QGraphicsLayoutItem::getContentsMargins().

void QGraphicsLayout::invalidate () [virtual]
清空 Geometry 缓存,清空 size hint 缓存,并 post 一个 LayoutRequest 事件到layout所属的widget

bool QGraphicsLayout::isActivated () const
如果layout当前正处理activated 中,返回true,否则返回false。
正处在activated中,意思就是调用activated还没用返回。
Note: 有效防止递归中调用activated导致的死锁问题。

QGraphicsLayoutItem * QGraphicsLayout::itemAt ( int i ) const [pure virtual]
纯虚函数,子类必须实现。
返回索引 i 代表的item的指针。
这个函数加上cout()等于提供了一套layout的迭代访问方法。
子类可以完全自主的决定 i 与 item 的对应关系,和视觉上的 item 排列没用必然联系

void QGraphicsLayout::removeAt ( int index ) [pure virtual]
纯虚函数,子类必须实现。重载实现中,需要根据count()的数量判断index的有效性。
在重载实现中,必须保证,被移除的item的parentLayoutItem()不再指向当前layout,因为这个函数就是用来把item从layout层次树上移除的。
如果移除item的layout还要被再次利用,我们建议在移除item的时候,同事对item指针delete操作。当然graphics view 框架本身并没用依赖这一特性。

void QGraphicsLayout::setContentsMargins ( qreal left, qreal top, qreal right, qreal bottom )
设置内容的边距,默认的边距取决于当前stype的定义,通过pixelMetric查询QStyle::PM_LayoutLeftMargin, QStyle::PM_LayoutTopMargin, QStyle::PM_LayoutRightMargin and QStyle::PM_LayoutBottomMargin可以得到定义的默认值。
对于下级layout,默认的边距为0.
变更内容的边距会倒在layout调用invalidate

void QGraphicsLayout::updateGeometry () [virtual]
重载实现QGraphicsLayoutItem::updateGeometry().

void QGraphicsLayout::widgetEvent ( QEvent * e ) [virtual]
虚函数,事件处理接口,会接收到layout所属的widget的所有事件。 QGraphicsLayout用这个事件处理接口,监听layout关心的widget事件,比如widget的geometry变更,layout 变更,layout方向变更等。
e 是事件指针。
你可以重载这个接口,实现自定义布局类

posted on 2012-09-24 17:11  JefferyZhou  阅读(2938)  评论(0编辑  收藏  举报