Announcements

Between mid-October and November, the content on AREA will be relocated to the Autodesk Community M&E Hub and the Autodesk Community Gallery. Learn more HERE.

Drag and Drop with PySide into Main Max Window

Drag and Drop with PySide into Main Max Window

mitchell.lotierzoJ5X6W
Participant Participant
1,084 Views
4 Replies
Message 1 of 5

Drag and Drop with PySide into Main Max Window

mitchell.lotierzoJ5X6W
Participant
Participant

If I get the instance of the main 3ds Max window with `QWidget.find(rt.windows.getMAXHWND())`, is it possible to somehow override the `dropEvent` of that window to accept drops from a QDialog created with PySide?

 

Is it even possible to do drag and drop from PySide into the main 3ds Max application?

0 Likes
Accepted solutions (1)
1,085 Views
4 Replies
Replies (4)
Message 2 of 5

Swordslayer
Advisor
Advisor
from qtmax import GetQMaxMainWindow
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import QDialog, QHBoxLayout

class DragButton(QPushButton):
    def mouseMoveEvent(self, e):
        if e.buttons() == QtCore.Qt.RightButton:
            return

        mimeData = QtCore.QMimeData()
        mimeData.setUrls([QtCore.QUrl.fromLocalFile("C:\\path\\file.max")]) # or file.jpg etc.
        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)
        drag.start(QtCore.Qt.MoveAction)

class Window(QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.setWindowTitle('Drag & Drop')

        self.setLayout(QHBoxLayout())
        self.layout().addWidget(DragButton("Drag Me"))        

dialog = Window(GetQMaxMainWindow())
dialog.show()
Message 3 of 5

Swordslayer
Advisor
Advisor
Accepted solution

Or if you want to do something more custom, like dropping some objects on construction plane, you can do it this way:

 

 

from qtmax import GetQMaxMainWindow
from PySide2 import QtCore, QtGui, QtWidgets
from pymxs import undo as max_undo, runtime as rt


class MaxEvents(QtCore.QObject):

    def eventFilter(self, object, event):
        if (event.type() == QtCore.QEvent.DragEnter):
            print("Drag enter")
        elif (event.type() == QtCore.QEvent.DragMove):
            print("Drag move")
        elif (event.type() == QtCore.QEvent.Drop):
            self.parent().dropped.emit()

        return False


class DragButton(QtWidgets.QPushButton):

    dropped = QtCore.Signal()
    mainWin = GetQMaxMainWindow()

    def mouseMoveEvent(self, e):
        if e.buttons() == QtCore.Qt.RightButton:
            return

        filter = MaxEvents(parent = self)
        self.mainWin.installEventFilter(filter)

        mimeData = QtCore.QMimeData()
        mimeData.setUrls([])
        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)

        try:
            drag.start(QtCore.Qt.MoveAction)
        finally:
            self.mainWin.removeEventFilter(filter)
            self.setDown(False)


class Window(QtWidgets.QDialog):

    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.setWindowTitle('Drag & Drop')

        self.setLayout(QtWidgets.QHBoxLayout())
        btn = DragButton("Drop Box")
        btn.dropped.connect(self.spawnBox)
        self.layout().addWidget(btn)

    def spawnBox(self):
        if (rt.mouse.pos.x > 0 and rt.mouse.pos.y > 0 and rt.mouse.pos.x <= rt.gw.getWinSizeX() and rt.mouse.pos.y <= rt.gw.getWinSizeY()):
            with max_undo(True):
                rt.Box(length = 5, width = 5, height = 5, pos = rt.mapScreenToCP(rt.mouse.pos))
            rt.redrawViews()
        else:
            print("Dropped outside of active viewport")

w = Window(GetQMaxMainWindow())
w.show()

 

Message 4 of 5

mitchell.lotierzoJ5X6W
Participant
Participant

@Swordslayer I appreciate the detailed response and the two options you provided. I meant to actually post an update back on Friday, but work got the best of me. I stumbled upon the whole concept of using the `eventFilter` on Friday and do like that approach better. Interestingly, I tried an approach similar to your first example, but couldn't get the Max main window to accept the drag, but I wasn't using `qtmax`, I was just getting the window via the runtime, so maybe that was the issue. I need to look more into the `qtmax` module.

Thanks again! Cheers!

0 Likes
Message 5 of 5

Swordslayer
Advisor
Advisor

The qtmax method (or MaxPlus one in older max versions) is basically the same thing as QtWidgets.QWidget.find(rt.windows.getMaxHWnd()), the important thing to make max accept the drop is to have an array of urls set in the mimeData (it can be empty if you don't want max to use what's in it, mimeData.setUrls([]) should still work).

0 Likes