c++ 如何将多行附加到单个QGraphicsPixmapItem?

jhkqcmku  于 2023-06-07  发布在  其他
关注(0)|答案(1)|浏览(129)

目前,我用一条线连接两个QGraphicsPixmapItem,并能够移动它们,但是当我添加第三个QGraphicsPixmapItem并尝试将其连接到其中一个时,它会破坏前一条连接线。
以下是我的当前代码:

#include <QApplication>

#include <QGraphicsScene>

#include <QGraphicsView>

#include <QGraphicsPixmapItem>

#include <QGraphicsLineItem>

#include <QPixmap>

class CustomElipse : public QGraphicsPixmapItem

{

public:

    CustomElipse (const QPixmap& pixmap) : QGraphicsPixmapItem(pixmap) {

        setFlag(QGraphicsItem::ItemIsMovable);

        setFlag(QGraphicsItem::ItemSendsScenePositionChanges);

    }

    void addLine(QGraphicsLineItem *line, bool isPoint1) {

        this->line = line;

        isP1 = isPoint1;

    }

    QVariant itemChange(GraphicsItemChange change, const QVariant &value)

    {

        if (change == ItemPositionChange && scene()) {

            // value is the new position.

            QPointF newPos = value.toPointF();

            moveLineToCenter(newPos);

        }

        return QGraphicsItem::itemChange(change, value);

    }

    void moveLineToCenter(QPointF newPos) {

        int xOffset = pixmap().rect().x() + pixmap().width()/2;

        int yOffset = pixmap().rect().y() + pixmap().height()/2;

        QPointF newCenterPos = QPointF(newPos.x() + xOffset, newPos.y() + yOffset);

        // Move the required point of the line to the center of the elipse

        QPointF p1 = isP1 ? newCenterPos : line->line().p1();

        QPointF p2 = isP1 ? line->line().p2() : newCenterPos;

        line->setLine(QLineF(p1, p2));

    }

private:

    QGraphicsLineItem *line;

    bool isP1;

};

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

{

    QApplication a(argc, argv);

    QGraphicsScene scene;

    CustomElipse *elipse1 = new CustomElipse(QPixmap(":green.png"));

    scene.addItem(elipse1);

    CustomElipse *elipse2 = new CustomElipse(QPixmap(":green.png"));

    scene.addItem(elipse2);

 CustomElipse *elipse3 = new CustomElipse(QPixmap(":green.png"));

    scene.addItem(elipse3);

    QGraphicsLineItem *line = scene.addLine(QLineF(40, 40, 80, 80));

    elipse1->addLine(line, true);

    elipse2->addLine(line, false);

    elipse3->addLine(line,false);

    QGraphicsView view(&scene);

    view.show();

    return a.exec();

}

我试着创建一条新的线,并像前一条一样连接它。我知道它覆盖了前一行,但保存它也不是一个好主意,因为一个项目可能指向100个其他项目。

QGraphicsLineItem *line1 = scene.addLine(QLineF(40, 40, 80, 80));
elipse3->addLine(line,true);
elipse2->addLine(line,false);
mcvgt66p

mcvgt66p1#

您的CustomElipse一次只能连接一行,因此添加第二行将使其与任何其他连接到它的行分离。
您需要考虑的是允许您的项目处理附加到多个行的情况,因此可以使用行列表而不是QGraphicsLineItem *line;bool isP1;也是如此。
这导致您的代码需要进行必要的更改,以便将行移动到其中心方法,因此它将处理附加到它的所有行,这需要一个遍历行列表的简单循环。

class CustomElipse : public QGraphicsPixmapItem
{
public:
    CustomElipse (const QPixmap& pixmap) : QGraphicsPixmapItem(pixmap)
    {
        setFlag(QGraphicsItem::ItemIsMovable);
        setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
    }

    void addLine(QGraphicsLineItem *line, bool isPoint1)
    {
        //instead of replacing the line
        //make it append it to the previous ones
        this->line->append(line);

        //append the bool that matches the line appended
        isP1.append(isPoint1);
    }

    QVariant itemChange(GraphicsItemChange change, const QVariant &value)
    {
        if (change == ItemPositionChange && scene())
        {
            // value is the new position.
            QPointF newPos = value.toPointF();

            moveLineToCenter(newPos);
        }

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

    void moveLineToCenter(QPointF newPos)
    {
        int xOffset = pixmap().rect().x() + pixmap().width()/2;
        int yOffset = pixmap().rect().y() + pixmap().height()/2;
        QPointF newCenterPos = QPointF(newPos.x() + xOffset, newPos.y() + yOffset);

        // Move the required point of the line to the center of the elipse
        //A simple loop to iterate through the list of lines and isP1 bool
        for(int i = 0; i < line->size(); i++)
        {
            QPointF p1 = isP1.at(i) ? newCenterPos : line->at(i)->line().p1();
            QPointF p2 = isP1.at(i) ? line->at(i)->line().p2() : newCenterPos;
            line->at(i)->setLine(QLineF(p1, p2));
        }
    }

private:
    //a list instead of a single line 
    QList<QGraphicsLineItem *> *line = new QList<QGraphicsLineItem *>;
    //same for isP1
    QList<bool> isP1;
};

int main(int argc,char*argv[])
{
    QApplication a(argc, argv);
    
    QGraphicsScene scene;

    CustomElipse *elipse1 = new CustomElipse(QPixmap(":green.png"));
    scene.addItem(elipse1);

    CustomElipse *elipse2 = new CustomElipse(QPixmap(":green.png"));
    scene.addItem(elipse2);

    CustomElipse *elipse3 = new CustomElipse(QPixmap(":green.png"));
    scene.addItem(elipse3);

    CustomElipse *elipse4 = new CustomElipse(QPixmap(":green.png"));
    scene.addItem(elipse4);

    QGraphicsLineItem *line = scene.addLine(QLineF(40, 40, 80, 80));

    QGraphicsLineItem *line1 = scene.addLine(QLineF(80, 80, 120, 120));

    QGraphicsLineItem *line2 = scene.addLine(QLineF(80, 80, 120, 120));

    QGraphicsLineItem *line3 = scene.addLine(QLineF(80, 80, 120, 120));

    //only one item can be the first point of a line
    //so one item uses true, the second must use false
    elipse1->addLine(line, true);
    elipse1->addLine(line1, true);

    elipse2->addLine(line, false);
    elipse2->addLine(line2,false);

    elipse3->addLine(line1,false);
    elipse3->addLine(line2,true);
    elipse3->addLine(line3,true);

    elipse4->addLine(line3,false);

    QGraphicsView view(&scene);

    view.show();

    return a.exec();
}

结果如下:

相关问题