2

I think the title is fairly self explanatory. I'm working to create a small standalone app that requires the user to drag and drop audio files onto buttons to in turn associate the file with a corresponding button on a piece of hardware by using the filepath, etc...

I've followed a ton of drag and drop tutorials for widgets, and my friend has for lists, however I'm beginning to believe that it can't be done for a button? I'm aware that you can drag and drop text onto a button. I am not fully up to speed with Qt yet so there may just be a glaring error that I'm missing.

Here is the code, many thanks!

import sys
from PyQt4 import QtGui, QtCore

class Button(QtGui.QPushButton):
    def __init__(self, parent):
    super(Button, self).__init__(parent)
    self.setAcceptDrops(True)
    self.setDragDropMode(QAbstractItemView.InternalMove)

def dragEnterEvent(self, event):
    if event.mimeData().hasUrls():
        event.acceptProposedAction()
    else:
        super(Button, self).dragEnterEvent(event)

def dragMoveEvent(self, event):
    super(Button, self).dragMoveEvent(event)

def dropEvent(self, event):
    if event.mimeData().hasUrls():
        for url in event.mimeData().urls():
            path = self.addItem(url.path())
            print path
        event.acceptProposedAction()
    else:
        super(Button,self).dropEvent(event)

class MyWindow(QtGui.QWidget):
    def __init__(self):
        super(MyWindow,self).__init__()
        self.setGeometry(100,100,300,400)
        self.setWindowTitle("Filenames")

        self.btn = QtGui.QPushButton()
        self.btn.setGeometry(QtCore.QRect(90, 90, 61, 51))
        self.btn.setText("Change Me!")
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.btn)

        self.setLayout(layout)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())
rickcnagy
  • 1,774
  • 18
  • 24
amitchone
  • 1,630
  • 3
  • 21
  • 45
  • Hi Adam, welcome to SO :)! In a question like this, you'll get more of a response if you post less code and show more of what the *exact* issue is. In this case, maybe you could isolate to the 5-10 lines that show that it maybe can't be done? – rickcnagy Apr 21 '15 at 18:49
  • Hi Brick, cheers! Always on here so figured I may as well register- finally! :) I would do that, but I'm not sure where the error is at all, that's why this is really stumping me. The script itself runs with no errors at all, just the button doesn't accept the event – amitchone Apr 21 '15 at 18:58
  • Ok! Well, I put in an edit that should make it a bit easier to read, and then hopefully someone with pyqt experience will be able to help. Good luck :D – rickcnagy Apr 21 '15 at 19:00
  • Have you looked into any of the posted examples? http://doc.qt.io/qt-5/dnd.html#examples – phyatt Apr 21 '15 at 19:15
  • I had a read through and am continuing to do so as well as searching on here still, yeah. All the examples are just using text onto buttons or lists. There was a good post on here that I followed, but it was for QList: (http://stackoverflow.com/questions/4151637/pyqt4-drag-and-drop-files-into-qlistwidget) – amitchone Apr 21 '15 at 19:20

1 Answers1

2

There are three problems with your posted code, the main being that you aren't even using the custom Button class that you made. You are adding just a regular button to your window with:

self.btn = QtGui.QPushButton()

instead of:

self.btn = Button(self)

Also, QPushButtons don't have a setDragDropMode() method, so you'll need to comment that line out. I'm not sure what it does anyway.

Also, QPushButton doesn't have an addItem() method so I'm not sure what that's about unless you were planning on implementing it. I replaced it below with just printing the file path.

Here is a working version of your code, that just prints the file path of any file dragged into the button:

import sys
from PyQt4 import QtGui, QtCore

class Button(QtGui.QPushButton):
    def __init__(self, parent):
        super(Button, self).__init__(parent)
        self.setAcceptDrops(True)
        #self.setDragDropMode(QAbstractItemView.InternalMove)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
        else:
            super(Button, self).dragEnterEvent(event)

    def dragMoveEvent(self, event):
        super(Button, self).dragMoveEvent(event)

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            for url in event.mimeData().urls():
                print str(url.toLocalFile())
            event.acceptProposedAction()
        else:
            super(Button,self).dropEvent(event)

class MyWindow(QtGui.QWidget):
    def __init__(self):
        super(MyWindow,self).__init__()
        self.setGeometry(100,100,300,400)
        self.setWindowTitle("Filenames")

        self.btn = Button(self)
        self.btn.setGeometry(QtCore.QRect(90, 90, 61, 51))
        self.btn.setText("Change Me!")
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.btn)

        self.setLayout(layout)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())
derricw
  • 6,757
  • 3
  • 30
  • 34
  • Much appreciated! Most of that code was just liberated from the QList drag and drop thread I mentioned in the comments, I'm still getting my head around Qt, as you can tell. So thank you very much! – amitchone Apr 21 '15 at 21:04
  • 1
    Thanks for this example! For those who want to use it with PyQt5, it worked for me, I just had to rename the module "QtGui" to "QtWidgets" – poppie Jun 20 '17 at 03:07