Python 在两个单独的QtableWidget之间拖放行

Python 在两个单独的QtableWidget之间拖放行,python,drag-and-drop,pyqt,pyqt4,qtablewidget,Python,Drag And Drop,Pyqt,Pyqt4,Qtablewidget,背景: 我的主窗口上有两个独立的QTableWidgets。它们都是在python中动态添加的。我已经实现了pyqt代码,可以在three_Pinepples解决方案中找到 我的问题 我希望能够将表行从一个表拖放到另一个表。例如: 如果我试图将项目B从左表拖动到右表 这就是结果 关于如何获得这种期望的行为,有什么建议吗?我看了一下@three_Pinepples的代码,不理解其中的一半,就把它删除了。可用于多行选择 import sys from PyQt4.QtGui import *

背景:

我的
主窗口上有两个独立的
QTableWidget
s。它们都是在python中动态添加的。我已经实现了pyqt代码,可以在three_Pinepples解决方案中找到

我的问题

我希望能够将表行从一个表拖放到另一个表。例如:

如果我试图将项目B从左表拖动到右表

这就是结果


关于如何获得这种期望的行为,有什么建议吗?

我看了一下@three_Pinepples的代码,不理解其中的一半,就把它删除了。可用于多行选择

import sys
from PyQt4.QtGui import *

class TableWidgetDragRows(QTableWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setDragDropOverwriteMode(False)
        # self.setSelectionMode(QAbstractItemView.SingleSelection)

        self.last_drop_row = None

    # Override this method to get the correct row index for insertion
    def dropMimeData(self, row, col, mimeData, action):
        self.last_drop_row = row
        return True


    def dropEvent(self, event):
        # The QTableWidget from which selected rows will be moved
        sender = event.source()

        # Default dropEvent method fires dropMimeData with appropriate parameters (we're interested in the row index).
        super().dropEvent(event)
        # Now we know where to insert selected row(s)
        dropRow = self.last_drop_row

        selectedRows = sender.getselectedRowsFast()

        # Allocate space for transfer
        for _ in selectedRows:
            self.insertRow(dropRow)

        # if sender == receiver (self), after creating new empty rows selected rows might change their locations
        sel_rows_offsets = [0 if self != sender or srow < dropRow else len(selectedRows) for srow in selectedRows]
        selectedRows = [row + offset for row, offset in zip(selectedRows, sel_rows_offsets)]

        # copy content of selected rows into empty ones
        for i, srow in enumerate(selectedRows):
            for j in range(self.columnCount()):
                item = sender.item(srow, j)
                if item:
                    source = QTableWidgetItem(item)
                    self.setItem(dropRow + i, j, source)

        # delete selected rows
        for srow in reversed(selectedRows):
            sender.removeRow(srow)

        event.accept()


    def getselectedRowsFast(self):
        selectedRows = []
        for item in self.selectedItems():
            if item.row() not in selectedRows:
                selectedRows.append(item.row())
        selectedRows.sort()
        return selectedRows


class Window(QWidget):
    def __init__(self):
        super().__init__()

        layout = QHBoxLayout()
        self.setLayout(layout)

        self.table_widgets = []
        for _ in range(3):
            tw = TableWidgetDragRows()
            tw.setColumnCount(2)
            tw.setHorizontalHeaderLabels(['Colour', 'Model'])

            self.table_widgets.append(tw)
            layout.addWidget(tw)

        filled_widget = self.table_widgets[0]
        items = [('Red', 'Toyota'), ('Blue', 'RV'), ('Green', 'Beetle')]
        for i, (colour, model) in enumerate(items):
            c = QTableWidgetItem(colour)
            m = QTableWidgetItem(model)

            filled_widget.insertRow(filled_widget.rowCount())
            filled_widget.setItem(i, 0, c)
            filled_widget.setItem(i, 1, m)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())
导入系统 从PyQt4.QtGui导入* 类TableWidgetDragRows(QTableWidget): 定义初始化(self,*args,**kwargs): super() self.setDragEnabled(真) self.setAcceptDrops(真) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setDragDropOverwriteMode(False) #self.setSelectionMode(QAbstractItemView.SingleSelection) self.last\u drop\u row=无 #重写此方法以获取正确的插入行索引 def dropMimeData(自身、行、列、mimeData、操作): self.last\u drop\u row=行 返回真值 def dropEvent(自身,事件): #将从中移动选定行的QTableWidget sender=event.source() #默认的dropEvent方法使用适当的参数触发dropMimeData(我们对行索引感兴趣)。 super().dropEvent(事件) #现在我们知道了在何处插入选定行 dropRow=自我。最后一行 selectedRows=sender.getselectedRowsFast() #分配空间进行转移 对于选定的箭头中的uu: self.insertRow(dropRow) #如果sender==receiver(self),则在创建新的空行后,所选行可能会更改其位置 sel_rows_offset=[0如果self!=发送方或srow
这似乎确实有效,但是我建议您在创建和设置
QTableWidgetItem
之前添加一个检查。此检查将简单地读取:
如果(sender.item(srow,j)不是None):
否则,如果行中的一个单元格为空,则在删除时会丢失主要数据。谢谢你的回答,我会把它标记为正确的。@sudobangbang谢谢你的评论。我忽略了这个问题,它发生在Python2上,默认情况下使用旧的PyQt API v1。已添加支票。