Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. QGraphicsView additem incorrect size in rezised view

QGraphicsView additem incorrect size in rezised view

Scheduled Pinned Locked Moved Unsolved Qt for Python
2 Posts 2 Posters 321 Views 1 Watching
  • 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.
  • R Offline
    R Offline
    RDDev
    wrote on last edited by
    #1

    Hi all,
    in my app i'm using a QGraphicsView to display a Microscope image and i want to set a new region for a higher magnification scan. Thus, my program displays an image, enables zoom by mousewheel and the cursor is shaped to a square that shows the user what area he will select. By clicking, i want to set the cursor square to its current position. I created a minimal example of this app with the help of ChatGPT thats shown below.

    Currently, the square that is drawn as item and depicted after clicking only coincides for one zooming level to the size of the cursor. Does anyone has a solution how to handle this coordinate mapping correctly?

    import sys
    from PySide6.QtWidgets import QGraphicsPixmapItem, QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsRectItem
    from PySide6.QtCore import Qt, QRectF
    from PySide6.QtGui import QPixmap, QPainter, QPen, QColor
    from PySide6 import QtCore
    from PySide6 import QtGui
    from PIL import Image, ImageQt
    import numpy as np
    
    class GraphicsView(QGraphicsView):
        def __init__(self, scene):
            super().__init__(scene)
            self.setRenderHint(QPainter.Antialiasing)
            self.setMouseTracking(True)
            self.zoom_factor = 1.1
            self.base_cursor_size = 10
            self.rect_item = None
            self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
            self.setResizeAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
            
    
        def wheelEvent(self, event):
            zoom_in_factor = self.zoom_factor
            zoom_out_factor = 1 / self.zoom_factor
    
            old_pos = self.mapToScene(event.position().toPoint())
    
            if event.angleDelta().y() > 0:
                zoom_factor = zoom_in_factor
            else:
                zoom_factor = zoom_out_factor
    
            self.scale(zoom_factor, zoom_factor)
    
            new_pos = self.mapToScene(event.position().toPoint())
            delta = new_pos - old_pos
            self.translate(delta.x(), delta.y())
    
            self.set_square_cursor()
    
        def mousePressEvent(self, event):
            if event.button() == Qt.LeftButton:
                if self.rect_item:
                    self.scene().removeItem(self.rect_item)
    
                scene_pos = self.mapToScene(event.position().toPoint())
                rect_size = 10 / self.transform().m11()  # Adjust rectangle size according to zoom level
                self.rect_item = QGraphicsRectItem(scene_pos.x()-rect_size/2, scene_pos.y()-rect_size/2, rect_size, rect_size)
                self.rect_item.setPen(QPen(QColor(0, 127, 255), 1 / self.transform().m11()))
                self.scene().addItem(self.rect_item)
            super().mousePressEvent(event)
    
    
        def enterEvent(self, event: QtCore.QEvent) -> None:
            self.set_square_cursor()
            super().enterEvent(event)
    
        def leaveEvent(self, event: QtCore.QEvent) -> None:
            self.setCursor(QtCore.Qt.CursorShape.ArrowCursor)
            super().leaveEvent(event)
    
        def set_square_cursor(self):
            # Calculate the cursor size based on the current zoom level
            transform = self.transform()
            scale_factor = transform.m11()
            cursor_size = int(self.base_cursor_size * scale_factor)
    
            cursor_arr = np.zeros((cursor_size, cursor_size), dtype=np.uint8)
            padded_cursor_arr = np.pad(cursor_arr, 1, constant_values=1)
            rgba_cursor = np.stack([padded_cursor_arr] * 4, axis=-1) * [[[255, 127, 0, 255]]]
            rgba_cursor = rgba_cursor.astype(np.uint8)
    
            qim = QtGui.QImage(rgba_cursor, rgba_cursor.shape[1], rgba_cursor.shape[0], QtGui.QImage.Format.Format_ARGB32)
            pix = QtGui.QPixmap.fromImage(qim)
            cursor = QtGui.QCursor(pix, -cursor_size // 2, -cursor_size // 2)
            self.setCursor(cursor)
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
    
            self.setWindowTitle("Zoomable QGraphicsView with Fixed Rectangle Cursor")
            self.setGeometry(100, 100, 800, 600)
    
            self.scene = QGraphicsScene()
            self.view = GraphicsView(self.scene)
            self.setCentralWidget(self.view)
    
            # add example image
            self.add_example_image()
    
        def add_example_image(self):
            rect = QRectF(0, 0, 800, 600)
            self.scene.setSceneRect(rect)
    
            # create example image
            pixmap = QPixmap.fromImage(ImageQt.ImageQt(Image.fromarray(np.random.randint(0, 20, (300, 400, 3), dtype=np.uint8))))
            pixmap_item = QGraphicsPixmapItem(pixmap)
            scale = 500 / pixmap_item.pixmap().width()
            pixmap_item.setScale(scale)
            pixmap_item.setPos(0, 0)
            self.scene.addItem(pixmap_item)
    
    def main():
        app = QApplication(sys.argv)
        window = MainWindow()
        window.show()
        sys.exit(app.exec())
    
    if __name__ == "__main__":
        main()
    
    

    Best and thanks in advance,
    RDDev

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      Shouldn't:
      rect_size = 10 / self.transform().m11() # Adjust rectangle size according to zoom level
      rather be:
      rect_size = 10 * self.transform().m11() # Adjust rectangle size according to zoom level

      ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      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