Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Drag and drop issue - dragged element teleports to 0,0 when begginning to drag, then follows normally
Forum Updated to NodeBB v4.3 + New Features

Drag and drop issue - dragged element teleports to 0,0 when begginning to drag, then follows normally

Scheduled Pinned Locked Moved Unsolved General and Desktop
1 Posts 1 Posters 127 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Desfell
    wrote on last edited by
    #1

    Hello there, title says it all. I am an absolute beginner in Qt and I am struggling to resolve a bug I have stumbled upon. I have a list of nodes and they should exchange positions when dragged over one another. They do that except, when beginning to drag, the node snaps to position 0,0 and then in that offset drags along with the mouse. I only have one function which takes care of positioning them (RefreshNodePositions()) - I have checked and it does not execute when this bug happens, so I do not know what could cause it.
    I am lost on how to find the root of issue. Any advice much appreciated!
    This is the "canvas" which holds the nodes

    #include "sequenceeditorwidget.h"
    #include "ui_sequenceeditorwidget.h"
    #include "sequencediagramnodeview.h"
    #include <QKeyEvent>
    #include <QKeySequence>
    #include <QMessageBox>
    SequenceEditorWidget::SequenceEditorWidget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::SequenceEditorWidget)
    {
        ui->setupUi(this);
        QObject::connect(
                    ui->addObject_button, &QPushButton::clicked,
                    this, &SequenceEditorWidget::onAddObject);
    
        scene = new QGraphicsScene(ui->sequenceGraphicsView);
        ui->sequenceGraphicsView->setScene(scene);
        ui->sequenceGraphicsView->setDragMode(QGraphicsView::RubberBandDrag);
        ui->sequenceGraphicsView->setRenderHints(QPainter::Antialiasing
                                             |QPainter::TextAntialiasing);
        ui->sequenceGraphicsView->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    }
    
    SequenceEditorWidget::~SequenceEditorWidget()
    {
        delete ui;
    }
    
    void SequenceEditorWidget::ChangeNodeName(const QString &name, int nodeID)
    {
        for(int i = 0; i < diagramNodes.length(); i++)
        {
            if(diagramNodes[i]->nodeId == nodeID)
            {
                diagramNodes[i]->model->setName(name);
                RefreshNodePositions();
                break;
            }
        }
    }
    
    int SequenceEditorWidget::getIndexOfNodeAtPos(QPointF pos)
    {
        if(diagramNodes.length() <= 1 || pos.x() <= 0)
        {
            return 0;
        }
    
        for(int i = 0; i < diagramNodes.length() - 1; i++)
        {
            if(pos.x() > diagramNodes[diagramNodes.length() - 1]->getSlotPosition().x())
            {
                return diagramNodes.length() - 1;
            }
            else if(pos.x() < 0)
            {
                return 0;
            }
            if(pos.x() >= diagramNodes[i]->getSlotPosition().x() && pos.x() < diagramNodes[i+1]->getSlotPosition().x())
            {
                return i;
            }
        }
        return -1;
    }
    
    int SequenceEditorWidget::getIndexOfNodeByID(int nodeID)
    {
        for(int i = 0; i < diagramNodes.length(); i++)
        {
                if(diagramNodes[i]->nodeId == nodeID)
                {
                    return i;
                }
        }
        return -1;
    }
    
    
    void SequenceEditorWidget::putNodeAtPos(QPointF pos, int nodeID)
    {
        int firstNodeIndex = getIndexOfNodeByID(nodeID);
        int secondNodeIndex = getIndexOfNodeAtPos(pos);
        QMessageBox::information(this, QString::number(firstNodeIndex), QString::number(secondNodeIndex));
        diagramNodes.swapItemsAt(firstNodeIndex, secondNodeIndex);
        RefreshNodePositions();
    }
    
    void SequenceEditorWidget::RefreshNodePositions()
    {
        QMessageBox::information(nullptr, "EXECUTED", "EXECUTED");
        *posToPlaceNextNode = *posAnchorNode;
        for(int i = 0; i < diagramNodes.length(); i++)
        {
                diagramNodes[i]->setSlotPosition(posToPlaceNextNode);
                posToPlaceNextNode->setX(posToPlaceNextNode->x() + diagramNodes[i]->boundingRect().width() + 30);
        }
    }
    
    void SequenceEditorWidget::onAddObject()
    {
        SequenceDiagramNodeView* newNode = new SequenceDiagramNodeView(this, nodeIdCounter++, posToPlaceNextNode);
        diagramNodes.append(newNode);
        posToPlaceNextNode->setX(posToPlaceNextNode->x() + newNode->boundingRect().width() + 30);
        scene->addItem(newNode);
    }
    
    void SequenceEditorWidget::keyPressEvent(QKeyEvent* event)
    {
        if(event->key() == Qt::Key_Delete)
        {
            QList<QGraphicsItem *> selected = scene->selectedItems();
            QMutableListIterator<QGraphicsItem *> i(selected);
            for(int i = 0; i < scene->selectedItems().length(); i++)
            {
                QString typeOfObject = typeid(scene->selectedItems()[i]).name();
                {
                    if(typeOfObject.compare("SequenceDiagramNodeView*"))
                    {
                        SequenceDiagramNodeView* nodeToRemove = (SequenceDiagramNodeView*)scene->selectedItems()[i];
                        for (int j = 0; j < diagramNodes.length(); j++)
                        {
                            if(nodeToRemove->nodeId == diagramNodes[j]->nodeId)
                            {
                                diagramNodes.removeAt(j);
                            }
                        }
                    }
                }
            }
            qDeleteAll(selected);
    
            RefreshNodePositions();
        }
    }
    
    

    And this is the view of the node itself

    
    #include <QStyleOptionGraphicsItem>
    #include <QPen>
    #include <QPainter>
    
    #include "sequencediagramnodeview.h"
    #include "sequencediagramnodemodel.h"
    
    #include <QStyleOptionGraphicsItem>
    #include <QPen>
    #include <QPainter>
    
    SequenceDiagramNodeView::SequenceDiagramNodeView(QWidget *parent, int nodeID, QPointF* slotPos)
    {
        this->model = new SequenceDiagramNodeModel();
        this->nodeId = nodeID;
        model->setName(QString::number(nodeID));
        this->controller = new sequenceDiagramNodeController(parent);
        this->parent = parent;
        this->textColor = Qt::darkGreen;
        this->backgroundColor = Qt::white;
        this->outlineColor = Qt::darkBlue;
        this->slotPosition = *slotPos;
        this->setPos(this->slotPosition);
    
        setFlags(ItemIsMovable | ItemIsSelectable);
        setFlag(ItemSendsGeometryChanges);
    }
    
    QPointF SequenceDiagramNodeView::getSlotPosition()
    {
        return this->slotPosition;
    }
    
    void SequenceDiagramNodeView::setSlotPosition(QPointF* pos)
    {
        this->slotPosition = *pos;
        this->setPos(this->slotPosition);
    }
    
    SequenceDiagramNodeView::~SequenceDiagramNodeView()
    {
    
    }
    
    
    QRectF SequenceDiagramNodeView::boundingRect() const
    {
        const int Margin = 1;
        return getOutlineRect().adjusted(-Margin, -Margin, +Margin, +Margin);
    }
    
    void SequenceDiagramNodeView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
    {
        QPen pen(outlineColor);
        if (option->state & QStyle::State_Selected) {
            pen.setStyle(Qt::DotLine);
            pen.setWidth(2);
        }
    
        painter->setPen(pen);
        painter->setBrush(backgroundColor);
        QFontMetricsF metrics{qApp->font()};
    
        // Draw outline rect
        QRectF outlineRect = getOutlineRect();
        painter->drawRect(outlineRect);
        pen.setStyle(Qt::SolidLine);
    
        // Draw name
        QFont font = painter->font();
        font.setBold(true);
        painter->setFont(font);
        painter->setPen(textColor);
        painter->drawText(getTextRect(model->getName(), 0, 0), Qt::AlignLeft, model->getName());
        font.setBold(false);
        painter->setFont(font);
    }
    
    QRectF SequenceDiagramNodeView::getOutlineRect() const
    {
        const int PADDING = 8;
        QFontMetricsF metrics{qApp->font()};
    
        qreal width = metrics.boundingRect(model->getName()).width();
        qreal height = (metrics.height()) * 2;
    
        QRectF rect{0, -PADDING * 1.5, width, height}; // TODO: Why?
        rect.adjust(-PADDING, -PADDING, +PADDING, +PADDING);
    
        return rect;
    }
    
    void SequenceDiagramNodeView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
    {
        controller->createEditNameDialog(this->nodeId);
    }
    
    void SequenceDiagramNodeView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
    {
        // Get center of the node
        QPointF pos = this->scenePos() + this->boundingRect().center();
        controller->droppedNodeAtPos(pos, this->nodeId);
    }
    
    QRectF SequenceDiagramNodeView::getTextRect(QString text, qreal dx, qreal dy) const {
        const int PADDING = 2;
        QFontMetricsF metrics{qApp->font()};
        QRectF rect = metrics.boundingRect(text);
        rect.adjust(-PADDING, -PADDING, +2*PADDING, +PADDING);
        rect.translate(dx, dy);
        return rect;
    }
    
    
    1 Reply Last reply
    0

    • Login

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved