복붙노트

[PYTHON] PyQt4 - 드래그 앤 드롭

PYTHON

PyQt4 - 드래그 앤 드롭

이 튜토리얼을 통해 PyQt4의 드래그 앤 드롭 방식을 이해할 수 있었다. 그러나 나는 다음과 같은 점을 이해할 수 없다. somepne이 나에게 그것을 더 명확하게 할 수 있다면 좋을 것입니다.

 def mouseMoveEvent(self, e): //class Button


    mimeData = QtCore.QMimeData()

    drag = QtGui.QDrag(self)
    drag.setMimeData(mimeData)
    drag.setHotSpot(e.pos() - self.rect().topLeft())

    dropAction = drag.start(QtCore.Qt.MoveAction)

def dropEvent(self, e): //class Example

    position = e.pos()
    self.button.move(position)

    e.setDropAction(QtCore.Qt.MoveAction)
    e.accept()

왜 self.button.move와 e.setDropAction이 분리되어 있습니까? self.button.move ()가 실제로 버튼 자체를 움직이지 않습니까? 누군가 drag.setHotSpot과 drag.start ()가 무슨 일을하는지 설명 할 수 있습니까? 감사.

해결법

  1. ==============================

    1.그 튜토리얼은 진부하게 오래된 것입니다. QDrag.start는 Qt 4.3부터 폐기되었습니다. 대신 QDrag.exec_를 사용해야합니다.

    그 튜토리얼은 진부하게 오래된 것입니다. QDrag.start는 Qt 4.3부터 폐기되었습니다. 대신 QDrag.exec_를 사용해야합니다.

    exec에 대한 문서에서 볼 수 있듯이 반환 값이 있습니다. dropEvent의 setDropAction가이 값을 결정합니다. 그것은 이동을 수행하지 않습니다. 그래서 실제 이동을하려면 self.button.move ()가 필요합니다. 그렇다면 setDropAction의 핵심은 무엇입니까? 당신이 한 드래그 작업의 종류를 알아야 할 수도 있습니다. 두 개의 목록 위젯간에 드래그 드롭을 구현한다고 가정 해보십시오. 이동 작업을 수행했다면, 소스 위젯에서 항목을 제거하고 대상에 항목을 만들어야 함을 의미합니다. 복사 작업 인 경우 원본을 그대로두고 대상에 복사본을 만들면됩니다.

    setHotSpot / hotSpot은 QDrag의 setPixmap과 관련이 있습니다. 항목을 드래그 할 때 QPixmap을 표시 할 수 있습니다. hotSpot은 픽스맵의 위치를 ​​결정합니다. pixmap은 커서가 pixmap의 왼쪽 상단 모서리를 기준으로 hotSpot에 위치하도록 배치됩니다. 따라서이 튜토리얼의 경우에는 표시 할 픽스맵이 없기 때문에 무의미합니다.

    이 튜토리얼의 약간 수정되고 업데이트 된 버전이 있습니다. 바라기를, 나는 충분한 코멘트를 포함했다. 오른쪽 클릭으로 이동하거나 Shift + 오른쪽 클릭으로 복사 할 수 있습니다.

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    import sys
    from PyQt4 import QtGui, QtCore
    
    
    class Button(QtGui.QPushButton):
        def mouseMoveEvent(self, e):
            if e.buttons() != QtCore.Qt.RightButton:
                return
    
            # write the relative cursor position to mime data
            mimeData = QtCore.QMimeData()
            # simple string with 'x,y'
            mimeData.setText('%d,%d' % (e.x(), e.y()))
    
            # let's make it fancy. we'll show a "ghost" of the button as we drag
            # grab the button to a pixmap
            pixmap = QtGui.QPixmap.grabWidget(self)
    
            # below makes the pixmap half transparent
            painter = QtGui.QPainter(pixmap)
            painter.setCompositionMode(painter.CompositionMode_DestinationIn)
            painter.fillRect(pixmap.rect(), QtGui.QColor(0, 0, 0, 127))
            painter.end()
    
            # make a QDrag
            drag = QtGui.QDrag(self)
            # put our MimeData
            drag.setMimeData(mimeData)
            # set its Pixmap
            drag.setPixmap(pixmap)
            # shift the Pixmap so that it coincides with the cursor position
            drag.setHotSpot(e.pos())
    
            # start the drag operation
            # exec_ will return the accepted action from dropEvent
            if drag.exec_(QtCore.Qt.CopyAction | QtCore.Qt.MoveAction) == QtCore.Qt.MoveAction:
                print 'moved'
            else:
                print 'copied'
    
    
        def mousePressEvent(self, e):
            QtGui.QPushButton.mousePressEvent(self, e)
            if e.button() == QtCore.Qt.LeftButton:
                print 'press'
    
    
    
    class Example(QtGui.QWidget):
        def __init__(self):
            super(Example, self).__init__()
            self.initUI()
    
    
        def initUI(self):
            self.setAcceptDrops(True)
    
            button = Button('Button', self)
            button.move(100, 65)
    
            self.buttons = [button]
    
            self.setWindowTitle('Copy or Move')
            self.setGeometry(300, 300, 280, 150)
    
    
        def dragEnterEvent(self, e):
            e.accept()
    
    
        def dropEvent(self, e):
            # get the relative position from the mime data
            mime = e.mimeData().text()
            x, y = map(int, mime.split(','))
    
            if e.keyboardModifiers() & QtCore.Qt.ShiftModifier:
                # copy
                # so create a new button
                button = Button('Button', self)
                # move it to the position adjusted with the cursor position at drag
                button.move(e.pos()-QtCore.QPoint(x, y))
                # show it
                button.show()
                # store it
                self.buttons.append(button)
                # set the drop action as Copy
                e.setDropAction(QtCore.Qt.CopyAction)
            else:
                # move
                # so move the dragged button (i.e. event.source())
                e.source().move(e.pos()-QtCore.QPoint(x, y))
                # set the drop action as Move
                e.setDropAction(QtCore.Qt.MoveAction)
            # tell the QDrag we accepted it
            e.accept()
    
    
    
    if __name__ == '__main__':
        app = QtGui.QApplication(sys.argv)
        ex = Example()
        ex.show()
        app.exec_()  
    
  2. ==============================

    2.PyQt5 및 Python 3에 맞게 수정 된 Avaris의 대답.

    PyQt5 및 Python 3에 맞게 수정 된 Avaris의 대답.

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    # Adapted for PyQt5 and Python 3 from Avaris' answer to
    # https://stackoverflow.com/questions/14395799/pyqt4-drag-and-drop
    
    import sys
    from PyQt5.QtWidgets import QPushButton, QWidget, QApplication
    from PyQt5.QtCore import Qt, QMimeData, QPoint
    from PyQt5.QtGui import QDrag, QPixmap, QPainter, QColor
    
    
    class Button(QPushButton):
        def mouseMoveEvent(self, e):
            if e.buttons() != Qt.RightButton:
                return
    
            # write the relative cursor position to mime data
            mimeData = QMimeData()
            # simple string with 'x,y'
            mimeData.setText('%d,%d' % (e.x(), e.y()))
    
            # let's make it fancy. we'll show a "ghost" of the button as we drag
            # grab the button to a pixmap
            pixmap = QWidget.grab(self)
    
            # below makes the pixmap half transparent
            painter = QPainter(pixmap)
            painter.setCompositionMode(painter.CompositionMode_DestinationIn)
            painter.fillRect(pixmap.rect(), QColor(0, 0, 0, 127))
            painter.end()
    
            # make a QDrag
            drag = QDrag(self)
            # put our MimeData
            drag.setMimeData(mimeData)
            # set its Pixmap
            drag.setPixmap(pixmap)
            # shift the Pixmap so that it coincides with the cursor position
            drag.setHotSpot(e.pos())
    
            # start the drag operation
            # exec_ will return the accepted action from dropEvent
            if drag.exec_(Qt.CopyAction | Qt.MoveAction) == Qt.MoveAction:
                print('moved')
            else:
                print('copied')
    
    
        def mousePressEvent(self, e):
            QPushButton.mousePressEvent(self, e)
            if e.button() == Qt.LeftButton:
                print('press')
    
    
    
    class Example(QWidget):
        def __init__(self):
            super(Example, self).__init__()
            self.initUI()
    
    
        def initUI(self):
            self.setAcceptDrops(True)
    
            button = Button('Button', self)
            button.move(100, 65)
    
            self.buttons = [button]
    
            self.setWindowTitle('Copy or Move')
            self.setGeometry(300, 300, 280, 150)
    
    
        def dragEnterEvent(self, e):
            e.accept()
    
    
        def dropEvent(self, e):
            # get the relative position from the mime data
            mime = e.mimeData().text()
            x, y = map(int, mime.split(','))
    
            if e.keyboardModifiers() & Qt.ShiftModifier:
                # copy
                # so create a new button
                button = Button('Button', self)
                # move it to the position adjusted with the cursor position at drag
                button.move(e.pos()-QPoint(x, y))
                # show it
                button.show()
                # store it
                self.buttons.append(button)
                # set the drop action as Copy
                e.setDropAction(Qt.CopyAction)
            else:
                # move
                # so move the dragged button (i.e. event.source())
                e.source().move(e.pos()-QPoint(x, y))
                # set the drop action as Move
                e.setDropAction(Qt.MoveAction)
            # tell the QDrag we accepted it
            e.accept()
    
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = Example()
        ex.show()
        app.exec_()
    
  3. from https://stackoverflow.com/questions/14395799/pyqt4-drag-and-drop by cc-by-sa and MIT license