Unwanted vertical offset with with QRubberBand
-
@mrjj said in Unwanted vertical offset with with QRubberBand:
@Bidski
Super.
Also if you can upload the small? project and give link here then
its just to run and see for oneself also.Ok, I have dumped some quick values.
The (x, y, width, height) of the QLabel geometry is reported as (188, 9, 613, 512)
When the QRubberBand is stretched above the QLabel (as shown in the original image), its geometry is reported as (335, 9, 62, 175)
When attempting to stretch the QRubberBand down to the bottom of the QLabel, the extent of its geometry reaches (340, 364, 272, 157)The black border of the QLabel (where the QRubberBand should be stopping) has top coordinate of 31 and a bottom coordinate of 544.
Based on this, the QRubberBand is overshooting the top by 22 pixels and undershooting the bottom by 22 pixels.These measurements were taken with the window in a non-maximised state. When maximised, the offset remains the same.
I will organise you a link to the code shortly
-
Hopefully you should be able to view this repo.
Bitbucket Repo -
@Bidski
It still sounds as difference between client coordinates and global coordinates :)
Like the height of the caption.It will let me into
https://bitbucket.org/Bidski/imageannotator/srcbut i cant seem to find the download as zip ?
I guess bitbucket do not offer such option. :)
Called Downloads :) ( doh) -
@mrjj said in Unwanted vertical offset with with QRubberBand:
@Bidski
It still sounds as difference between client coordinates and global coordinates :)
Like the height of the caption.What is the correct way to handle the difference in coordinate systems?
-
Hi
Its these functions.
http://doc.qt.io/qt-5/qwidget.html#mapFromGlobal
QPoint QWidget::mapToParent(const QPoint &pos) constI didnt get to run it ( will tonight) but my best guess is that parent for RubberBand and
parent for Label is not the same and the offset comes from that.A Child is relative to its parent. So its x,y is from the parent x,y. and not from zero,zero
So I think its where the diff comes from.
The mouse is in global, but the Label is in local with x,y.
I think RubberBand is relative to parent (if any) and not 0,0.Its talked about here
http://stackoverflow.com/questions/16527248/qrubberband-on-a-definite-label -
I had a look at my code again. The QMenuBar, QLabel, and QRubberBand all share the same parent (which is AnnotateApp), so the mouse event position should have been in the same coordinate system as everything else? It appears that the QMenuBar is somehow absent in the calculation of the coordinates?
However, I made some code changes based on the SO link @mrjj provided. The QLabel is now the parent of QRubberBand and the mouse event coordinates are now mapped to global and then mapped from global to QLabel, as shown below.
void AnnotateApp::mousePressEvent(QMouseEvent *event) { // Create a rubber band if the mouse event is happening inside the image. if (ui->image->geometry().contains(event->pos())) { origin = ui->image->mapFromGlobal(this->mapToGlobal(event->pos())); if (!rubberBand) { rubberBand = new QRubberBand(QRubberBand::Rectangle, ui->image); } rubberBand->setGeometry(QRect(origin, QSize())); rubberBand->show(); } } void AnnotateApp::mouseMoveEvent(QMouseEvent *event) { // Only act if we actually have a rubber band to work with. if (rubberBand && rubberBand->isVisible()) { QPoint pos = ui->image->mapFromGlobal(this->mapToGlobal(event->pos()); // Check to see if the mouse is still inside the iamge or not. // If it is, then update the rubber band to the new coordinates. if (ui->image->geometry().contains(pos)) { rubberBand->setGeometry(QRect(origin, pos).normalized()); } // If it is not, then clamp the coordinates to the image boundary. else { int x = std::min(ui->image->geometry().right(), std::max(pos.x(), ui->image->geometry().left())); int y = std::min(ui->image->geometry().bottom(), std::max(pos.y(), ui->image->geometry().top())); rubberBand->setGeometry(QRect(origin, QPoint(x, y)).normalized()); } } }
This simply changes where the offset occurs. In the first image, I can't drag the left and top sides of the rubber band past where they are (started dragging from the middle of the QLabel). In the second image I started dragging from the top-left of the QLabel, immediately a small x-offset is appears and the width of the QRubberBand snaps to where the x-boundary occurs in the first image.
-
I don't have a bugfix for you, but a workaround.
reverte mousePressEvent back to how it was and
void AnnotateApp::mouseMoveEvent(QMouseEvent *event) { // Only act if we actually have a rubber band to work with. if (rubberBand && rubberBand->isVisible()) { // Check to see if the mouse is still inside the iamge or not. // If it is, then update the rubber band to the new coordinates. QRect fixedRect (ui->image->x(), ui->image->y()+ui->menubar->height(), ui->image->width(), ui->image->height()); if (fixedRect.contains(event->pos())) { rubberBand->setGeometry(QRect(origin, event->pos()).normalized()); } // If it is not, then clamp the coordinates to the image boundary. else { int x = std::min(fixedRect.right(), std::max(event->pos().x(), fixedRect.left())); int y = std::min(fixedRect.bottom(), std::max(event->pos().y(), fixedRect.top())); rubberBand->setGeometry(QRect(origin, QPoint(x, y)).normalized()); } } }
but its a workaround! Hopefully someone can give you a better solution.
-
@Bidski
Hi
Not in Qt. ( maybe if old)I would guess from the attempt to snap the
coordinates but cant say for sure.However, please see this sample
https://www.dropbox.com/s/gp9rvylkb18xnl3/myrubberband.zip?dl=0
Drag the rubberband and release
It cuts what is expected and show in label
So all seems to be fine :)#include <QMouseEvent> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); move_rubberband = false; rubberBand = new QRubberBand(QRubberBand::Rectangle, this); rubberBand->setGeometry(0,0,50,50); rubberBand->show(); } void MainWindow::mousePressEvent(QMouseEvent *e) { if(rubberBand->geometry().contains(e->pos())) { rubberband_offset = e->pos() - rubberBand->pos(); move_rubberband = true; } } void MainWindow::mouseMoveEvent(QMouseEvent *e) { if(move_rubberband) { rubberBand->move(e->pos() - rubberband_offset); } } void MainWindow::mouseReleaseEvent(QMouseEvent *e) { move_rubberband = false; QRect r=rubberBand->geometry(); rubberBand->hide(); QPixmap p=grab(r); // no need for mapTo here. ui->label->setPixmap(p); rubberBand->show(); rubberBand->raise(); }