Почему при выводе списка изображений в QGraphicsScene они перекрывают QRubberBand?

Есть список картинок, которые выводятся в QGraphicsScene наподобие видео. С помощью QRubberBand проходят вычисления координат выделенной области, но при этом его не видно под выводящимися изображениями (он как первый слой торта), т.е. он как бы приклеен к QGraphicsScene.

Я хочу понять причину по которой он не отображается поверх выводимых изображений.

Сейчас это выглядит вот так:

введите сюда описание изображения

введите сюда описание изображения

Я хочу понять причины по которым не видно QRubberBand и было бы хорошо, если получится вывести его как на втором скриншоте.

main.py

import sys
import coordCatch

from PyQt5.Qt import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets, QtCore


class graphicsScene(QtWidgets.QGraphicsScene):
    clicked = pyqtSignal()

    def __init__(self, parent=None):
        super(graphicsScene, self).__init__(parent)

        self.xpos = None
        self.ypos = None
        self.selecting = False
        self.setSceneRect(0,0,1063,1418)
        self.selection = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle)
        self.addWidget(self.selection)
        self.originQPoint = None
        self.originCropPoint = None
        self.currentQRect = None


    def mousePressEvent(self, event):
        self.selecting = True
        self.originQPoint = event.scenePos()
        self.selection.hide()
        self.originCropPoint = event.scenePos()       
        self.clicked.emit()


    def mouseMoveEvent(self, event):
        if self.originQPoint is not None and self.selecting:
            rect = QtCore.QRect(self.originQPoint.toPoint(), 
                                event.scenePos().toPoint())
            self.selection.setGeometry(rect)
            self.selection.show()


    def mouseReleaseEvent(self, event):
        self.selecting = False
        self.selection.hide()
        self.currentQRect = QtCore.QRect(self.originCropPoint.toPoint(), 
                                         event.scenePos().toPoint())
        print(self.currentQRect)



class ProcessWorker(QObject):
    imageChanged = pyqtSignal(QImage)


    def doWork(self):
        self.image_list = ['E:/Projects/QGraphicsView + mpl/pngForDispleying/1.jpg',
                        'E:/Projects/QGraphicsView + mpl/pngForDispleying/2.jpg',
                        'E:/Projects/QGraphicsView + mpl/pngForDispleying/3.jpg',
                        'E:/Projects/QGraphicsView + mpl/pngForDispleying/4.jpg',
                        'E:/Projects/QGraphicsView + mpl/pngForDispleying/5.jpg',
                        'E:/Projects/QGraphicsView + mpl/pngForDispleying/6.jpg',
                        'E:/Projects/QGraphicsView + mpl/pngForDispleying/7.jpg',
                        'E:/Projects/QGraphicsView + mpl/pngForDispleying/8.jpg',
                        'E:/Projects/QGraphicsView + mpl/pngForDispleying/9.jpg']

        f = 0

        while True:
            if f <= len(self.image_list) - 1:
                img = QImage(self.image_list[f])
                self.imageChanged.emit(img)
                QThread.msleep(150)
                f += 1
            else:
                f = 0
                img = QImage(self.image_list[f])
                self.imageChanged.emit(img)
                QThread.msleep(1)



class ExampleApp(QtWidgets.QMainWindow, coordCatch.Ui_MainWindow):
    def __init__(self):
        super(ExampleApp, self).__init__()

        self.setupUi(self)
        self.resize(840, 740)  

        self.gscene = graphicsScene()        
        self.graphicsView.setScene(self.gscene)
        self.graphicsView.show()
        self.graphicsView.setFixedSize(710, 610)

        self.pixmap = QGraphicsPixmapItem()
        self.graphicsView.scene().addItem(self.pixmap) 

        self.workerThread = QThread()
        self.worker = ProcessWorker()
        self.worker.moveToThread(self.workerThread)
        self.workerThread.finished.connect(self.worker.deleteLater)
        self.workerThread.started.connect(self.worker.doWork)
        self.worker.imageChanged.connect(self.setImage)
        self.workerThread.start()


    @pyqtSlot(QImage)
    def setImage(self, image):
        pixmap = QPixmap.fromImage(image)
        self.pixmap.setPixmap(pixmap)       


def main():
    app = QtWidgets.QApplication(sys.argv) 

    window = ExampleApp()
    window.show() 
    app.exec_()  

if __name__ == '__main__': 
    app = QtWidgets.QApplication(sys.argv) 
    main() 

