Unsolved QGraphicsView scale issue
-
Hello.
I try to implement my own graphics item which simply draws the frame around the pixel.
I have already written some code, and it works partially. The problem is that when I scroll down to the right-bottom and scale my view for some particular factors (22-30), frame offsets for up to a half of neighbour pixel.
.
This was made for scale value 30. For scale values 1-20, 32- problem disappears.Here is a class of my own graphics item (frame around the pixel):
PixelRect::PixelRect(QGraphicsView *view, QGraphicsItem *parent) : QGraphicsItem(parent), view_(view), scenePoint_(15, 15), zoom_(view_->matrix().m11()) { view_->scene()->addItem(this); } void PixelRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { qreal zoom = view_->matrix().m11(); QPen pen = QPen(); pen.setWidth(1); pen.setColor(Qt::black); pen.setStyle(Qt::DotLine); painter->setPen(pen); int x = scenePoint_.x() * zoom; int y = scenePoint_.y() * zoom; QPoint p = view_->mapFromScene(scenePoint_.x(), scenePoint_.y()); painter->drawRect(QRectF(p.x() + view_->horizontalScrollBar()->value(), p.y() + view_->verticalScrollBar()->value(), (int)zoom, (int)zoom )); } QRectF PixelRect::boundingRect() const { qreal zoom = view_->matrix().m11(); QRectF rectOut; int x = scenePoint_.x() * zoom; int y = scenePoint_.y() * zoom; QPoint p = view_->mapFromScene(scenePoint_.x(), scenePoint_.y()); rectOut = QRectF(p.x() + view_->horizontalScrollBar()->value(), p.y() + view_->verticalScrollBar()->value(), (int)zoom, (int)zoom ); return rectOut; } void PixelRect::setPos(const QPoint &pos) { qreal zoom = view_->matrix().m11(); qreal offsetX = (view_->viewport()->width() - view_->scene()->width() * zoom) / 2; if (offsetX < 0) offsetX = 0; qreal offsetY = (view_->viewport()->height() - view_->scene()->height() * zoom) / 2; if (offsetY < 0) offsetY = 0; int x = (pos.x() - offsetX + view_->horizontalScrollBar()->value()) / zoom; int y = (pos.y() - offsetY + view_->verticalScrollBar()->value()) / zoom; if (x < 0) x = 0; if (y < 0) y = 0; if (x >= view_->scene()->width()) x = view_->scene()->width() - 1; if (y >= view_->scene()->height()) y = view_->scene()->height() - 1; scenePoint_.setX(x); scenePoint_.setY(y); update(); }
Usage:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), c_(1), oldMousePos_(15, 15) { ui->setupUi(this); QPixmap pix; pix.load(":images/city.jpeg"); QGraphicsScene * scene = new QGraphicsScene(ui->widget); view_ = new QGraphicsView(scene, this); view_->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); view_->setMouseTracking(true); view_->viewport()->installEventFilter(this); QGridLayout *topLayout = new QGridLayout; topLayout->addWidget(view_, 0, 0); ui->widget->setLayout(topLayout); QGraphicsPixmapItem* pixmapItem = new QGraphicsPixmapItem(pix); scene->addItem(pixmapItem); pixelRect_ = new PixelRect(view_); pixelRect_->setFlag(QGraphicsItem::ItemIgnoresTransformations); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { QMatrix m; m.scale(c_, c_); c_++; view_->setMatrix(m); qDebug() << c_; } bool MainWindow::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::MouseMove) { QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event); if (pixelRect_) pixelRect_->setPos(mouseEvent->pos()); oldMousePos_ = mouseEvent->pos(); } }
Full example https://drive.google.com/file/d/1iL_TR8p8kEGNzPJKfZCiNP6Y4x8pgpFB/view?usp=sharing
Thanks.