Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Qt mismatch of coordinates



  • Hello.
    I added a itemgroup (inherited from QObject and QGraphicsItemGroup) to the coordinates (25,0), then I added an ellipse to the coordinates (25, 0) and added a picture. (CanvasScene inherited from QGraphicsScene). I also drew the position of the group.

    Screenshot from 2021-04-24 10-49-51.png

    Why the coordinates of itemgroup and ellipse don't match? And why x-position of image equal to x-positon of itemgroup?

    main.cpp:

    #include "mainwindow.h"
    
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        return a.exec();
    }
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QGraphicsView>
    #include <QGraphicsItem>
    #include <QMouseEvent>
    //-----------------------------------------
    class MoveItem : public QObject, public QGraphicsRectItem
    {
        Q_OBJECT
        Q_INTERFACES(QGraphicsItem)
    public:
        MoveItem(const QString& path, uint64_t& zc, QGraphicsRectItem *parent = nullptr);
        ~MoveItem();
        QRectF boundingRect() const override;
    signals:
    protected:
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
    
    private:
        QImage qimage_;
        QPixmap pixmap_;
        QRectF rect_;
        uint64_t& zCounter_;
    };
    
    
    //-----------------------------------------
    class ItemGroup : public QObject, public QGraphicsItemGroup
    {
        Q_OBJECT
        Q_INTERFACES(QGraphicsItem)
    public:
        ItemGroup(uint64_t& zc, QGraphicsItemGroup *parent = nullptr);
        ~ItemGroup() = default;
    
    protected:
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
    private:
        uint64_t& zCounter_;
    };
    
    
    
    //-----------------------------------------
    class CanvasScene : public QGraphicsScene
    {
    public:
        CanvasScene(uint64_t& zc, QGraphicsScene *scene = 0);
        ~CanvasScene() = default;
    
    private:
        uint64_t& zCounter_;
        ItemGroup* itemGroup_ = nullptr;
    };
    
    
    //-----------------------------------------
    #define ZOOM_FACTOR 1.15
    class CanvasView : public QGraphicsView
    {
        Q_OBJECT
    public:
        CanvasView(QWidget* parent = 0);
        ~CanvasView();
    
        void addImage(const QString& path, QPointF point);
        void setZoomFactor(double factor) { zoomFactor_ = factor; }
    protected:
        void mouseMoveEvent(QMouseEvent* event) override;
        void mousePressEvent(QMouseEvent* event) override;
        void mouseReleaseEvent(QMouseEvent* event) override;
        void wheelEvent(QWheelEvent* event) override;
        void resizeEvent(QResizeEvent *event) override;
        virtual QString setToolTipText(QPoint imageCoordinates);
        void drawBackground(QPainter *painter, const QRectF &rect) override;
    private:
        CanvasScene* scene_;
        double zoomFactor_;
        bool pan_;
        bool panStartX_;
        bool panStartY_;
        uint64_t zCounter_ = 0;
    };
    
    
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
        CanvasView* canvasWidget;
    };
    #endif // MAINWINDOW_H
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "./ui_mainwindow.h"
    
    MoveItem::MoveItem(const QString& path, uint64_t& zc, QGraphicsRectItem *parent) :
        QGraphicsRectItem(parent), zCounter_(zc)
    {
        qimage_ = QImage(path);
        rect_ = qimage_.rect();
        setAcceptHoverEvents(true);
        setFlag(QGraphicsItem::ItemIsMovable, true);
    }
    
    MoveItem::~MoveItem() {}
    
    QRectF MoveItem::boundingRect() const
    {
        return QRectF (0, 0, rect_.width(), rect_.height());
    }
    
    void MoveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        painter->setPen(QPen(QColor(0, 160, 230),2));
        painter->drawImage(boundingRect(), qimage_);
    }
    
    //-----------------------------------------------
    ItemGroup::ItemGroup(uint64_t& zc, QGraphicsItemGroup *parent) :
        QGraphicsItemGroup(parent),
        zCounter_(zc)
    {
        setAcceptHoverEvents(true);
        setFlags(ItemIsSelectable|ItemSendsGeometryChanges);
    }
    
    
    void ItemGroup::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        painter->save();
        painter->setPen( QPen(Qt::green, 3) );
        painter->drawEllipse(this->pos(), 6,6);
        painter->setPen( QPen(Qt::darkMagenta, 3) );
        painter->drawEllipse(this->scenePos(), 3,3);
        painter->restore();
    }
    
    //-----------------------------------------------
    CanvasScene::CanvasScene(uint64_t& zc, QGraphicsScene *scene) : zCounter_(zc)
    {
        (void)scene;
        itemGroup_ = new ItemGroup(zc);
        itemGroup_->setHandlesChildEvents(true);
    
        QPointF p = {25,0};
        itemGroup_->setPos(p);
        addItem(itemGroup_);
    
        addEllipse(QRectF(25, 0, 3, 3), QPen(Qt::black), QBrush(Qt::green));
    
        ++zCounter_;
        MoveItem* item = new MoveItem("bender.png", zCounter_);
        item->setFlag(QGraphicsItem::ItemIsSelectable, true);
        item->setPos({50,50});
        addItem(item);
    }
    
    CanvasView::CanvasView(QWidget* parent) :
        QGraphicsView(parent)
    {
        zoomFactor_ = ZOOM_FACTOR;
        scene_ = new CanvasScene(zCounter_);
        setMouseTracking(true);
        setScene(scene_);
        setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
        setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
        setDragMode(QGraphicsView::RubberBandDrag);
        setResizeAnchor(QGraphicsView::AnchorViewCenter);
    }
    
    
    CanvasView::~CanvasView()
    {
        delete scene_;
    }
    
    
    void CanvasView::addImage(const QString& path, QPointF point)
    {
        ++zCounter_;
        MoveItem* item = new MoveItem(path, zCounter_);
        item->setFlag(QGraphicsItem::ItemIsSelectable, true);
        item->setPos(point);
        scene_->addItem(item);
    }
    
    
    void CanvasView::mouseMoveEvent(QMouseEvent *event)
    {
        if (pan_) {
            panStartX_ = event->position().x();
            panStartY_ = event->position().y();
            event->accept();
        }
        QGraphicsView::mouseMoveEvent(event);
    }
    
    
    void CanvasView::mousePressEvent(QMouseEvent *event)
    {
        if (event->button() == Qt::LeftButton) {
             pan_ = true;
             panStartX_ = event->position().x();
             panStartY_ = event->position().y();
             event->accept();
    
         }
        QGraphicsView::mousePressEvent(event);
    }
    
    
    void CanvasView::mouseReleaseEvent(QMouseEvent *event)
    {
        QGraphicsView::mouseReleaseEvent(event);
        if (event->button() == Qt::LeftButton) {
            pan_ = false;
            event->accept();
          }
    }
    
    void CanvasView::wheelEvent(QWheelEvent *event)
    {
        // When zooming, the view stay centered over the mouse
        this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    
        auto numPixels = event->angleDelta();
    //    qInfo()<<"CanvasView::wheelEvent: "<<numPixels.x()<<' '<<numPixels.y();
        double factor = zoomFactor_;//(event->modifiers() & Qt::ControlModifier) ? zoomCtrlFactor : zoomFactor;
        if (numPixels.y() > 0) {
            scale(factor, factor);
        } else {
            scale(1/factor, 1/factor);
        }
    
        // The event is processed
        event->accept();
    }
    
    
    void CanvasView::resizeEvent(QResizeEvent *event)
    {
        // First call, the scene is created
        if(event->oldSize().width() == -1 || event->oldSize().height() == -1) return;
    
        // Get the previous rectangle of the scene in the viewport
        QPointF P1=mapToScene(QPoint(0,0));
        QPointF P2=mapToScene(QPoint(event->oldSize().width(),event->oldSize().height()));
    
        // Stretch the rectangle around the scene
        if (P1.x()<0) P1.setX(0);
        if (P1.y()<0) P1.setY(0);
        if (P2.x()>scene_->width()) P2.setX(scene_->width());
        if (P2.y()>scene_->height()) P2.setY(scene_->height());
    }
    
    
    QString CanvasView::setToolTipText(QPoint imageCoordinates)
    {
        (void)imageCoordinates;
        return QString("");
    
    }
    
    void CanvasView::drawBackground(QPainter *painter, const QRectF &rect)
    {
        setCacheMode(CacheNone);
        painter->save();
        setBackgroundBrush(QBrush(QColor(77, 77, 77)));
        painter->fillRect(rect, backgroundBrush());
        scene_->setBackgroundBrush(QBrush(QColor(158, 158, 158)));
        painter->fillRect(scene_->sceneRect(), scene_->backgroundBrush());
        painter->setPen( QPen(QColor(247, 0, 255),2) );
        painter->drawRect(scene_->sceneRect());
        painter->restore();
    }
    
    //-----------------------------------------------
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        canvasWidget = new CanvasView();
        canvasWidget->addImage("bender.png", {-1000, -1000});
        canvasWidget->addImage("bender.png", {1300,1300});
        setCentralWidget(canvasWidget);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
        delete canvasWidget;
    }
    

    regads, max



  • It is late-oclock and I'm lazy so not reading your code, but the general reason people have problems with coordinates is because they forget that coordinates are relative to the parent widget, not global screen coordinates.


Log in to reply