coordCatch.py

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(642, 491)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(10, 10, 441, 331))
        self.graphicsView.setObjectName("graphicsView")

        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        self.colorLayout = QtWidgets.QVBoxLayout()
        self.nameLayout = QtWidgets.QVBoxLayout()

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))

Ответы (1 шт):

Автор решения: S. Nick

Пожалуйста не публикуйте строки кода, которые не нужны в минимально-воспроизводимом примере.

Замените строку:

self._item_color = QColor(0, 0, 255, 0)

например так:

self._item_color = QColor(0, 0, 255, 55) 

main.py:

import sys
# ???import random
# ???import pyautogui

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.Qt import *

from coordCatch import Ui_MainWindow

# ???import numpy as np
# ???import matplotlib as mpl
# ???import matplotlib.pyplot as plt
# ???from matplotlib.pyplot import *
# ???from PIL import Image
# ???from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas

# --> v <----------------------------------------------------------------------------
class GraphicsScene(QtWidgets.QGraphicsScene):
    clicked = pyqtSignal()
    
    def __init__(self, parent=None):
        super(GraphicsScene, self).__init__(parent)

        self._pos = QPointF()
        self._current_item = None
        
#        self._item_color = QColor(0, 0, 255, 0) 
        self._item_color = QColor(0, 0, 255, 55)                     # <---- !!!
        
        self.xpos = None
        self.ypos = None
        self.selecting = False
#        self.setSceneRect(0, 0, 1063, 1418)
        self.setSceneRect(0, 0, 800, 600)
        
        self.selection = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle)
        self.addWidget(self.selection)
        #print(type(self.selection))
        self.originQPoint = None
        #self.selection = None
        self.originCropPoint = None
        self.currentQRect = None
   
    def mousePressEvent(self, event):
        #self.selection = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle)
        self.selecting = True
        self.originQPoint = event.scenePos()
        self.selection.hide()
        self.originCropPoint = event.scenePos()

        self._pos = event.scenePos()
        self._current_item = QGraphicsRectItem()
        self._current_item.setBrush(self._item_color)
        self._current_item.setPen(QPen(QColor("#f8f4ff"), 3, QtCore.Qt.DashLine))
        self.addItem(self._current_item)
        self._current_item.setRect(QRectF(self._pos, self._pos))

        self.clicked.emit()

    
    def mouseMoveEvent(self, event):
        if self.originQPoint is not None and self.selecting:
            rect = QtCore.QRect(self.originQPoint.toPoint(), 
                                event.scenePos().toPoint())
            self.selection.setGeometry(rect)
            self.selection.show()

        if self._current_item:
            rect = QRectF(self._pos, event.scenePos()).normalized()
            self._current_item.setRect(rect)

    def mouseReleaseEvent(self, event):
        self.selecting = False
        self.selection.hide()
        self.currentQRect = QtCore.QRect(self.originCropPoint.toPoint(), 
                                         event.scenePos().toPoint())
        print(self.currentQRect)

        self.removeItem(self._current_item)
        self._current_item = None

# ???        global rectangle 
# ???        rectangle = self.currentQRect.getRect() 
        #self.moved.emit(self.currentQRect)


class ProcessWorker(QObject):
    imageChanged = pyqtSignal(QImage)

    def doWork(self):
        self.image_list = [    
            'lena.jpg',                      # !!! установите свои изображения
            'audience_A.png',
            'audience_B.png',
            'audience_C.png',
            'audience_D.png',
            'Ok.png',
        ]
        f = 0
        
        while True:
#            if f <= 8:
# ----------------> vvvvvvvvvvvvvvvvvvvvvvvv <----------------------------------
            if f <= len(self.image_list) - 1:
            
                img = QImage(self.image_list[f])
                self.imageChanged.emit(img)
                QThread.msleep(1500)
                f += 1
            else:
                f = 0
                img = QImage(self.image_list[f])
                self.imageChanged.emit(img)
                QThread.msleep(1)


