Unsolved [PyQt5] What is the right way to discretize a QDrag pixmap along a grid?
-
Hi everyone, I hope I'm at the right address as I'm new to this forum (and forums in general). I've asked the same question on StackOverflow but it received no attention there.
The following code produces a simple applet with a button that we can make copies of by dragging and dropping it.
import sys import math from PyQt5.QtCore import QMimeData, QPoint, Qt from PyQt5.QtGui import QColor, QDrag, QPainter from PyQt5.QtWidgets import QApplication, QPushButton, QWidget class Button(QPushButton): def mouseMoveEvent(self, e): if e.buttons() != Qt.LeftButton: return mimeData = QMimeData() mimeData.setText('%d,%d' % (e.x(), e.y())) pixmap = QWidget.grab(self) painter = QPainter(pixmap) painter.setCompositionMode(painter.CompositionMode_DestinationIn) painter.fillRect(pixmap.rect(), QColor(0, 0, 0, 127)) painter.end() drag = QDrag(self) drag.setMimeData(mimeData) drag.setPixmap(pixmap) drag.setHotSpot(e.pos()) if drag.exec_(Qt.CopyAction) == Qt.CopyAction: print('Button has been copied!') class Example(QWidget): def __init__(self): super(Example, self).__init__() self.initUI() def initUI(self): self.setAcceptDrops(True) button = Button('Button', self) button.resize(100, 30) self.buttons = [button] self.setWindowTitle('Create new buttons') self.setGeometry(300, 300, 300, 300) def dragEnterEvent(self, e): e.accept() def dropEvent(self, e): mime = e.mimeData().text() relx, rely = map(int, mime.split(',')) button = Button('Copied button', self) button.resize(100, 30) xcoord = e.pos().x() - relx xcoord = math.floor(0.5 + xcoord / 100) * 100 ycoord = e.pos().y() - rely ycoord = math.floor(0.5 + ycoord / 30) * 30 button.move(QPoint(xcoord, ycoord)) button.show() self.buttons.append(button) e.setDropAction(Qt.CopyAction) e.accept() if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() ex.show() app.exec_()
The definition of
xcoord
andycoord
cause the dropped copy of the button to automatically align with a simple grid. I would like the location ofpixmap
, which currently traces the mouse as we perform our drag and drop, to be discretized, so that it is located where the button would land when I would drop the button.While experimenting, I learned that, while dragging, the mouse coordinates are not being kept track of automatically; one has to reimplement
self.dragMoveEvent()
to do so. I've tried to use this to continually update the coordinates ofdrag.setHotSpot()
, but without results.I am aware that PyQt5 has numerous options for implementing grid layouts, which I feel is the right way to proceed, but I have no idea how to do so.
-
Hi and welcome to the forums.
You app really sound like this exmaple
https://doc.qt.io/qtforpython/overviews/qtwidgets-draganddrop-puzzle-example.html
where you can drag an image piece to a grid.
However, it uses a list of taken positions so not sure that will work for your use case ?Just to understand it right. While dragging, you want the cursor to sort of jump to grid locations ?
-
@Simon_tries_hard said in [PyQt5] What is the right way to discretize a QDrag pixmap along a grid?:
one has to reimplement self.dragMoveEvent() to do so
I don't see it in the code you posted.
I also don't understand why you're constantly creating QDrag while moving mouse with pressed left button.
And you do not accept/reject the mouse move event. -
@mrjj said in [PyQt5] What is the right way to discretize a QDrag pixmap along a grid?:
Just to understand it right. While dragging, you want the cursor to sort of jump to grid locations ?
While dragging, a 'ghost' instance of the button (the
pixmap
which is made to resemble the button but with added transparency) appears behind the cursor. I want this ghost instance to jump from grid location to grid location as I'm moving the mouse.@jsulm said in [PyQt5] What is the right way to discretize a QDrag pixmap along a grid?:
@Simon_tries_hard said in [PyQt5] What is the right way to discretize a QDrag pixmap along a grid?:
one has to reimplement self.dragMoveEvent() to do so
I don't see it in the code you posted.
I also don't understand why you're constantly creating QDrag while moving mouse with pressed left button.
And you do not accept/reject the mouse move event.The code I posted is what I started with. I tweaked it around in various ways with no good results, but I didn't post the changed codes.
As for the rest of what you say, well, I'm a newbie when it comes to Qt so whatever you don't understand I probably understand even less.