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

mapToScene returns position with offset



  • Hello everyone!
    I'm making an app for resizing bmp images. I want to be able to choose area for resizing, so i implemented QRubberBand for this aim. Everything is fine except mapToScene.
    When i'm trying to get point coordinates according to original image, i get them with offset. Moreover, offset is different from image to image, but around 50 pixels on x axis and 70 on y axis.
    cpp file

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "QGraphicsPixmapItem"
    #include "QPixmap"
    #include "QGraphicsScene"
    #include "QFileDialog"
    #include "QDir"
    #include "QStandardItemModel"
    #include "QLineEdit"
    #include "QMouseEvent"
    #include "QRubberBand"
    #include "QDebug"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::mousePressEvent(QMouseEvent *event)
    {
        QPoint origin = event->pos();
        QPointF pic_pos = ui->graphicsView->mapToScene(event->pos());
        QPoint p = pic_pos.toPoint();
        qDebug() << p.rx(); //prints position with some offset
        qDebug()<<p.ry();
        origin.setX(origin.rx()-50); //i want cursor to be at center of square
        origin.setY(origin.ry()-50);
        QSize pos(100,100); //chosing area is a square with 100 by 100 size
        rubberBand->setGeometry(QRect(origin, pos));
        QPalette pal;
        pal.setBrush(QPalette::Highlight, QBrush(Qt::green));
        rubberBand->setPalette(pal);
        rubberBand->show();
    }
    
    void MainWindow::on_actionOpen_file_triggered()
    {
        QString filter = "BMP image (*.bmp)";
        QString file_name = QFileDialog::getOpenFileName(this, "Choose image",QDir::homePath(), filter);
        QGraphicsScene *scene = new QGraphicsScene(this);
        QPixmap pixmap(file_name);
        scene->addPixmap(pixmap);
    
        ui->graphicsView->setScene(scene);
        ui->graphicsView->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
        ui->graphicsView->show();
    }
    
    

    main

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

    header

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QRubberBand>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private slots:
        void on_actionOpen_file_triggered();
        void mousePressEvent(QMouseEvent *event) override;
    
    private:
        Ui::MainWindow *ui;
        QRubberBand *rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
    };
    #endif // MAINWINDOW_H
    
    

  • Lifetime Qt Champion

    See QMouseEvent::pos() - you have a position relative to your mainmwindow, not to your view here.



  • @Christian-Ehrlicher Thanks for your help! But could you please explain how to do it?


  • Lifetime Qt Champion

    You have to map the coordinates from your mainwindow to your scene -> QWidget::mapTo()



  • @Christian-Ehrlicher I got the idea, but still don't know how to implement it. Could you please provide some code?


  • Lifetime Qt Champion

    @Peter_Dev said in mapToScene returns position with offset:

    Could you please provide some code?

    So hard to call mapTo(ui->graphicsView, event->pos()) ?



  • @Christian-Ehrlicher when i make it like this, program finishes unexpectedly if i click anywhere on picture


  • Lifetime Qt Champion

    Use a debugger and take a look at the backtrace to see where exactly t crashes.



  • @Christian-Ehrlicher Segmentation fault. Seems to happen at mapTo


  • Lifetime Qt Champion

    Then make sure all your pointers you're using are valid. And please show some code...



  • @Christian-Ehrlicher Only change i made was in this function:

    void MainWindow::mousePressEvent(QMouseEvent *event)
    {
        QPoint origin = event->pos();
        QPointF res = ui->graphicsView->mapToScene(mapTo(ui->graphicsView,event->pos()));//here
        QPoint p = res.toPoint(); 
        qDebug() << p.rx();
        qDebug()<<p.ry();
        origin.setX(origin.rx()-50);
        origin.setY(origin.ry()-50);
        QSize pos(100,100);
        rubberBand->setGeometry(QRect(origin, pos));
        QPalette pal;
        pal.setBrush(QPalette::Highlight, QBrush(Qt::green));
        rubberBand->setPalette(pal);
        rubberBand->show();
    }
    

  • Lifetime Qt Champion

    @Peter_Dev said in mapToScene returns position with offset:

    PointF res = ui->graphicsView->mapToScene(mapTo(ui->graphicsView,event->pos()));//here

    What is "mapTo" here?
    Did you check all the pointers as already suggested?



  • @jsulm Checking now. mapTo maps click position relative to graphicsView, i guess. Am i wrong?


  • Lifetime Qt Champion

    @Peter_Dev Did you debug and/or check the pointers? This is actually the first thing to do if your app is crashing...



  • @jsulm it crushes at mapTo, when it tries to call mapToParent inside itself. I think problem is in passing ui->graphicsView as first argument in mapTo


  • Lifetime Qt Champion

    @Peter_Dev Again: did you check the pointers? Are those valid?



  • @jsulm Sorry, i'm new here. I don't quite understand what you mean by checking pointers, but as i understood you, yes, all pointers are valid. Before i put mapTo here, everything was working correctly. Sorry for wasting your time, but it's really important project for me, so i need your help very much.



  • @Peter_Dev
    Your code shows

    mapTo(ui->graphicsView,event->pos())
    

    And you wrote

    @jsulm it crushes at mapTo, when it tries to call mapToParent inside itself. I think problem is in passing ui->graphicsView as first argument in mapTo

    If you're saying that crashes, you need to look at its code to determine why. If you're asking for our help, how can we help if you don't show mapTo()'s code?


  • Lifetime Qt Champion

    @JonB I think it's the mapTo from QMainWindow from QWidget :-)
    This was my mistake also when reading this code :-)



  • @JonB

    QPoint QWidget::mapTo(const QWidget * parent, const QPoint & pos) const
    {
        QPoint p = pos;
        if (parent) {
            const QWidget * w = this;
            while (w != parent) {
                Q_ASSERT_X(w, "QWidget::mapTo(const QWidget *parent, const QPoint &pos)",
                           "parent must be in parent hierarchy");
                p = w->mapToParent(p); 
                w = w->parentWidget();
            }
        }
        return p;
    }
    
    QPoint QWidget::mapToParent(const QPoint &pos) const
    {
        return pos + data->crect.topLeft(); //crushes here
    }
    


  • @jsulm , @Peter_Dev
    OK then. https://doc.qt.io/qt-5/qwidget.html#mapTo

    QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const

    Translates the widget coordinate pos to the coordinate system of parent. The parent must not be nullptr and must be a parent of the calling widget.

    I think we can assume parent, ui->graphicsView, is not nullptr, else ui->graphicsView->mapToScene(...) would dump, and it wouldn't be to do with mapTo(). But you should check that ui->graphicsView pointer value.

    If not that, I can't quite get my head around it, but ui->graphicsView cannot be parent of "calling widget" which is MainWindow, can it?

    EDIT This post crossed with @Peter_Dev's latest.

     return pos + data->crect.topLeft(); //crushes here
    

    Assuming you are seeing this in the debugger, what is the value of data and what does it point to?



  • @JonB written that "No such data". So, how to solve my problem? Should i use mapTo or something else?



  • @Peter_Dev
    For the record, am I right that you (or at least the Qt mapTo() code you show) are not compiling for debug? I believe in debug it would have hit the

                Q_ASSERT_X(w, "QWidget::mapTo(const QWidget *parent, const QPoint &pos)",
                           "parent must be in parent hierarchy");
    

    You'll have to ask the experts what's going on/you should do here, I think QMainWindow::mapTo(ui->graphicsView) is the wrong thing to be doing, but I don't claim to know what you should be doing....



  • Ok, i understand. I'll be trying to figure it out. Thanks to everyone who helped me here and sorry for wasting your time.


Log in to reply