Как можно копировать с перетаскиванием из одного списка, но использовать перемещение для внутреннего перетаскивания

Мне нужно иметь возможность копировать элемент из одного listWidget в другой. Это достаточно легко сделать, но я не могу найти способ различать действия перетаскивания в зависимости от того, возник ли перетаскиваемый элемент в списке, в который он перетаскивается, без необходимости, возможно, переопределить почти каждую функцию перетаскивания с помощью моего своя. Когда я перетаскиваю элемент из одного списка в другой, я хочу его скопировать, но когда я перетаскиваю элемент в том же списке, я хочу его переместить.

Я искал возможность установки mimetypes, но затем мне нужно написать свое собственное событие mouseMoveEvent, чтобы, возможно, узнать, откуда перетаскиваемый элемент, но пока попытки это сломать все. Невозможно установить тип MIME для элемента без переопределения mouseMoveEvent?

Поскольку элементы, которые я перетаскиваю, настраиваются, мне нужно написать собственное определение, чтобы перестроить его, когда он будет перемещен или скопирован во второй список. С функциями перетаскивания по умолчанию все это отлично работает с внутренними перемещениями. Но до сих пор мне не удалось понять, как использовать функции перетаскивания по умолчанию, когда перетаскивание является внутренним перемещением, а затем переключиться на мою настраиваемую функцию, чтобы скопировать элемент, когда перетаскивание происходит из другого списка.

import sys
from PyQt4 import QtGui , QtCore


def main():

    app = QtGui.QApplication(sys.argv)

    w = QtGui.QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple')
    layout=QtGui.QHBoxLayout(w)
    dragList=DragDropListWidget()
    layout.addWidget(dragList)
    dragList.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
    dragList.name='dragList'
    dragList.populate(['one','two','three'])
    dragList2=DragDropListWidget()
    dragList2.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
    dragList2.name='dragList'


    layout.addWidget(dragList2)
    w.show()

    sys.exit(app.exec_())

class scriptsWidget(QtGui.QWidget):


    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self)

        self.name=''

        self.widget_QHBoxLayout = QtGui.QHBoxLayout(self)
        self.widget_QHBoxLayout.setSpacing(0)
        self.widget_QHBoxLayout.setContentsMargins(0, 0, 0, 0)

        self.name_QLabel = QtGui.QLabel(self)
        self.widget_QHBoxLayout.addWidget(self.name_QLabel)

        self.user_QLabel = QtGui.QLabel(self)
        self.widget_QHBoxLayout.addWidget(self.user_QLabel)

        self.widget_QHBoxLayout.setSpacing(0)
        self.widget_QHBoxLayout.setContentsMargins(0, 0, 0, 0)



    def setName(self,name):
        self.name_QLabel.setText(name)
        self.name=name

    def setUser(self,user):
        self.user_QLabel.setText(user)

class customQListWidgetItem(QtGui.QListWidgetItem):


    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self)
        self.name=''

    def setName(self,name):
        self.name=name   




class DragDropListWidget(QtGui.QListWidget):
    _drag_info = []
    def __init__(self, parent = None):

        super(DragDropListWidget, self).__init__(parent)


        self.name=''


    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(QtCore.Qt.CopyAction)
            event.accept()

        else:
            super(DragDropListWidget, self).dragMoveEvent(event)


    def dropEvent(self, event):
        if event.mimeData().hasText():
            event.setDropAction(QtCore.Qt.CopyAction)
            event.accept()
            links = []
            for url in event.mimeData().urls():
                links.append(str(url.toLocalFile()))
            self.emit(QtCore.SIGNAL("dropped"), links)

        else:
            event.setDropAction(QtCore.Qt.CopyAction)
            items = []
            for index in xrange(self.count()):
                items.append(self.item(index))

            super(DragDropListWidget, self).dropEvent(event)

            for index in xrange(self.count()):
                if self.item(index) not in items:
                    self.populateDrop(self.item(index), index, [self.item(index).data(QtCore.Qt.UserRole).toPyObject()])

    def populateDrop(self,item,row,items=[]):
        for i in items:
            widget = scriptsWidget()
            widget.setName(i)
            widget.setUser('x')
            self.takeItem(row)
            item = customQListWidgetItem()
            item.setName(i)
            item.setWhatsThis(i)
            data = (i)
            item.setData(QtCore.Qt.UserRole, data)
            self.insertItem (row, item)
            self.setItemWidget(item,widget)



    def populate(self,items=[]):
        self.clear()
        for i in items:
            print(i)
            widget = scriptsWidget()
            widget.setName(i)
            widget.setUser('x')
            item = customQListWidgetItem()
            item.setName(i)
            data = (i)
            item.setData(QtCore.Qt.UserRole, data)
            self.addItem(item)
            self.setItemWidget(item,widget)



if __name__ == '__main__':
    main()

person obfuscated    schedule 21.10.2016    source источник


Ответы (2)


