Search code examples
pythonpyqt5qgraphicssceneqpixmap

New QPixmap seems to overlay old QPixmap


I want to display some images on my GUI, first when I click on the button, to select first image, everything act normal, my image is displayed fitInView, but when I want to select the next image, dark magic happens.. my second image is not in center like the first one, is on top of the QGraphicsView, and also it seem like old image's QScenes doesn't disappear, I have the ScrollBar from risg and bottom and I can scrool until I have al blank on QGraphicsView, what is the problem? I can't figured out..

My code:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
# from PyQt4 import QtCore, QtWidgets

class Graph(QtWidgets.QGraphicsView):
        def __init__(self, parent=None):
            super(Graph, self).__init__(parent)
            scene = QtWidgets.QGraphicsScene(self)
            self.setScene(scene)
            self.pixmap = QtGui.QPixmap()
            self.m_pixmap_item = self.scene().addPixmap(self.pixmap)


        def setPixmap(self, _pixmap):
            self.pixmap = _pixmap
            # self.m_pixmap_item = self.scene().addPixmap(self.pixmap)
            self.m_pixmap_item.setPixmap(self.pixmap)
            self.fitInView(self.m_pixmap_item, QtCore.Qt.KeepAspectRatio)

        def resizeEvent(self, event):
            if not self.m_pixmap_item.pixmap().isNull():
                self.fitInView(self.m_pixmap_item, QtCore.Qt.KeepAspectRatio)
            super(Graph, self).resizeEvent(event)

mainwindow part:

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.setMinimumSize(640, 480)
        # --> Create Class ResizbleRubberBand <-> Parent: QLabel
        self.band = Graph(self)
        # --> Create buttons & functions
        self.fileOpen_btn = QtWidgets.QPushButton()
        self.create_and_format_btn(self.fileOpen_btn, self.fileOpen, 'GUI/icons/file.png', 32)
        btn_Layout = QtWidgets.QVBoxLayout()
        btn_layout_1 = QtWidgets.QHBoxLayout()
        btn_layout_1.addWidget(self.fileOpen_btn)
        btn_Layout.addLayout(btn_layout_1)
        layout = QtWidgets.QHBoxLayout(self)
        layout.setAlignment(QtCore.Qt.AlignCenter)
        layout.addWidget(self.band)
        layout.addLayout(btn_Layout)

    def create_and_format_btn(self, btn_name, btn_function, btn_icon, btn_iconsize):
        btn_name.clicked.connect(btn_function)
        btn_name.setIcon(QtGui.QIcon(btn_icon))
        btn_name.setIconSize(QtCore.QSize(btn_iconsize, btn_iconsize))

    def fileOpen(self):
        path = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File')
        filename = path[0]
        self.loadImage_On_Pixmap(filename)

    def loadImage_On_Pixmap(self, file):
        f = QtGui.QPixmap(file)
        self.band.setPixmap(f)



if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    # window.setGeometry(800, 100, 600, 500)
    window.show()
    sys.exit(app.exec_())

First Image (Normal):

enter image description here

Second Image (Strange):

enter image description here


Solution

  • Try it:

    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.QtWidgets import QFileDialog
    
    
    class PhotoViewer(QtWidgets.QGraphicsView):
        photoClicked = QtCore.pyqtSignal(QtCore.QPoint)
    
        def __init__(self, parent):
            super(PhotoViewer, self).__init__(parent)
            self._zoom = 0
            self._empty = True
            self._scene = QtWidgets.QGraphicsScene(self)
            self._photo = QtWidgets.QGraphicsPixmapItem()
            self._scene.addItem(self._photo)
            self.setScene(self._scene)
            self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
            self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
            self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
            self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
            self.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(30, 30, 30)))
            self.setFrameShape(QtWidgets.QFrame.NoFrame)
    
        def hasPhoto(self):
            return not self._empty
    
        def fitInView(self, scale=True):
            rect = QtCore.QRectF(self._photo.pixmap().rect())
            if not rect.isNull():
                self.setSceneRect(rect)
                if self.hasPhoto():
                    unity = self.transform().mapRect(QtCore.QRectF(0, 0, 1, 1))
                    self.scale(1 / unity.width(), 1 / unity.height())
                    viewrect = self.viewport().rect()
                    scenerect = self.transform().mapRect(rect)
                    factor = min(viewrect.width() / scenerect.width(),
                                 viewrect.height() / scenerect.height())
                    self.scale(factor, factor)
                self._zoom = 0
    
        def setPhoto(self, pixmap=None):
            self._zoom = 0
            if pixmap and not pixmap.isNull():
                self._empty = False
                self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
                self._photo.setPixmap(pixmap)
            else:
                self._empty = True
                self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
                self._photo.setPixmap(QtGui.QPixmap())
            self.fitInView()
    
        def wheelEvent(self, event):
            if self.hasPhoto():
                if event.angleDelta().y() > 0:
                    factor = 1.25
                    self._zoom += 1
                else:
                    factor = 0.8
                    self._zoom -= 1
                if self._zoom > 0:
                    self.scale(factor, factor)
                elif self._zoom == 0:
                    self.fitInView()
                else:
                    self._zoom = 0
    
        def toggleDragMode(self):
            if self.dragMode() == QtWidgets.QGraphicsView.ScrollHandDrag:
                self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
            elif not self._photo.pixmap().isNull():
                self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
    
        def mousePressEvent(self, event):
            if self._photo.isUnderMouse():
                self.photoClicked.emit(QtCore.QPoint(event.pos()))
            super(PhotoViewer, self).mousePressEvent(event)
    
    
    class Window(QtWidgets.QWidget):
        def __init__(self):
            super(Window, self).__init__()
    
            self.viewer = PhotoViewer(self)
    
            self.btnLoad = QtWidgets.QToolButton(self)
            self.btnLoad.setIcon(QtGui.QIcon('im.png'))
            self.btnLoad.setIconSize(QtCore.QSize(32, 32))
            self.btnLoad.clicked.connect(self.loadImage)
    
            layout = QtWidgets.QHBoxLayout(self)
            layout.addWidget(self.viewer)
            layout.addWidget(self.btnLoad)
    
    
        def loadImage(self):
            filename, _ = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File')
            if filename:
                self.viewer.setPhoto(QtGui.QPixmap(filename))
    
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        window = Window()
        window.setGeometry(400, 100, 640, 480)
        window.show()
        sys.exit(app.exec_())
    

    enter image description here