Qt 之 QGraphicsItemGroup

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt 之 QGraphicsItemGroup相关的知识,希望对你有一定的参考价值。

参考技术A 参考 QGraphicsItemGroup

QGraphicsItemGroup 类提供了一个容器,该容器将一组项目视为单个项目。

QGraphicsItemGroup 是一种特殊类型的复合项,它会将自身及其所有子项视为一个项(即,所有子项的所有事件和几何都合并在一起)。当用户希望将几个较小的 item 分组为一个大 item 时,通常在演示工具中使用 item 组,以简化 item 的移动和复制。

如果只想将 item 存储在其他项目中,则可以通过将合适的父级传递给 setParentItem() 来直接使用任何 QGraphicsItem 。

QGraphicsItemGroup 的 boundingRect() 函数返回项目组中所有项目的边界矩形。 QGraphicsItemGroup 忽略其子项上的 ItemIgnoresTransformations 标志(即,相对于组项的几何形状,将子项视为可变形的)。

有两种构造项目组的方法。最简单,最常见的方法是将项目列表(例如所有选定的项目)传递给 createItemGroup() ,该列表将返回新的 QGraphicsItemGroup 项目。另一种方法是手动构造 QGraphicsItemGroup 项,然后调用 addItem() 将其添加到场景中,然后通过调用 addToGroup() 一次将项手动添加到组中。要拆除(“取消分组”) item 组,可以调用 destroyItemGroup() ,也可以通过调用 removeFromGroup() 手动从组中删除所有 item。

与调用 setParentItem() (仅保留子项的父项相对位置和转换)相反,添加和删除项的操作将保留项的场景相对位置和转换。

addtoGroup() 函数可将目标项目重新添加到该项目组,从而使项目相对于场景的位置和变换保持完整。从视觉上看,这意味着通过 addToGroup() 添加的项目将由于此操作而保持完全不变,而不管该项目或组的当前位置或转换如何;尽管该 item 的位置和 rect 可能会发生变化。

removeFromGroup() 函数的语义与 setParentItem() 相似,它将项目作为项目组的父项目。与 addToGroup() 一样,项目的场景相对位置和变换保持不变。

如何设置 QGraphicsItemGroup 的显示范围?

【中文标题】如何设置 QGraphicsItemGroup 的显示范围?【英文标题】:How can I set the display range of a QGraphicItemGroup? 【发布时间】:2017-12-25 23:54:32 【问题描述】:

我有一个 QGraphicsItemGroup 聚合了几个子项,我只想显示组的一部分。(不是子项的数量,区域)。就像这里的图片一样。

我要显示显示区域。

为此,我尝试了覆盖 QGraphicsItemGroup::boundingRect()。然而,什么都没有发生。我在 QT 文档中找到了这个,也许这就是为什么不起作用的原因。

QGraphicsItemGroup 的 boundingRect() 函数返回项目组中所有项目的边界矩形。

另外,我知道我可以更改 QGraphicsView 的大小以使其正常工作。但是我把 View 作为 CentralWidget,因为我还需要在 View 中显示其他对象,所以我不能改变 View 的大小。

如何设置 QGraphicItemGroup 的显示范围?

【问题讨论】:

【参考方案1】:

要执行此任务,我们可以通过返回定义可见区域的QPainterPath 来覆盖shape(),以便它传播到它的孩子,我们启用标志ItemClipsChildrenToShape

class GraphicsItemGroup: public QGraphicsItemGroup
public:
    GraphicsItemGroup(QGraphicsItem * parent = 0):QGraphicsItemGroup(parent)
        setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
    
    QPainterPath shape() const
    
        if(mShape.isEmpty())
            return QGraphicsItemGroup::shape();
        return mShape;
    
    void setShape(const QPainterPath &shape)
        mShape = shape;
        update();
    

private:
    QPainterPath mShape;
;

例子:

int main(int argc, char *argv[])

    QApplication a(argc, argv);
    QWidget w;
    w.setLayout(new QVBoxLayout);

    QGraphicsView view;
    QPushButton button("click me");

    w.layout()->addWidget(&view);
    w.layout()->addWidget(&button);

    view.setScene(new QGraphicsScene);
    GraphicsItemGroup group;
    view.scene()->addItem(&group);
    auto ellipse = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
    ellipse->setBrush(Qt::red);
    auto rect = new QGraphicsRectItem(QRect(150, 150, 100, 100));
    rect->setBrush(Qt::blue);
    group.addToGroup(ellipse);
    group.addToGroup(rect);

    QObject::connect(&button, &QPushButton::clicked, [&group]()
        QPainterPath shape;
        if(group.shape().boundingRect() == group.boundingRect())
            shape.addRect(0, 50, 250, 150);
        
        group.setShape(shape);
    );

    w.show();
    return a.exec();

输出:

完整的例子可以在下面的link找到。

【讨论】:

非常感谢!这就是我想要的!就一个问题。据我所知,QGraphicItem.shape() 似乎类似于 boundingRect()。就我而言,为什么 boundingRect 不起作用但 shape() 起作用? boundingRect(): ... 将项目的外边界定义为矩形;所有绘画都必须限制在项目的边界矩形内。 QGraphicsView 使用它来确定项目是否需要重绘。 shape():将此项的形状作为本地坐标中的 QPainterPath 返回。该形状用于许多事情,包括碰撞检测、命中测试和 QGraphicsScene::items() 函数。默认实现调用 boundingRect() 来返回一个简单的矩形形状,但是子类可以重新实现这个函数来为非矩形项返回一个更准确的形状。例如,圆形项目可能会选择返回椭圆形以更好地检测碰撞。 ,也就是说,第一个定义在哪里绘制,另一个定义什么是可见的。 :P 非常感谢!

以上是关于Qt 之 QGraphicsItemGroup的主要内容,如果未能解决你的问题,请参考以下文章

QT之二级菜单(二级菜单的箭头可以使用QSS设置图片)

Qt 之 QImage

Qt 之 QBitmap

Qt添加驱动——Qt数据库之添加MySQL驱动插件

Qt动画窗口,Qt之对话框消失动画

Qt-Qt之雷达扫描效果-No25-QtRadar