用QGraphicsRectItem创建一个矩形,右键点击这个矩形,可以将该矩形拆分成两个间隔10像素的矩形;且矩形的左右边框可以拖拽,当拖拽的区域发生重叠时,自动将两个矩形合并

用QGraphicsRectItem创建一个矩形,右键点击这个矩形,可以将该矩形拆分成两个间隔10像素的矩形;且矩形的左右边框可以拖拽,当拖拽的区域发生重叠时,自动将两个矩形合并

在以下示例中,我将提供一个简化的实现,展示如何在QGraphicsRectItem基础上实现矩形的拆分和合并。请注意,这个示例是为了教学目的而简化的,并且可能需要根据你的具体需求进行调整。

首先,我们定义一个DraggableRectItem类,继承自QGraphicsRectItem,并实现拆分和合并的逻辑。

#include <QGraphicsRectItem>  
#include <QGraphicsSceneMouseEvent>  
#include <QList>  
  
class DraggableRectItem : public QGraphicsRectItem {  
public:  
    DraggableRectItem(const QRectF &rect, QGraphicsItem *parent = nullptr)  
        : QGraphicsRectItem(rect, parent), isSplitting(false) {  
        setFlag(QGraphicsItem::ItemIsMovable);  
        setFlag(QGraphicsItem::ItemSendsGeometryChanges);  
        setFlag(QGraphicsItem::ItemIsFocusable);  
    }  
  
    void split(const QPointF &splitPoint) {  
        QRectF newRect1 = QRectF(rect().topLeft(), splitPoint - rect().topLeft());  
        QRectF newRect2 = QRectF(splitPoint, rect().bottomRight() - splitPoint);  
        newRect2.moveTopLeft(splitPoint + QPointF(10, 0)); // Add 10 pixels gap  
  
        DraggableRectItem *item1 = new DraggableRectItem(newRect1);  
        DraggableRectItem *item2 = new DraggableRectItem(newRect2);  
  
        item1->setPos(this->pos());  
        item2->setPos(this->pos() + QPointF(newRect1.width() + 10, 0));  
  
        scene()->addItem(item1);  
        scene()->addItem(item2);  
  
        scene()->removeItem(this);  
        delete this;  
    }  
  
    static void merge(DraggableRectItem *item1, DraggableRectItem *item2) {  
        QRectF mergedRect = item1->rect().united(item2->rect().translated(-item2->pos() + item1->pos()));  
        DraggableRectItem *mergedItem = new DraggableRectItem(mergedRect);  
        mergedItem->setPos(item1->pos());  
  
        item1->scene()->addItem(mergedItem);  
        item1->scene()->removeItem(item1);  
        item1->scene()->removeItem(item2);  
  
        delete item1;  
        delete item2;  
    }  
  
protected:  
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override {  
        if (event->button() == Qt::RightButton) {  
            isSplitting = true;  
            splitPoint = event->pos();  
        }  
        QGraphicsRectItem::mousePressEvent(event);  
    }  
  
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override {  
        if (isSplitting) {  
            // Here you could visually indicate the split by drawing a temporary line or rectangle  
        } else {  
            QGraphicsRectItem::mouseMoveEvent(event);  
        }  
    }  
  
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override {  
        if (isSplitting && event->button() == Qt::RightButton) {  
            split(splitPoint);  
        }  
        isSplitting = false;  
        QGraphicsRectItem::mouseReleaseEvent(event);  
    }  
  
private:  
    QPointF splitPoint;  
    bool isSplitting;  
};

在这个类中,我们实现了拆分矩形的功能:当用户在矩形上右键点击并释放时,矩形将在点击位置被拆分为两个新的矩形。拆分操作通过split函数完成,它创建了两个新的DraggableRectItem实例,并根据拆分点调整它们的大小和位置。

合并操作是通过静态函数merge实现的,它接受两个DraggableRectItem指针,创建一个新的矩形项来覆盖这两个矩形的并集区域,并删除原始的两个矩形。

