PyQt5 ile bir kod editörü yapmaya çalışıyorum. Ancak oluşturduğum QTextEdit widget’ında bir sorunla karşılaştım ve çözemedim. Enter tuşuna bastığımda kod tamamlama işlevini gerçekleştirmek yerine yeni satıra geçiyor. Ancak ben Enter tuşuna basıldığında tamamlamayı gerçekleştirmesini istiyorum (Enter yerine QCompleter’daki tuşlara bastığımda doğru çalışıyor).
kod:
from PyQt5.QtCore import QRect, QSize, Qt
from PyQt5.QtGui import QPainter, QTextCursor
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPlainTextEdit, QCompleter
from keyword import kwlist
class TextArea(QWidget):
def __init__(self, filePath: str, editorContent: str, parent=None):
super().__init__(parent)
self.filePath = filePath
self.fileName = filePath
self.editor = QPlainTextEdit(self)
self.editor.setPlainText(editorContent)
self.lineNumberArea = LineNumberArea(self.editor)
self.editor.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)
self.editor.textChanged.connect(self.updateLineNumberArea)
self.editor.verticalScrollBar().valueChanged.connect(self.updateLineNumberArea)
self.completer = QCompleter(kwlist)
self.completer.activated.connect(self.insert_completion)
self.completer.setWidget(self.editor)
self.completer.setCompletionMode(QCompleter.PopupCompletion)
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.editor.textChanged.connect(self.complete)
layout = QVBoxLayout(self)
layout.addWidget(self.editor)
self.setLayout(layout)
def insert_completion(self, completion):
tc = self.editor.textCursor()
extra = len(completion) - len(self.completer.completionPrefix())
tc.select(QTextCursor.WordUnderCursor)
tc.removeSelectedText()
tc.insertText(completion)
tc.movePosition(QTextCursor.EndOfWord)
tc.insertText(" ")
self.editor.setTextCursor(tc)
def text_under_cursor(self):
tc = self.editor.textCursor()
tc.select(QTextCursor.WordUnderCursor)
return tc.selectedText()
def complete(self):
prefix = self.text_under_cursor()
self.completer.setCompletionPrefix(prefix)
popup = self.completer.popup()
if self.completer.completionCount() == 0:
popup.hide()
return
popup.setCurrentIndex(self.completer.completionModel().index(0, 0))
cr = self.editor.cursorRect()
cr.setWidth(
self.completer.popup().sizeHintForColumn(0)
+ self.completer.popup().verticalScrollBar().sizeHint().width()
)
self.completer.complete(cr)
def keyPressEvent(self, event):
if self.completer.popup().isVisible() and event.key() in [
Qt.Key_Enter,
Qt.Key_Return,
Qt.Key_Up,
Qt.Key_Down,
Qt.Key_Tab,
Qt.Key_Backtab,
]:
event.ignore()
return
if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
if self.completer.popup().isVisible():
self.insert_completion(self.completer.currentCompletion())
self.completer.popup().hide()
return
super().keyPressEvent(event)
def changeContent(self, newContent):
self.editor.setPlainText(newContent)
def returnContent(self):
return self.editor.toPlainText()
def lineNumberAreaWidth(self):
digits = 4
max_num = max(1, self.editor.blockCount())
while max_num >= 10:
max_num /= 10
digits += 1
space = 10 + self.editor.fontMetrics().horizontalAdvance('9') * digits
return space
def resizeEvent(self, event):
super().resizeEvent(event)
cr = self.editor.contentsRect()
self.lineNumberArea.setGeometry(
QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height())
)
def updateLineNumberArea(self):
self.lineNumberArea.update()
def getFilePath(self):
return self.filePath
def getFileName(self):
return self.fileName
def returnText(self):
return self.editor.toPlainText()
def paste(self):
self.editor.paste()
def copy(self):
self.editor.copy()
def cut(self):
self.editor.cut()
def undo(self):
self.editor.undo()
def redo(self):
self.editor.redo()
class LineNumberArea(QWidget):
def __init__(self, editor):
super(LineNumberArea, self).__init__(editor)
self.editor = editor
def sizeHint(self):
return QSize(self.editor.lineNumberAreaWidth(), 0)
def paintEvent(self, event):
self.lineNumberAreaPaintEvent(event)
def lineNumberAreaPaintEvent(self, event):
painter = QPainter(self)
painter.fillRect(event.rect(), Qt.lightGray)
block = self.editor.firstVisibleBlock()
blockNumber = block.blockNumber()
top = round(self.editor.blockBoundingGeometry(block).translated(self.editor.contentOffset()).top())
bottom = top + round(self.editor.blockBoundingRect(block).height())
# Adjust spacing
left_margin = 5
right_margin = 5
while block.isValid() and top <= event.rect().bottom():
if block.isVisible() and bottom >= event.rect().top():
number = str(blockNumber + 1)
painter.setPen(Qt.black)
# Draw text with margins
painter.drawText(left_margin, top, self.width() - left_margin - right_margin,
self.editor.fontMetrics().height(), Qt.AlignRight, number)
block = block.next()
top = bottom
bottom = top + round(self.editor.blockBoundingRect(block).height())
blockNumber += 1