QTableWidget实现拖动换行

import sys

from PyQt6.QtCore import Qt
from PyQt6.QtGui import QIntValidator, QDoubleValidator
from PyQt6.QtWidgets import QApplication, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget, QPushButton, QCheckBox, \
    QLineEdit, QStyledItemDelegate, QMessageBox


class FloatValidator(QDoubleValidator):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setDecimals(3)


class CustomDelegate(QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        if index.column() == 1:
            editor = QLineEdit(parent)
            editor.setValidator(QIntValidator())
            return editor
        elif index.column() == 2:
            editor = QLineEdit(parent)
            editor.setValidator(FloatValidator())
            return editor
        elif index.column() == 4:
            editor = QLineEdit(parent)
            editor.setValidator(QIntValidator(0, 9999))
            return editor
        return super().createEditor(parent, option, index)


class TableWidget(QTableWidget):
    def __init__(self, parent=None):
        super().__init__(0, 5, parent)
        self.setHorizontalHeaderLabels(['名字', '位置', '目标值', '状态', '延时读取'])

        # 启用拖放功能
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setDragDropMode(QTableWidget.DragDropMode.InternalMove)
        self.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
        self.setDropIndicatorShown(True)

    def dropEvent(self, event):
        try:
            #super().dropEvent(event)
            source_row = self.currentRow()
            target_row = self.indexAt(event.position().toPoint()).row()

            if target_row == -1 or source_row == -1 or source_row == target_row:
                event.ignore()
                return
            #event.accept()
            self.swap_rows(source_row, target_row)

        except Exception as e:
            # 捕获异常并显示警告
            QMessageBox.critical(self, "Error", f"An error occurred during row swapping: {str(e)}")

    def dragMoveEvent(self, event):
        event.accept()

    def swap_rows(self, source_row, target_row):
        if source_row == -1 or target_row == -1:
            return
        print(f"swap row{source_row} to {target_row}")

        # 遍历每列,获取源行和目标行的数据
        for col in range(self.columnCount()):
            source_item = self.takeItem(source_row, col)
            target_item = self.takeItem(target_row, col)
            if source_item is None or target_item is None:
                print(f"none item in column:{col}")
                continue
            self.setItem(source_row, col, target_item)
            self.setItem(target_row, col, source_item)
        for col in range(self.columnCount()):
            # 交换 cell widget
            #  FIXME:采用交换状态,直接交换widget会崩溃,不知道为啥
            source_checkbox = self.cellWidget(source_row, col)
            target_checkbox = self.cellWidget(target_row, col)
            if isinstance(source_checkbox, QCheckBox) and isinstance(target_checkbox, QCheckBox):
                # 复制状态
                source_state = source_checkbox.isChecked()
                target_state = target_checkbox.isChecked()

                source_checkbox.setChecked(target_state)
                target_checkbox.setChecked(source_state)

            print(f"swap row {source_row} to {target_row} col {col}")
        print(f"swap row{source_row} to {target_row} finished")  #  打印这个之后会崩溃


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

        self.table = TableWidget()
        self.table.setColumnWidth(0, 150)
        self.table.setColumnWidth(1, 100)
        self.table.setColumnWidth(2, 100)
        self.table.setColumnWidth(3, 80)
        self.table.setColumnWidth(4, 120)

        self.add_row_button = QPushButton("Add Row")
        self.add_row_button.clicked.connect(self.add_row)

        layout = QVBoxLayout()
        layout.addWidget(self.table)
        layout.addWidget(self.add_row_button)
        self.setLayout(layout)

    def add_row(self):
        row_position = self.table.rowCount()
        self.table.insertRow(row_position)

        name_item = QTableWidgetItem()
        self.table.setItem(row_position, 0, name_item)

        pos_item = QTableWidgetItem()
        pos_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
        self.table.setItem(row_position, 1, pos_item)

        target_item = QTableWidgetItem()
        target_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
        self.table.setItem(row_position, 2, target_item)

        status_checkbox = QCheckBox()
        self.table.setCellWidget(row_position, 3, status_checkbox)

        delay_item = QTableWidgetItem()
        delay_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
        self.table.setItem(row_position, 4, delay_item)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = TableWidgetApp()
    window.show()
    sys.exit(app.exec())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冥焱破晓

开发不易,写文章更难,感谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值