按照网上打造了一个代码编辑器,奇怪的是,下拉菜单粘贴和键盘ctrl+v有效,而下拉菜单复制和键盘ctrl+c无效,我没有写任何这方面的代码,难道是QPlainTextEdit的bug?
class QPlainTextEditLineNum(QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.setLineWrapMode(QPlainTextEdit.NoWrap) # 不自动换行
self.lineNumberArea = LineNumPaint(self)
self.document().blockCountChanged.connect(self.update_line_num_width)
self.document().cursorPositionChanged.connect(self.highlightCurrentLine) # 高亮当前行
self.verticalScrollBar().sliderMoved.connect(self.scroll_event) # 滚动条移动更新行号
self.update_line_num_width()
self.highlightCurrentLine()
def highlightCurrentLine(self):
extraSelections = QTextEdit.extraSelections(QTextEdit())
if not self.isReadOnly():
selection = QTextEdit.ExtraSelection()
lineColor = QColor(Qt.yellow).lighter(160)
selection.format.setBackground(lineColor)
selection.format.setProperty(QTextFormat.FullWidthSelection, True)
selection.cursor = self.textCursor()
selection.cursor.clearSelection()
extraSelections.append(selection)
self.setExtraSelections(extraSelections)
def wheelEvent(self, d: QWheelEvent) -> None:
self.scroll_event(d)
super().wheelEvent(d)
def scroll_event(self, event: QWheelEvent=None):
self.lineNumberArea.update()
def keyPressEvent(self, e: QKeyEvent) -> None:
super().keyPressEvent(e)
self.lineNumberArea.update()
def mousePressEvent(self, e: 'QMouseEvent') -> None:
super().mousePressEvent(e)
self.update()
self.highlightCurrentLine()
def lineNumberAreaWidth(self):
block_count = self.document().blockCount()
max_value = max(1, block_count)
d_count = len(str(max_value))
_width = self.fontMetrics().width('9') * d_count + 5
return _width
def update_line_num_width(self):
self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0)
def resizeEvent(self, event):
super().resizeEvent(event)
cr = self.contentsRect()
self.lineNumberArea.setGeometry(QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height()))
def lineNumberAreaPaintEvent(self, event):
cursor = QTextCursor(self.document())
painter = QPainter(self.lineNumberArea)
painter.fillRect(event.rect(), Qt.lightGray)
line_height = self.fontMetrics().lineSpacing() # 包含行间距的行高
block_number = self.cursorForPosition(QPoint(0, int(line_height / 2))).blockNumber()
first_visible_block = self.document().findBlock(block_number)
blockNumber = block_number
cursor.setPosition(self.cursorForPosition(QPoint(0, int(line_height / 2))).position())
rect = self.cursorRect()
scroll_compensation = rect.y() - int(rect.y() / line_height) * line_height
top = scroll_compensation
last_block_number = self.cursorForPosition(QPoint(0, self.height() - 1)).blockNumber()
height = self.fontMetrics().height()
block = first_visible_block
while block.isValid() and (top <= event.rect().bottom()) and blockNumber <= last_block_number:
# cur_line_count = block.lineCount()
if block.isVisible():
number = str(blockNumber + 1)
painter.setPen(Qt.black)
# print((0, top, self.lineNumberArea.width(), height), number)
painter.drawText(0, top, self.lineNumberArea.width(), height, Qt.AlignCenter, number)
block = block.next()
top = top + line_height
blockNumber += 1
class LineNumPaint(QWidget):
def __init__(self, q_edit):
super().__init__(q_edit)
self.q_edit_line_num = q_edit
def sizeHint(self):
return QSize(self.q_edit.lineNumberAreaWidth(), 0)
def paintEvent(self, event):
self.q_edit_line_num.lineNumberAreaPaintEvent(event)
谢谢大神回复。
代码就是从网上复制来的,小白一个,暂时解决不了问题,继续求助网络
补充问题:
cut CTRL+X键页可以删去选择文本,就是系统剪切板内容没有变化,系统剪切板只可读不可写,有写保护系变量要打开吗?
一直没有留意,发现copy时出现
OleSetClipboard: Failed to set mime data (text/plain, text/html, application/vnd.oasis.opendocument.text) on clipboard: COM error 0xffffffff800401f0 CO_E_NOTINITIALIZED (Unknown error 0x0800401f0) (参数错误。)
有说是
它不能在子线程或者非gui线程下用,怎么办?
有说
看到这样一段网文,不知道怎样做,太小白了
文本的选择由QTextCursor类处理,该类提供创建选择,检索文本内容或删除选择的功能。您可以使用textCursor()方法检索与用户可见光标对应的对象。如果你想在QPlainTextEdit中设置一个选择,只需在QTextCursor对象上创建一个选择,然后使用setCursor()将该游标设置为可见光标。选择可以通过copy()复制到剪贴板,也可以用cut()剪切到剪贴板。