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())
