Search code examples
pythonpyqt5qlabelqpixmap

How to make an image selectable using pixmap and Qlabel?


I am trying to show multiple images using Pyqt5. It would be nice to make the image selectable within the GUI so that the users can select and copy that image right away easily.

By "selectable", I meant the user can right click the image and then copy it and then potentially paste it to somewhere else outside of the GUI. Just like a normal image saved in a Word. User can select/copy an image in Word and then paste it to somewhere else.

I know for Text in Qlabel this can easily achieved by using self.my_label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse). However, it seems for images there is no such method handling it. Is there any way I can work it out for images?

import sys
import PyQt5
from PyQt5.QtWidgets import (
    QLabel,
    QVBoxLayout,
    QWidget
)
from PyQt5 import QtCore
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import QSize


class Display_Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setMinimumSize(QSize(980,700))
        self.layout = QVBoxLayout(self)
        self.label1 = QLabel(self)
        self.pixmap = QPixmap(path_to_my_image)
        self.pixmap = self.pixmap.scaled(900, 900, QtCore.Qt.KeepAspectRatio)
        self.label1.setPixmap(self.pixmap)
        self.label1.resize(self.pixmap.width(), self.pixmap.height())



# Run if Script
if __name__ == "__main__":
    app = PyQt5.QtWidgets.QApplication(sys.argv)
    MainWindow = Display_Window()                                                   # Initialize GUI
    MainWindow.show()                                                                       # Show Window
    app.exec_()      

Solution

  • You can subclass the label and create a menu whenever it has a valid pixmap, then use the system clipboard to copy it.

    class CopiableLabel(QLabel):
        def contextMenuEvent(self, event):
            pixmap = self.pixmap()
            if not pixmap.isNull():
                menu = QMenu()
                copyAction = menu.addAction('Copy image to clipboard')
                if menu.exec_(event.globalPos()) == copyAction:
                    QApplication.clipboard().setPixmap(pixmap)
                return
            super().contextMenuEvent(event)
    
    
    class Display_Window(QWidget):
        def __init__(self):
            super().__init__()
            self.layout = QVBoxLayout(self)
            self.label1 = CopiableLabel(self)
            self.layout.addWidget(self.label1)
            self.pixmap = QPixmap(path_to_my_image)
            self.pixmap = self.pixmap.scaled(900, 900, Qt.KeepAspectRatio)
            self.label1.setPixmap(self.pixmap)
    

    Note that setting a pixmap on a QLabel automatically resizes it (unless it has the scaledContents property set to True.
    You also should add the label to the layout, as I did in the above modifications.