Это то, что я придумал. Я устанавливаю переменную данных класса при щелчке по элементу, чтобы я мог сказать, откуда он появился, когда элемент был сброшен. Я пробовал использовать переменную класса внутри DragDropListWidget, но по какой-то причине она сохраняла только локальное имя текущего списка ... странно. Глобальная переменная тоже работает, но это нежелательно.

import sys
from PyQt4 import QtGui , QtCore

def main():

    app = QtGui.QApplication(sys.argv)

    w = QtGui.QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple')
    layout=QtGui.QHBoxLayout(w)
    dragList=DragDropListWidget()
    layout.addWidget(dragList)
    d=data()
    dragList.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
    dragList.name='dragList'
    dragList.populate(['one','two','three'])
    dragList.data=d
    dragList2=DragDropListWidget()
    dragList2.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
    dragList2.name='dragList2'
    dragList2.external='dragList2'
    dragList2.data=d


    layout.addWidget(dragList2)
    w.show()

    sys.exit(app.exec_())

class data(object):
    def __init__(self, parent=None):
        self.origin='new'




class scriptsWidget(QtGui.QWidget):


    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self)

        self.name=''

        self.widget_QHBoxLayout = QtGui.QHBoxLayout(self)
        self.widget_QHBoxLayout.setSpacing(0)
        self.widget_QHBoxLayout.setContentsMargins(0, 0, 0, 0)

        self.name_QLabel = QtGui.QLabel(self)
        self.widget_QHBoxLayout.addWidget(self.name_QLabel)

        self.user_QLabel = QtGui.QLabel(self)
        self.widget_QHBoxLayout.addWidget(self.user_QLabel)

        self.widget_QHBoxLayout.setSpacing(0)
        self.widget_QHBoxLayout.setContentsMargins(0, 0, 0, 0)



    def setName(self,name):
        self.name_QLabel.setText(name)
        self.name=name

    def setUser(self,user):
        self.user_QLabel.setText(user)

class customQListWidgetItem(QtGui.QListWidgetItem):


    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self)
        self.name=''
        self.list=''

    def setName(self,name):
        self.name=name   




class DragDropListWidget(QtGui.QListWidget):

    def __init__(self, parent = None):

        super(DragDropListWidget, self).__init__(parent)
        self._dropping = False
        self.itemPressed.connect(self.clicked)

        self.data=''

        self.name=''
        self.external=''
        self.internal=False

    def clicked(self):
        global origin 
        self.data.origin=self.name


    def dragMoveEvent(self, event):

        if event.mimeData().hasUrls():
            event.setDropAction(QtCore.Qt.CopyAction)
            event.accept()

        else:

            super(DragDropListWidget, self).dragMoveEvent(event)


    def dropEvent(self, event):

        if event.mimeData().hasText():
            event.setDropAction(QtCore.Qt.CopyAction)
            event.accept()
            links = []
            for url in event.mimeData().urls():
                links.append(str(url.toLocalFile()))
            self.emit(QtCore.SIGNAL("dropped"), links)

        else:
            if self.external is self.name and self.data.origin is not self.name:
                print('external')
                event.setDropAction(QtCore.Qt.CopyAction)
                items = []
                for index in xrange(self.count()):
                    items.append(self.item(index))
                print items

                super(DragDropListWidget, self).dropEvent(event)

                for index in xrange(self.count()):
                    if self.item(index) not in items:
                        print(index)
                        self.populateDrop(self.item(index), index, [self.item(index).data(QtCore.Qt.UserRole).toPyObject()])

            else:
                print('internal')
                event.setDropAction(QtCore.Qt.MoveAction)

                super(DragDropListWidget, self).dropEvent(event)

        self.data.origin = None       

    def populateDrop(self,item,row,items=[]):
        for i in items:
            widget = scriptsWidget()
            widget.setName(i)
            widget.setUser('x')
            self.takeItem(row)
            item = customQListWidgetItem()
            item.setName(i)
            item.setWhatsThis(i)
            item.list=self.name
            data = (i)
            item.setData(QtCore.Qt.UserRole, data)
            self.insertItem (row, item)
            self.setItemWidget(item,widget)



    def populate(self,items=[]):
        self.clear()
        for i in items:
            print(i)
            widget = scriptsWidget()
            widget.setName(i)
            widget.setUser('x')

            item = customQListWidgetItem()
            item.setName(i)
            item.list=self.name
            data = (i)
            item.setData(QtCore.Qt.UserRole, data)
            self.addItem(item)
            self.setItemWidget(item,widget)



if __name__ == '__main__':
    main()
person obfuscated    schedule 22.10.2016

Различить, исходит ли перетаскивание из этого виджета или из другого виджета, тривиально - просто используйте источник события в любом из событий перетаскивания / перетаскивания. Например:

void MyWidget::dragMoveEvent(QDragMoveEvent *event) 
{
    if (event->source() != this) {
        // the drag comes from another widget
    }
}
person Phil K    schedule 30.12.2020