PyQt5系列教程(31): QPlainTextEdit
上期我们介绍了文本输入栏(QLineEdit),这期我们将介绍一下纯文本输入框(QPlainTextEdit)。好吧,这名字是我取得,是难听了点。
总体介绍
QPlainTextEdit类提供了一个用于编辑和显示纯文本的小部件。
介绍和概念
QPlainTextEdit是支持纯文本的高级查看器/编辑器。它经过优化处理大型文档并对用户输入做出快速响应。
QPlainText使用与QTextEdit相同的技术和概念,但是为纯文本处理进行了优化。
QPlainTextEdit适用于段落和字符。段落是一个格式化的字符串,它被字符包装以适应窗口小部件的宽度。默认情况下,当阅读纯文本时,一个换行符表示一个段落。文档由零个或多个段落组成。段落以强硬换行符分隔。段落中的每个字符都有其自己的属性,例如字体和颜色。
QPlainTextEdit上鼠标光标的形状默认为Qt. IBeamCursor。它可以通过viewport()的游标属性进行更改。
使用QPlainTextEdit作为显示小部件
使用setPlainText()来设置或替换文本,删除现有文本并将其替换为传递给setPlainText()的文本。
可以使用QTextCursor类或函数insertPlainText(),appendPlainText()或paste()插入文本。
默认情况下,文本编辑会以空格为间隔把单词包装在文本编辑小部件中。
setLineWrapMode()函数用于指定您想要的换行类型,WidgetWidth或NoWrap(如果不需要任何换行)。如果使用WrapgetWidth WidgetWidth的自动换行,则可以使用setWordWrapMode()指定是否在空白处或任何地方断开。
find()函数可用于查找和选择文本中的给定字符串。
如果您想限制QPlainTextEdit中段落的总数,因为它在日志查看器中很有用,那么您可以使用maximumBlockCount属性。 setMaximumBlockCount()和appendPlainText()的组合将QPlainTextEdit转换为日志文本的高效查看器。使用centerOnScroll()属性可以减少滚动,使日志查看器更快。文本可以通过有限的方式进行格式化,可以使用语法高亮显示,也可以使用appendHtml()附加HTML格式的文本。尽管QPlainTextEdit不支持使用表格和浮点数进行复杂的富文本渲染,但它支持您在日志查看器中可能需要的有限段落格式。
只读型键盘组合
当使用QPlainTextEdit时,只读键绑定仅限于导航,并且文本只能用鼠标选择:
使用QPlainTextEdit作为编辑器
关于使用QPlainTextEdit作为显示小部件的所有信息也适用于此处。
文本的选择由QTextCursor类处理,该类提供创建选择,检索文本内容或删除选择的功能。您可以使用textCursor()方法检索与用户可见光标对应的对象。如果你想在QPlainTextEdit中设置一个选择,只需在QTextCursor对象上创建一个选择,然后使用setCursor()将该游标设置为可见光标。选择可以通过copy()复制到剪贴板,也可以用cut()剪切到剪贴板。整个文本可以使用selectAll()来选择。
QPlainTextEdit包含一个可以使用document()方法检索的QTextDocument对象。您也可以使用setDocument()设置自己的文档对象。如果文本改变,QTextDocument将发出一个textChanged()信号,并且它还提供了一个isModified()函数,如果文本自加载或自从上次调用setModified并将其作为参数调用后,将返回true。另外它提供了撤销和重做的方法。
语法高亮
就像QTextEdit一样,QPlainTextEdit和QSyntaxHighlighter一起工作。
可编辑键盘组合
用于编辑的键绑定列表:
与QTextEdit的差异
QPlainTextEdit是一个很单一的类,通过使用QTextEdit和QTextDocument背后的大部分技术来实现。它的性能优于QTextEdit,主要是在文本文档上使用称为QPlainTextDocumentLayout的另一种简化文本布局。纯文本文档布局不支持表格或嵌入帧,并且逐行逐行滚动方式替换像素精确高度计算。这使得可以处理更大的文档,并且仍然可以实时启用换行来调整编辑器的大小。它还可以用于快速日志查看器。
一句话对于纯文本,QPlainTextEdit更合适!
类归属
PyQt5->QtWidgets->QPlainTextEdit
继承关系
继承:QAbstractScrollArea
更多详细的介绍请见官网:
小例子
本期小例子来源于github,作者:Ivan Luchko,具体网址我不记得了。
这个例子我觉得挺好的,没有必要再单独写一个了,所以本期我们一起来学习一下这个例子。为便于学习,我做了部分修改:
- 删除了与本次知识点无关的内容
- 修改了原作品中存在的bug
总体的效果图如下:
在这个程序当中我们实现了:
- 行号
- 在当前行时有黄色的标记
核心代码讲解
在正式讲解之前,我们简单的介绍一下Python当中关于嵌套类的概念。嵌套类,(=@__@=)这个东东是什么?我们举个生活中的例子吧,如下图:
从上图中我们了解到老司机和汽车之间的关系,以及作为一个整体的作用。下面我们运行面向对象的编程方法抽象这一生活中的实际例子。
#coding=utf-8
class RunningCar:
class VeteranDriver:
def __init__(self, car):
self.car = car
def action(self, action):
if action == 'startup':
self.car.startup()
elif action == 'stop':
self.car.stop()
elif action == 'turn':
self.car.turn()
def __init__(self):
self.veterandriver = self.VeteranDriver(self)
def cmd(self, cmd):
self.veterandriver.action(cmd)
def startup(self):
print('\n老司机:没时间解释了,快上车!\n')
def stop(self):
print('\n滴嘟..滴嘟..滴嘟..请让一让,这里是车祸现场,大家不要围观!\n')
def turn(self):
print('\n我靠,车翻了~〒_〒!\n')
car = RunningCar()
while True:
cmd = input("汽车待命中,请输入指令('startup','stop','turn')->")
if cmd == 'stop':
car.cmd(cmd)
break
car.cmd(cmd)
上面这段代码就是一个类中类的例子了。我们新建了一个汽车RunningCar类,在这个类中我们还有一个类就是老司机VeteranDriver类。
一个汽车肯定是可以 启动、停车、转弯 的。这三个方法是汽车应该有的功能。但是现在无人汽车技术还不成熟啊,所以老司机就有作用了,老司机发出具体的命令然后汽车去执行。
老司机发出指令: 启动、转弯、停车 ,调用的是汽车的这三个方法。即内部类调用外部类的方法。
class VeteranDriver:
def __init__(self, car):
self.car = car
def action(self, action):
if action == 'startup':
self.car.startup()
elif action == 'stop':
self.car.stop()
elif action == 'turn':
self.car.turn()
当然我这里描述的是比较简答,举的例子也是简单的,很多特殊的情况也没有考虑。
我们在实例化RunningCar类的同时会产生VeteranDriver对象
def __init__(self):
self.veterandriver = self.VeteranDriver(self)
然后通过VeteranDriver对象调用其方法,例如代码中
def cmd(self, cmd):
self.veterandriver.action(cmd)
不知道大家了解内部类、外部类的关系没有。把效果给大家演示一下(图形化界面):
为什么要说这个呢,因为我们实现QPlainTextEdit的功能中,用到了这个方法。我把大致的代码给大家演示一下:
class QCodeEditor(QPlainTextEdit):
class NumberBar(QWidget):
def __init__(self, editor):
QWidget.__init__(self, editor)
self.editor = editor
self.editor.blockCountChanged.connect(self.updateWidth)
self.editor.updateRequest.connect(self.updateContents)
self.font = QFont()
self.numberBarColor = QColor("#e8e8e8")
def paintEvent(self, event):
def getWidth(self):
def updateWidth(self):
def updateContents(self, rect, dy):
def __init__(self):
super(QCodeEditor, self).__init__()
self.setWindowTitle('微信公众号:学点编程吧--带行号和颜色的文本框')
self.setFont(QFont("Ubuntu Mono", 12))
self.setLineWrapMode(QPlainTextEdit.NoWrap)
self.number_bar = self.NumberBar(self)
self.currentLineNumber = None
self.cursorPositionChanged.connect(self.highligtCurrentLine)
self.setViewportMargins(40, 0, 0, 0)
self.highligtCurrentLine()