Starting a drag stops widget from receiving mouseMoveEvent().



  • Hello Qt guys.

    My application does image dragging and dropping. And I wanted to have the image being dragged to be visible under the mouse cursor and also be partially transparent, like the many commercial applications out there.

    I really can't find a solution anywhere. There are some similar questions on the internet but they are unanswered or I can't get them to work. like "here":http://www.developer.nokia.com/Community/Wiki/Archived:Transparent_QPixmap_picture and "here":http://qt-project.org/faq/answer/how_can_i_have_a_partially_transparent_pixmap_on_my_toplevel_window
    .
    Obviously, QDrag::setPixmap() won't allow transparency (to my knowledge) and looks ugly.
    So, I had another idea. When dragging starts, I show a QLabel with the dragged image in it, painted partially transparent, and move the image with the mouse position. When mouse is released, I hide the image label.

    Here is a sample code (PySide):
    @class TransparentImageLabel(QtGui.QLabel):
    def init(self, image, parent=None):
    super().init(parent)
    self.setPixmap(image)
    self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
    self.setWindowFlags(QtCore.Qt.FramelessWindowHint)

    def paintEvent(self, e):-
        painter = QtGui.QPainter(self)
        painter.setOpacity(.5)
        painter.drawPixmap(self.pos().x(), self.pos().y(), self.pixmap())
        painter.end()
    

    class DragSource(QtGui.QLabel):
    def init(self, image, parent=None):
    """
    An image label. When mouse is dragged over it,
    shows another small label moving with cursor.
    """
    super().init(parent)
    self.setPixmap(QtGui.QPixmap(image))
    self.tr_label = TransparentImageLabel(image, parent=self)

    def mouseMoveEvent(self, e):
        #drag an image from this label
        mime_data = QtCore.QMimeData()
        mime_data.setImageData(self.pixmap())
        drag = QtGui.QDrag(self)
        drag.setMimeData(mime_data)
        drag.start()
        self.tr_label.show()
        pixmap_width = self.pixmap().width()
        pixmap_height = self.pixmap().height()
        #move label with mouse moves
        self.tr_label.setGeometry(e.pos().x(), e.pos().y()  , pixmap_width , pixmap_height)
        super().mouseMoveEvent(e)
    
    def mouseReleaseEvent(self, e):
        self.tr_label.hide()
    

    class DropTarget(QtGui.QWidget):
    def init(self, parent=None):
    super().init(parent)
    self.layout = QtGui.QVBoxLayout()
    self.image_label = QtGui.QLabel('Drop here!')
    self.layout.addWidget(self.image_label)
    self.setLayout(self.layout)
    self.setAcceptDrops(True)

    def dragEnterEvent(self, e):
        if e.mimeData().hasImage():
            e.accept()
        else:
            e.ignore()
    
    def dropEvent(self, e):
        self.image_label.setPixmap(e.mimeData().imageData())
    

    class Application(QtGui.QWidget):
    def init(self, parent=None):
    super().init(parent)
    self.layout = QtGui.QVBoxLayout()
    self.layout.addWidget(DragSource(r'C:\image.jpg'))
    self.layout.addWidget(DropTarget())
    self.setLayout(self.layout)

    app = QtGui.QApplication(sys.argv)
    main = Application()
    main.show()
    sys.exit(app.exec_())
    @

    It works in that a transparent image is being dragged with the mouse.
    The problem is, when I start the drag (line 31), the label holding the image stops receiving mouseMoveEvents, which also kills the image moving capability. If I comment out the line, the image moves, but I can't drop anything, since I already disabled dragging.
    This might seem logical, as starting dragging should generate dragMoveEvents instead, but nah, no such events get generated.

    Sorry for the long post :-(
    Please help the community solve this problem once and for all :-) . I'd accept modifications on my code or a completely different solution.

    Thanks a lot.



  • I also tried QLabel::grabMouse() function in the hope that it will keep the widget receiving events, but instead it locked the GUI and prevented receiving further events.
    Is this a bug within Qt or is it actually a bug in Qt?



  • Somebody say something?.
    Is it me, or is it QTea?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.