#pyqt5# 在 QTablewidget控件中 通过鼠标拖动实现 改变行索引 或 列索引

通过重写 QTablewidget 控件,可以实现鼠标拖动改变列索引或行索引

1.鼠标拖动列表元素改变行索引:

class TableWidget(QTableWidget):
# class Label(QWidget,QPainter):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.viewport().setAcceptDrops(True)
        self.setDragDropOverwriteMode(False)
        self.setDropIndicatorShown(True)

        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setDragDropMode(QAbstractItemView.InternalMove)

	def dropEvent(self, event):
		  if event.source() == self:
		      rows = set([mi.row() for mi in self.selectedIndexes()])
		      targetRow = self.indexAt(event.pos()).row()
		      rows.discard(targetRow)
		      rows = sorted(rows)
		      if not rows:
		          return
		      if targetRow == -1:
		          targetRow = self.rowCount()
		      for _ in range(len(rows)):
		          self.insertRow(targetRow)
		      rowMapping = dict() # Src row to target row.
		      for idx, row in enumerate(rows):
		          if row < targetRow:
		              rowMapping[row] = targetRow + idx
		          else:
		              rowMapping[row + len(rows)] = targetRow + idx
		      colCount = self.columnCount()
		      for srcRow, tgtRow in sorted(rowMapping.iteritems()):
		          for col in range(0, colCount):
		              self.setItem(tgtRow, col, self.takeItem(srcRow, col))
		      for row in reversed(sorted(rowMapping.iterkeys())):
		          self.removeRow(row)
		      event.accept()
		      return

    def drop_on(self, event):
        index = self.indexAt(event.pos())
        if not index.isValid():
            return self.rowCount()
            print("drop_on_return:",self.rowCount())

        return index.row() + 1 if self.is_below(event.pos(), index) else index.row()


    def is_below(self, pos, index):
        rect = self.visualRect(index)
        margin = 2
        if pos.y() - rect.top() < margin:
            return False
        elif rect.bottom() - pos.y() < margin:
            return True
        # noinspection PyTypeChecker
        return rect.contains(pos, True) and not (
                    int(self.model().flags(index)) & Qt.ItemIsDropEnabled) and pos.y() >= rect.center().y()

2. 鼠标拖动列表元素改变列索引:

class TableWidget(QTableWidget):
# class Label(QWidget,QPainter):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.viewport().setAcceptDrops(True)
        self.setDragDropOverwriteMode(False)
        self.setDropIndicatorShown(True)

        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setDragDropMode(QAbstractItemView.InternalMove)


    def dropEvent(self, event: QDropEvent):
        print("*******")
        if not event.isAccepted() and event.source() == self:
            print("in*******")
            drop_row = self.drop_on(event)
            print(drop_row)
            rows = sorted(set(item.row() for item in self.selectedItems())) #所有要移动的行
            rows_to_move = [
                [QTableWidgetItem(self.item(row_index, column_index)) for column_index in range(self.columnCount())]
                for row_index in rows]
            print(rows_to_move )
            for row_index in reversed(rows):
                self.removeRow(row_index)
                if row_index < drop_row:
                    drop_row -= 1
            print("row",self.rowCount())
            for row_index, data in enumerate(rows_to_move):
                row_index += drop_row
                self.insertRow(row_index)
                for column_index, column_data in enumerate(data):
                    self.setItem(row_index, column_index, column_data)
            print("row",self.rowCount())
            event.accept()
            for row_index in range(len(rows_to_move)):
                self.item(drop_row + row_index, 0).setSelected(True)
                # self.item(drop_row + row_index, 1).setSelected(True)
            print("row",self.rowCount())
        # super().dropEvent(event)
        print("row", self.rowCount())

    def drop_on(self, event):
        index = self.indexAt(event.pos())
        if not index.isValid():
            return self.rowCount()
            print("drop_on_return:",self.rowCount())

        return index.row() + 1 if self.is_below(event.pos(), index) else index.row()


    def is_below(self, pos, index):
        rect = self.visualRect(index)
        margin = 2
        if pos.y() - rect.top() < margin:
            return False
        elif rect.bottom() - pos.y() < margin:
            return True
        # noinspection PyTypeChecker
        return rect.contains(pos, True) and not (
                    int(self.model().flags(index)) & Qt.ItemIsDropEnabled) and pos.y() >= rect.center().y()

你可能感兴趣的:(Pyqt5,python编程)