请注意,这个示例没有处理矩形的拖拽功能以及自动检测重叠并合并的逻辑。拖拽功能可以通过设置QGraphicsRectItem的标志位来实现,而自动合并则需要更复杂的逻辑来检测重叠并在适当的时候调用merge函数。

为了实现自动合并,你可能需要在每个矩形的mouseMoveEvent中添加逻辑来检查它是否与其他矩形重叠,并在重叠时调用merge函数。这可能需要维护一个场景中所有矩形的列表,并在每次移动时更新这个列表。

此外,这个示例中的拆分和合并操作是硬编码的,可能需要根据你的应用程序的具体需求进行调整。例如,你可能需要添加更多的用户交互来确认拆分或合并操作,或者根据特定的业务规则来限制这些操作。

在以上的内容基础上,给出拆分和合并矩形的具体代码

在以下示例中,我将提供一个简化的实现,展示如何在QGraphicsRectItem基础上实现矩形的拆分和合并。请注意,这个示例是为了教学目的而简化的,并且可能需要根据你的具体需求进行调整。

首先,我们定义一个DraggableRectItem类,继承自QGraphicsRectItem,并实现拆分和合并的逻辑。

#include <QGraphicsRectItem>  
#include <QGraphicsSceneMouseEvent>  
#include <QList>  
  
class DraggableRectItem : public QGraphicsRectItem {  
public:  
    DraggableRectItem(const QRectF &rect, QGraphicsItem *parent = nullptr)  
        : QGraphicsRectItem(rect, parent), isSplitting(false) {  
        setFlag(QGraphicsItem::ItemIsMovable);  
        setFlag(QGraphicsItem::ItemSendsGeometryChanges);  
        setFlag(QGraphicsItem::ItemIsFocusable);  
    }  
  
    void split(const QPointF &splitPoint) {  
        QRectF newRect1 = QRectF(rect().topLeft(), splitPoint - rect().topLeft());  
        QRectF newRect2 = QRectF(splitPoint, rect().bottomRight() - splitPoint);  
        newRect2.moveTopLeft(splitPoint + QPointF(10, 0)); // Add 10 pixels gap  
  
        DraggableRectItem *item1 = new DraggableRectItem(newRect1);  
        DraggableRectItem *item2 = new DraggableRectItem(newRect2);  
  
        item1->setPos(this->pos());  
        item2->setPos(this->pos() + QPointF(newRect1.width() + 10, 0));  
  
        scene()->addItem(item1);  
        scene()->addItem(item2);  
  
        scene()->removeItem(this);  
        delete this;  
    }  
  
    static void merge(DraggableRectItem *item1, DraggableRectItem *item2) {  
        QRectF mergedRect = item1->rect().united(item2->rect().translated(-item2->pos() + item1->pos()));  
        DraggableRectItem *mergedItem = new DraggableRectItem(mergedRect);  
        mergedItem->setPos(item1->pos());  
  
        item1->scene()->addItem(mergedItem);  
        item1->scene()->removeItem(item1);  
        item1->scene()->removeItem(item2);  
  
        delete item1;  
        delete item2;  
    }  
  
protected:  
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override {  
        if (event->button() == Qt::RightButton) {  
            isSplitting = true;  
            splitPoint = event->pos();  
        }  
        QGraphicsRectItem::mousePressEvent(event);  
    }  
  
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override {  
        if (isSplitting) {  
            // Here you could visually indicate the split by drawing a temporary line or rectangle  
        } else {  
            QGraphicsRectItem::mouseMoveEvent(event);  
        }  
    }  
  
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override {  
        if (isSplitting && event->button() == Qt::RightButton) {  
            split(splitPoint);  
        }  
        isSplitting = false;  
        QGraphicsRectItem::mouseReleaseEvent(event);  
    }  
  
private:  
    QPointF splitPoint;  
    bool isSplitting;  
};

在这个类中,我们实现了拆分矩形的功能:当用户在矩形上右键点击并释放时,矩形将在点击位置被拆分为两个新的矩形。拆分操作通过split函数完成,它创建了两个新的DraggableRectItem实例,并根据拆分点调整它们的大小和位置。

