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?