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

Highlight hovered cells in QGraphicsScene



  • I am trying to highlight hovered cells on a Grid drawn in a QGraphicsScene.

    Previously I had tried to add another transparent QWidget to the Scene, so that this new QWidget is shown above the Scenes drawing.
    I tried it like this without any success. The Overlay Widget is never visible as it is covered by the Scenes drawing

    self.__scene = QtWidgets.QGraphicsScene(self)
            self.__view = QtWidgets.QGraphicsView(self.__scene, self)
            self.__overlay = QWidget() # must be toplevel it seems
            self.__scene.addWidget(self.__overlay)
    

    As a workaround I thought that I can just draw both the Grid AND the Highlight effect (blue rect around the cell) on the Scene. My code now looks as follows. But the problem is, that I will always have to redraw the Highlight when the Grid was redrawn. Apparently the newly drawn Grid will draw over my Highlight. This just feels super hacky

    def __drawGrid(self):
            if self.__grid_cells:
                # remove prev. grid from scene
                self.__scene.removeItem(self.__grid_cells)
                # remove last reference for gc
                self.__grid_cells = None
            # create new grid
            self.__grid_cells = QGraphicsItemGroup()
            for row_idx, row in enumerate(self.__pattern_model.get_cells()):
                for stitch_idx, stitch in enumerate(row):
                    x1 = stitch_idx * self.__cell_width
                    y1 = row_idx * self.__cell_height
                    if stitch:
                        pen = QPen(Qt.white, 1, Qt.SolidLine)
                        brush = QBrush(Qt.black)
                    else:
                        pen = QPen(Qt.black, 1, Qt.SolidLine)
                        brush = QBrush(Qt.white)
                    self.__grid_cells.addToGroup(
                        self.__scene.addRect(
                            x1, y1, self.__cell_width, self.__cell_height, pen, brush
                        )
                    )
            self.__scene.addItem(self.__grid_cells)
            # redraw highlight to put it on top again
            self.__redraw_highlight()
    
        def __redraw_highlight(self):
            if self.highlighted_cell:
                self.__scene.removeItem(self.highlighted_cell)
            self.__scene.addItem(self.highlighted_cell)
    
        def __drawHighlight(self, stitch_idx, row_idx):
            if self.highlighted_cell:
                self.__scene.removeItem(self.highlighted_cell)
            x1 = stitch_idx * self.__cell_width
            y1 = row_idx * self.__cell_height
            pen = QPen(Qt.blue, 5, Qt.SolidLine)
            self.highlighted_cell = self.__scene.addRect(
                x1, y1, self.__cell_width, self.__cell_height, pen
            )
    

    Is the way I am doing it right now completely wrong? Are there any best or even just better practices for this?


  • Lifetime Qt Champion

    Hi,

    Why not use a QRubberBand and move it where you want without adding it to the scene ?


  • Lifetime Qt Champion

    Hi,

    Why not use a QRubberBand and move it where you want without adding it to the scene ?



  • @occohd21
    I see you adding widgets. rectangles and groups. I don't know what your grid is for, but did you at least consider doing it all via drawBackground()? That's how I do things like this, and for temporary highlighting I use drawForeground(), with a semi-transparent color. There is no adding & removing graphics items. It's a very different approach, depends on your usage.



  • @SGaist Thanks for your answer. I did it that way :)


Log in to reply