class ExampleApp(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(ExampleApp, self).__init__()
        self.setupUi(self)
        
# ???        self.counter = 0
        self.resize(840, 640)  

        self.gscene = GraphicsScene()        
        self.graphicsView.setScene(self.gscene)
        self.graphicsView.show()
        self.graphicsView.setFixedSize(710, 610)

        #self.pic = 'E:\RQC Projects\QGraphicsView + mpl\my.png'
        #self.image = QImage(self.pic)
        self.pixmap = QGraphicsPixmapItem()
        self.graphicsView.scene().addItem(self.pixmap) 

        self.workerThread = QThread()
        self.worker = ProcessWorker()
        self.worker.moveToThread(self.workerThread)
        self.workerThread.finished.connect(self.worker.deleteLater)
        self.workerThread.started.connect(self.worker.doWork)
        self.worker.imageChanged.connect(self.setImage)
        self.workerThread.start()
        
    @pyqtSlot(QImage)
    def setImage(self, image):
        pixmap = QPixmap.fromImage(image)
        self.pixmap.setPixmap(pixmap)       


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv) 
    window = ExampleApp()
    window.show() 
    sys.exit(app.exec_())

введите сюда описание изображения



Update:

Попробуйте так:

main.py:

import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.Qt import *

from coordCatch import Ui_MainWindow                                      # !


class GraphicsScene(QtWidgets.QGraphicsScene):
    clicked = pyqtSignal()

    def __init__(self, parent=None):
        super(GraphicsScene, self).__init__(parent)
# ???    self.xpos = None
# ???    self.ypos = None
        self.selecting = False
        self.setSceneRect(0, 0, 1063, 1418)    
        
        self.selection = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle)
#---     self.addWidget(self.selection)
        
        self.originQPoint = None
        self.originCropPoint = None
        self.currentQRect = None
        
        self.startPos = None                                                 # +++

    def mousePressEvent(self, event):
        self.selecting = True
        self.originQPoint = event.scenePos()
        self.selection.hide()
        self.originCropPoint = event.scenePos()       
        self.clicked.emit()

        self.startPos = event.lastScreenPos()                                # +++

    def mouseMoveEvent(self, event):
        if self.originQPoint is not None and self.selecting:
            lastScreenPos = event.lastScreenPos()                            # +++
            rect = QtCore.QRect(self.startPos, lastScreenPos)                # +++ 
            
#            print(f'def mouseMoveEvent(self, event): rect = {rect}')              
            self.selection.setGeometry(rect)
            self.selection.show()

    def mouseReleaseEvent(self, event):
        self.selecting = False
        self.selection.hide()
        self.currentQRect = QtCore.QRect(
            self.originCropPoint.toPoint(), 
            event.scenePos().toPoint()
        )
        print(self.currentQRect)             # ???


class ProcessWorker(QObject):
    imageChanged = pyqtSignal(QImage)

    def doWork(self):
        self.image_list = [    
            'lena.jpg',                      # !!! установите свои изображения
            'audience_A.png',
            'audience_B.png',
            'audience_C.png',
            'audience_D.png',
            'Ok.png',
        ]
        f = 0

        while True:
            if f <= len(self.image_list) - 1:
                img = QImage(self.image_list[f])
                self.imageChanged.emit(img)
                QThread.msleep(3500)
                f += 1
            else:
                f = 0
                img = QImage(self.image_list[f])
                self.imageChanged.emit(img)
                QThread.msleep(1)


class ExampleApp(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(ExampleApp, self).__init__()
        self.setupUi(self)
        self.resize(840, 740)                     

        self.gscene = GraphicsScene()        
        self.graphicsView.setScene(self.gscene)
        
# ???        self.graphicsView.show()
        self.graphicsView.setFixedSize(710, 610)

        self.pixmap = QGraphicsPixmapItem()
        self.graphicsView.scene().addItem(self.pixmap) 
        
        self.workerThread = QThread()
        self.worker = ProcessWorker()
        self.worker.moveToThread(self.workerThread)
        self.workerThread.finished.connect(self.worker.deleteLater)
        self.workerThread.started.connect(self.worker.doWork)
        self.worker.imageChanged.connect(self.setImage)
        self.workerThread.start()
        
    @pyqtSlot(QImage)
    def setImage(self, image):
        pixmap = QPixmap.fromImage(image)
        self.pixmap.setPixmap(pixmap)       


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv) 
    window = ExampleApp()
    window.show() 
    app.exec_()  

coordCatch.py:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(642, 491)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        
        self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(10, 10, 441, 331))         #  441, 331
        self.graphicsView.setObjectName("graphicsView")

        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

# ???        self.colorLayout = QtWidgets.QVBoxLayout()
# ???        self.nameLayout = QtWidgets.QVBoxLayout()

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        

введите сюда описание изображения

→ Ссылка