Как в pyqt5 программно запустить перетаскивание виджета при отжатой мыши?
Возникла необходимость программного запуска перетаскивания drag, перемещаю кнопки с qtoolbox на qgraphicview. При дропе создаю на полотне сцены graphicitem. На текущий момент повесил shortcut на запуск drag.exec(), но после нажатия сочетания клавиш, оно дропается на месте указателя мыши. Желаемое поведение, чтобы оно запустило процесс перетаскивания и следовало за мышью без зажатой левой кнопки мыши и чтобы была возможность выбора точки дропа.
обнолено: клавиша 'Q' для предпологаемого включения режима drag (по факту идет дроп на текущее местоположение мыши)
пример кода
import sys
from PyQt5.QtCore import Qt, QSize, QMimeData, QByteArray
from PyQt5.QtGui import QIcon, QDrag
from PyQt5.QtWidgets import QMainWindow, QApplication, QGraphicsScene, QGraphicsView, QToolBox, QGridLayout, \
QToolButton, QButtonGroup, QLabel, QWidget, QAction, QSizePolicy, QHBoxLayout, QGraphicsRectItem, QGraphicsItem, \
QStyle
class MyGraphicsView(QGraphicsView):
def dragEnterEvent(self, event):
if event.mimeData().hasFormat("item/rect"):
event.acceptProposedAction()
self.update()
def dragMoveEvent(self, event):
if event.mimeData().hasFormat("item/rect"):
event.acceptProposedAction()
def dropEvent(self, event):
if event.mimeData().hasFormat("item/rect"):
pos = self.mapToScene(event.pos())
item = QGraphicsRectItem(0, 0, 300, 300)
item.setFlag(QGraphicsItem.ItemIsMovable)
self.scene().addItem(item)
item.setPos(pos)
self.update()
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.scene = QGraphicsScene(-300, -300, 2520, 1680)
self.view = MyGraphicsView(self.scene)
self.view.centerOn(self.view.viewport().rect().topLeft())
self.view.viewport().update()
self.toolBox = QToolBox()
self.buttonGroup = QButtonGroup()
layout = QGridLayout()
layout.setContentsMargins(0, 0, 0, 0)
name = "item"
icon = QIcon(QApplication.style().standardIcon(QStyle.SP_DesktopIcon))
button = QToolButton()
button.setIcon(icon)
button.setIconSize(QSize(50, 50))
button.setCheckable(True)
button.mouseMoveEvent = self.enableDrag
self.buttonGroup.addButton(button)
self.button = button
layout = QGridLayout()
layout.addWidget(button, 0, 0, Qt.AlignHCenter)
layout.addWidget(QLabel(name), 1, 0, Qt.AlignCenter)
action = QAction("startDrag", self)
action.triggered.connect(self.enableDrag)
action.setShortcut("Q")
action.setStatusTip("Начать перетаскивание")
button.addAction(action)
layout.setRowStretch(2, 2)
layout.setColumnStretch(1, 2)
block = QWidget()
block.setLayout(layout)
self.toolBox.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred))
self.toolBox.addItem(block, "toolbox")
l = QHBoxLayout()
l.addWidget(self.toolBox)
l.addWidget(self.view)
self.widget = QWidget()
self.widget.setLayout(l)
self.setCentralWidget(self.widget)
def enableDrag(self, *args):
print("pressed")
drag = QDrag(self.button)
mime = QMimeData()
drag.setMimeData(mime)
mime.setData("item/rect", QByteArray(b''))
pixmap = self.button.icon().pixmap(QSize(64, 64))
pixmap.setMask(pixmap.createHeuristicMask())
drag.setPixmap(pixmap)
drag.setHotSpot(pixmap.rect().topLeft())
drag.exec_()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.setVisible(True)
sys.exit(app.exec_())