合并操作是通过静态函数merge实现的,它接受两个DraggableRectItem指针,创建一个新的矩形项来覆盖这两个矩形的并集区域,并删除原始的两个矩形。

请注意,这个示例没有处理矩形的拖拽功能以及自动检测重叠并合并的逻辑。拖拽功能可以通过设置QGraphicsRectItem的标志位来实现,而自动合并则需要更复杂的逻辑来检测重叠并在适当的时候调用merge函数。

为了实现自动合并,你可能需要在每个矩形的mouseMoveEvent中添加逻辑来检查它是否与其他矩形重叠,并在重叠时调用merge函数。这可能需要维护一个场景中所有矩形的列表,并在每次移动时更新这个列表。

此外,这个示例中的拆分和合并操作是硬编码的,可能需要根据你的应用程序的具体需求进行调整。例如,你可能需要添加更多的用户交互来确认拆分或合并操作,或者根据特定的业务规则来限制这些操作。

请补充上重叠检测部分的代码 

要点

rect1.intersects(rect2)//这是判断矩形是否发生重叠的关键函数

内容

为了检测矩形是否重叠,我们可以在DraggableRectItem类中添加一个静态方法,该方法接受两个DraggableRectItem对象,并检查它们的矩形是否重叠。以下是一个示例实现:

static bool isOverlapping(DraggableRectItem *item1, DraggableRectItem *item2) {  
    QRectF rect1 = item1->rect().translated(item1->pos());  
    QRectF rect2 = item2->rect().translated(item2->pos());  
    return rect1.intersects(rect2);  
}

这个方法首先将每个矩形的位置与其自身的矩形合并,以获取其在场景中的绝对位置。然后,它使用QRectF::intersects()方法来检查这两个矩形是否重叠。

为了在实际应用中使用这个重叠检测,你可能需要在某个事件处理函数(如mouseMoveEvent)中调用它。例如,你可以在DraggableRectItem类中添加一个用于处理矩形移动的槽函数,并在其中检查重叠。

以下是一个可能的实现方式:

// 假设你有一个存储所有DraggableRectItem的列表itemsList  
QList<DraggableRectItem*> itemsList;  
  
// 在某个适当的位置(例如在scene的mouseMoveEvent中)  
void checkAndMergeOverlappingItems() {  
    for (int i = 0; i < itemsList.size(); ++i) {  
        DraggableRectItem *currentItem = itemsList.at(i);  
        for (int j = i + 1; j < itemsList.size(); ++j) {  
            DraggableRectItem *nextItem = itemsList.at(j);  
            if (DraggableRectItem::isOverlapping(currentItem, nextItem)) {  
                // 如果两个矩形重叠,则合并它们  
                DraggableRectItem::merge(currentItem, nextItem);  
                  
                // 从列表中移除已合并的项  
                itemsList.removeAll(currentItem);  
                itemsList.removeAll(nextItem);  
                  
                // 合并后可能需要重新检查重叠,或者退出循环以防止在已修改的列表上继续迭代  
                // 在这个简单的例子中,我们只是简单地退出循环  
                return;  
            }  
        }  
    }  
}

请注意,这个checkAndMergeOverlappingItems函数应该在你想要检查重叠的时候被调用,例如在场景的mouseMoveEvent中,或者通过定时器定期检查。此外,当矩形被合并后,你应该确保更新你的矩形列表,以防止对已删除对象的进一步引用。

这个简单的实现假设一旦找到重叠的矩形就立即合并它们,并且每次只合并一对重叠的矩形。在更复杂的应用场景中,你可能需要考虑一种更高效的算法来处理多个重叠的情况,或者添加额外的逻辑来确认合并操作。

另外,请确保在合并操作之后正确地管理内存和场景中的项目。在上面的merge方法中,我们删除了传入的两个DraggableRectItem对象,并创建了一个新的合并后的对象。这意味着任何对这些对象的外部引用都需要被更新或清除,以防止悬挂引用或内存泄漏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值