#!/usr/bin/env python3 from PyQt6.QtCore import Qt, QEvent, QObject from PyQt6.QtWidgets import ( QAbstractItemView, QApplication, QMainWindow, QMessageBox, QPlainTextEdit, QStyledItemDelegate, QTableWidget, QTableWidgetItem, ) from PyQt6.QtGui import QKeyEvent from typing import cast class EscapeDelegate(QStyledItemDelegate): def __init__(self, parent=None): super().__init__(parent) def createEditor(self, parent, option, index): return QPlainTextEdit(parent) def eventFilter(self, editor: QObject, event: QEvent): """By default, QPlainTextEdit doesn't handle enter or return""" print("EscapeDelegate event handler") if event.type() == QEvent.Type.KeyPress: key_event = cast(QKeyEvent, event) if key_event.key() == Qt.Key.Key_Return: if key_event.modifiers() == (Qt.KeyboardModifier.ControlModifier): print("save data") self.commitData.emit(editor) self.closeEditor.emit(editor) return True elif key_event.key() == Qt.Key.Key_Escape: discard_edits = QMessageBox.question( self.parent(), "Abandon edit", "Discard changes?" ) if discard_edits == QMessageBox.StandardButton.Yes: print("abandon edit") self.closeEditor.emit(editor) return True return False class MyTableWidget(QTableWidget): def __init__(self, parent=None): super().__init__(parent) self.setItemDelegate(EscapeDelegate(self)) # self.setEditTriggers(QAbstractItemView.EditTrigger.DoubleClicked) class MainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.table_widget = MyTableWidget(self) self.table_widget.setRowCount(2) self.table_widget.setColumnCount(2) for row in range(2): for col in range(2): item = QTableWidgetItem() item.setText(f"Row {row}, Col {col}") self.table_widget.setItem(row, col, item) self.setCentralWidget(self.table_widget) self.table_widget.resizeColumnsToContents() self.table_widget.resizeRowsToContents() if __name__ == "__main__": app = QApplication([]) window = MainWindow() window.show() app.exec()