I am using QTableWidget to creating something like excel. One of the QTableWidget column is able to let user update note with multiple line. Before use QTextEdit, user need to manually add " \n" to achieve multiple line, but this is not friendly user. I found out I can set QTextEdit into QTableWidget. By using QTextEdit, I able to type multiple line by press "Enter" or "Shift+Enter". However, I want when "Shift+Enter" is pressed, it go to next line but when "Enter" is pressed, it run self.update_MySQL function.
Below is my sample code
import sys, itertools, sip
sip.setapi('QVariant',2)
from PyQt4 import QtCore, QtGui
class CustomTextEditDelegate(QtGui.QItemDelegate):
def createEditor(self, parent, option, index):
editor = QtGui.QTextEdit(parent)
return editor
def setEditorData(self, editor, index):
editor.setText(index.data())
def setModelData(self, editor, model, index):
model.setData(index, editor.toPlainText())
class PIX_DATABASE_UI(QtGui.QTableWidget):
def __init__(self, parent=None):
super(PIX_DATABASE_UI, self).__init__(parent)
### signal
self.update_tableWidget()
self.itemEntered.connect(self.update_MySQL)
# -----------------------------------------------------------------------------------------------------------------#
def update_MySQL(self):
print "MySQL Updated"
def update_tableWidget(self):
self.filter_columns = [u'remark']
self.setColumnCount(len(self.filter_columns))
self.setHorizontalHeaderLabels(self.filter_columns)
self.setRowCount(5)
for row, col in itertools.product(range(5), range(len(self.filter_columns))):
if self.filter_columns[col] == "remark":
width = self.sizeHint().width()
self.setColumnWidth(col, width * 0.75)
self.setItem(row, col, QtGui.QTableWidgetItem(str("ABC")))
self.setItemDelegateForColumn(col, CustomTextEditDelegate(self))
self.verticalHeader().setResizeMode(row, QtGui.QHeaderView.ResizeToContents)
# -----------------------------------------------------------------------------------------------------------------#
# -----------------------------------------------------------------------------------------------------------------#
if __name__ == '__main__':
global ui
try:
ui.close()
except:
pass
app = QtGui.QApplication(sys.argv)
app.setStyle(QtGui.QStyleFactory.create("Plastique"))
# print QtGui.QStyleFactory.keys()
ui = PIX_DATABASE_UI()
ui.show()
sys.exit(app.exec_())
Conclusion:
Thanks eyllanesc, the code is help me to achieve what I want to achieve with slightly modify to the keyPressEvent. Original code is still emit even I press "Shift + Enter". Below code is what I modified.
def keyPressEvent(self, event):
modifiers = QtGui.QApplication.keyboardModifiers()
if modifiers != QtCore.Qt.ShiftModifier and event.key() == QtCore.Qt.Key_Return:
self.enter.emit()
# If you do not want a new line uncomment the following
# return
super(TextEdit, self).keyPressEvent(event)
So now, after edit in textEdit and press "Enter", it will run self.update_MySQL and when press "Shift + Enter", it will go to next line.
What you can do is that the data of the model is updated and for this the commitData
signal calling the setModelData()
method must be emited.
By doing this you can use the signal itemChanged()
because the data of the item is modified.
import sys, itertools, sip
sip.setapi('QVariant',2)
from PyQt4 import QtCore, QtGui
class TextEdit(QtGui.QTextEdit):
pressed = QtCore.pyqtSignal()
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Return:
self.pressed.emit()
# If you do not want a new line uncomment the following
# return
super(TextEdit, self).keyPressEvent(event)
class CustomTextEditDelegate(QtGui.QItemDelegate):
def createEditor(self, parent, option, index):
editor = TextEdit(parent)
editor.pressed.connect(self.commitAndCloseEditor)
return editor
def setEditorData(self, editor, index):
editor.setText(index.data())
def setModelData(self, editor, model, index):
model.setData(index, editor.toPlainText())
def commitAndCloseEditor(self):
editor = self.sender()
self.commitData.emit(editor)
# if you want to close the editor uncomment the following
# self.closeEditor.emit(editor, QtGui.QAbstractItemDelegate.NoHint)
class PIX_DATABASE_UI(QtGui.QTableWidget):
def __init__(self, parent=None):
super(PIX_DATABASE_UI, self).__init__(parent)
### signal
self.update_tableWidget()
self.itemEntered.connect(self.update_MySQL)
self.itemChanged.connect(self.update_MySQL)
# -----------------------------------------------------------------------------------------------------------------#
def update_MySQL(self, it):
print("MySQL Updated", it.text())
def update_tableWidget(self):
self.filter_columns = [u'remark']
self.setColumnCount(len(self.filter_columns))
self.setHorizontalHeaderLabels(self.filter_columns)
self.setRowCount(5)
for row, col in itertools.product(range(5), range(len(self.filter_columns))):
if self.filter_columns[col] == "remark":
width = self.sizeHint().width()
self.setColumnWidth(col, width * 0.75)
self.setItem(row, col, QtGui.QTableWidgetItem(str("ABC")))
self.setItemDelegateForColumn(col, CustomTextEditDelegate(self))
self.verticalHeader().setResizeMode(row, QtGui.QHeaderView.ResizeToContents)
# -----------------------------------------------------------------------------------------------------------------#
# -----------------------------------------------------------------------------------------------------------------#
if __name__ == '__main__':
global ui
try:
ui.close()
except:
pass
app = QtGui.QApplication(sys.argv)
app.setStyle(QtGui.QStyleFactory.create("Plastique"))
# print QtGui.QStyleFactory.keys()
ui = PIX_DATABASE_UI()
ui.show()
sys.exit(app.exec_())