Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect mouse click on images displayed in GUI created using PySide

Firstly, I'm new to Python, Qt and PySide so forgive me if this question seems too simple.

What I'm trying to do is to display a bunch of photos in a grid in a GUI constructed using PySide API. Further, when a user clicks on a photo, I want to be able to display the information corresponding to that photo. Additionally, I would like the container/widget used for displaying the photo to allow for the photo to be changed e.g. I should be able to replace any photo in the grid without causing the entire grid of photos to be created from scratch again.

Initially I tried to use QLabel to display a QPixmap but I realized (whether mistakenly or not) that I have no way to detect mouse clicks on the label. After some searching, I got the impression that I should subclass QLabel (or some other relevant class) and somehow override QWidget's(QLabel's parent class) mousePressEvent() to enable mouse click detection. Problem is I'm not sure how to do that or whether there is any alternative widget I can use to contain my photos other than the QLabel without having to go through subclass customization.

Can anyone suggest a more suitable container other than QLabel to display photos while allowing me to detect mouse clicks on the photo or provide some code snippet for subclassing QLabel to enable it to detect mouse clicks?

Thanks in advance for any replies.

like image 681
lightalchemist Avatar asked Dec 27 '22 02:12

lightalchemist


2 Answers

I've added an example of how to emit a signal and connect to another slot. Also the docs are very helpful

from PySide.QtCore import *
from PySide.QtGui import *

import sys


class Main(QWidget):


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

        layout  = QHBoxLayout(self)

        picture = PictureLabel("pic.png", self)
        picture.pictureClicked.connect(self.anotherSlot)

        layout.addWidget(picture)
        layout.addWidget(QLabel("click on the picture"))

    def anotherSlot(self, passed):
        print passed
        print "now I'm in Main.anotherSlot"


class PictureLabel(QLabel):

    pictureClicked = Signal(str) # can be other types (list, dict, object...)

    def __init__(self, image, parent=None):
        super(PictureLabel, self).__init__(parent)        
        self.setPixmap(image)

    def mousePressEvent(self, event):
        print "from PictureLabel.mousePressEvent"
        self.pictureClicked.emit("emit the signal")

a = QApplication([])
m = Main()
m.show()
sys.exit(a.exec_())
like image 74
Jeff Avatar answered Dec 31 '22 12:12

Jeff


Even if the question has been answered, i want to provide an other way that can be used in different situations (see below) :

from PySide.QtCore import *
from PySide.QtGui import *

import sys

class Main(QWidget):

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

        layout  = QHBoxLayout(self)
        picture = QLabel()
        picture.setPixmap("pic.png")
        layout.addWidget(picture)
        layout.addWidget(QLabel("click on the picture"))

        makeClickable(picture)
        QObject.connect(picture, SIGNAL("clicked()"), self.anotherSlot)

    def anotherSlot(self):
        print("AnotherSlot has been called")

def makeClickable(widget):
    def SendClickSignal(widget, evnt):
        widget.emit(SIGNAL('clicked()'))
    widget.mousePressEvent = lambda evnt: SendClickSignal(widget, evnt)


a = QApplication([])
m = Main()
m.show()
sys.exit(a.exec_())

This way doesn't imply subclassing QLabel so it can be used to add logic to a widget made with QtDeigner.

Pros :

  • Can be used over QTdesigner compiled files
  • Can be applied to any kind of widget (you might need to include a super call to the overrided function to ensure widget's normal behavior)
  • The same logic can be used to send other signals

Cons :

  • You have to use the QObject syntax to connect signals and slots
like image 40
C.LECLERC Avatar answered Dec 31 '22 13:12

C.LECLERC