我想制作像MicroSoft Word这样的TextEditer。 我已经制作了一个丰富的TextEditer。但它并不是很复杂。它可以编辑文本。 我的发短信目前可以做如下。
基本功能
1.color change
2.pointsize change
3.打印出
4.像Microsoft Word一样的分页
5.坐标保证金
6.搜索&替换单词
7.copy&糊
8.expanding& shlinking
9.save&负载
10.undo&重做
我想添加更复杂的功能。
1.Ruby Characters(我已安装)
2.Kumimoji角色(我还没有安装它,但我想我能做到。)
3.Tatenakayoko(与Kumimoji有一点差别)
4.Bunchu(Kacchu)(与Kumimoji有一点差别)
5.表达像Tex / LaTex这样的数学公式。
Tex / LaTex非常漂亮。我希望我能做到这一点。
总之,我想表达排版。
其他
1.插入类似Microsoft Word的文本表。
Introductions & Explanations of inserting texttables in Japanese
2.插入许多图表,如三角形,正方形,圆形,椭圆形等。
3.在东亚文字中垂直写作。
我想做上述事情。
我盲目搜索。
作为我的第一步,我尝试对QTextDocumentLayout进行子分类。此处的代码。
from PySide import QtCore
from PySide import QtGui
import sys
class TextEdit(QtGui.QTextEdit):
def __init__(self,parent=None):
super(TextEdit,self).__init__(parent=None)
self.customDocumentLayout = CustomDocumentLayout(self.document())
self.customDocumentLayout.setPaintDevice(self.viewport())
self.document().setDocumentLayout(self.customDocumentLayout)
self.document().setPageSize(QtCore.QSizeF(797,1123))
self.tcf = TextCharFormatObjectInterface()
self.document().documentLayout().registerHandler(QtGui.QTextFormat.UserObject+1,self.tcf)
def keyPressEvent(self,event):
if event.key() == QtCore.Qt.Key_0:
print(16,self.toPlainText())
char = QtGui.QTextCharFormat()
char.setObjectType(QtGui.QTextFormat.UserObject+1)
char.setProperty(1,event.text())
tc = self.textCursor()
tc.insertText("\ufffc",char)
# return QtGui.QTextEdit.keyPressEvent(self,event)
class TextCharFormatObjectInterface(QtGui.QPyTextObject):
def __init__(self,parent=None):
super(TextCharFormatObjectInterface,self).__init__(parent=None)
def intrinsicSize(self,doc,posInDocument,format):
try:
char = format.toCharFormat()
f_m = QtGui.QFontMetrics(char.font())
rectF = f_m.boundingRect(char.property(1))
size = rectF.size()
return size
except Exception as e:
print(42,e)
def drawObject(self,painter,rect,doc,posInDocument,format):
try:
font = painter.font()
font.setPointSize(int(font.pointSize()))
painter.setFont(font)
painter.drawText(rect,format.property(1))
except Exception as e:
print(24,e)
class CustomDocumentLayout(QtGui.QAbstractTextDocumentLayout):
def __init__(self,doc):
super(CustomDocumentLayout,self).__init__(doc)
def resizeInlineObject(self,item,posInDocument,format):
try:
char = format.toCharFormat()
if not char.isValid():
return
handler = self.handlerForObject(char.objectType())
size = handler.intrinsicSize(self.document(),posInDocument,format)
item.setAscent(size.height())
item.setWidth(size.width())
item.setDescent(0)
except Exception as e:
print(62,e)
def positionInlineObject(self,item, posInDocument, format):
print(68,item)
def drawInlineObject(self,painter,rect,object,posInDocument,format):
try:
print(75,object,rect,format.property(1),painter.viewport())
char = format.toCharFormat()
if not char.isValid():
return
painter.setViewport(QtCore.QRect(0,0,self.document().pageSize().width(),self.document().pageSize().height()))
painter.drawText(rect,format.property(1))
self.update.connect("QRect()")
# handler = self.handlerForObject(format.objectType())
# handler.drawObject(painter,rect,self.document(),posInDocument,format)
except Exception as e:
print(76,e)
def hitTest(self,point,accuracy):
print(44,point,accuracy)
return accuracy
def documentChanged(self,fr, charsRemoved, charsAdded):
print(83,fr,charsRemoved,charsAdded)
self.documentSizeChanged.connect("QSizeF()")
def documentSize(self):
print("documentSize",self.document().pageSize())
return self.document().pageSize()#
def blockBoundingRect(self,block):
try:
block.setVisible(True)
self.documentSizeChanged.connect("QSizeF()")
self.updateBlock.connect("QTextBlock()")
layout = QtGui.QTextLayout(block)
layout.beginLayout()
line = layout.createLine()
line.setPosition(QtCore.QPointF(0,0))
line.setLineWidth(300)
s = line.xToCursor(0,QtGui.QTextLine.CursorBetweenCharacters)
print(88,"ラインのナチュラルレクト",line.naturalTextRect(),"レクト",line.rect())
#なぜか、このドローカーソルとの順序を逆にすると墜落。
layout.endLayout()
painter = QtGui.QPainter(self.paintDevice())
painter.setViewport(self.paintDevice().geometry())
painter.begin(self.paintDevice())
print(100,self.paintDevice().geometry(),self.paintDevice())
print(123,"painter-viewport",painter.viewport())
pen = painter.pen()
pen.setWidth(1)
pen.setStyle(QtCore.Qt.SolidLine)
pen.setColor(QtCore.Qt.black)
painter.setPen(pen)
brush = painter.brush()
brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern)
brush.setColor(QtCore.Qt.black)
painter.setBrush(brush)
line.draw(painter,QtCore.QPointF(0,0))
layout.drawCursor(painter,QtCore.QPointF(0,0),1,2)
layout.draw(painter,QtCore.QPointF(0,0))
painter.end()
boundingRect = layout.boundingRect()
return boundingRect
except Exception as e:
print(97,e)
#
def draw(self,painter,context):
try:
pen = painter.pen()
pen.setWidth(1)
pen.setColor(QtCore.Qt.black)
painter.setPen(pen)
brush = painter.brush()
brush.setColor(QtCore.Qt.black)
brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern)
painter.setBrush(brush)
print(painter,painter.font(),painter.brush(),painter.pen(),painter.viewport())
self.update.connect("QRectF()")
self.documentSizeChanged.connect("QSizeF()")
self.pageCountChanged.connect("int()")
except Exception as e:
print(47,e)
def main():
try:
QtGui.QApplication([])
except Exception as e:
print(18,e)
textedit = TextEdit()
textedit.show()
sys.exit(QtGui.QApplication.exec_())
if __name__ == "__main__":
main()
我不知道该怎么办。 此代码可以正常运行。 但它完全没用。 无论如何,我想知道解决方案。你有什么想法吗?
我希望我能知道这些事情。
我想知道哪个有利于实现我的目的。 我想充分了解这些课程。
1.我了解如何对QAbstractTextDocumentLayout进行细分
2.我了解如何使用QTextBlockUserData
3.我了解如何使用QTextLayout.formatRange
4.我了解如何使用QTextLayout.setAdditionalFormat
5.我了解如何使用QTextObjectInterface(我在日语SOF中理解。)
6.我了解相关的事情。
我该怎么办? PySide& Qt Reference没有显示任何可以理解的例子。
发展环境:Python 3.6.3
PySide 1.2.4
(已添加21/2/2018)
(drawInlineObject)默认实现在对象处理程序上调用drawObject()。仅在Qt内调用此函数。子类可以重新实现此函数以自定义内联对象的绘制。
(resizeInlineObject)默认实现将项目的大小调整为对象处理程序的intrinsicSize()函数返回的大小。仅在Qt内调用此函数。子类可以重新实现此函数以自定义内联对象的大小调整。
也就是说,如果我们想要转换我们的内联文本,我们需要ObjectReplacementCharacter(/ uFFFC),因为只有/ uFFFC可以调用drawObject()& intrinsicSize()方法。 我在这里重写了一遍。
def resizeInlineObject(self,item,posInDocument,format):
try:
char = format.toCharFormat()
if not char.isValid():
return
handler = self.handlerForObject(char.objectType())
size = handler.intrinsicSize(self.document(),posInDocument,format)
return size
except Exception as e:
print(62,e)
def drawInlineObject(self,painter,rect,object,posInDocument,format):
try:
char = format.toCharFormat()
if not char.isValid():
return
handler = self.handlerForObject(char.objectType())
handler.drawObject(painter,rect,self.document(),posInDocument,format)
except Exception as e:
print(76,e)
我还重写了blockBoundingRect方法。
def blockBoundingRect(self,block):
try:
boundingRect = block.layout().boundingRect()
height = 0
leading = 16
boundingRect.setRect(0,0,self.document().pageSize().width(),18)
layout = QtGui.QTextLayout(block)
layout.beginLayout()
while True:
line = layout.createLine()
if not line.isValid():
break
height += leading
line.setPosition(QtCore.QPointF(0,height))
line.setLineWidth(797)
height += line.height()
layout.endLayout()
painter = QtGui.QPainter(self.paintDevice())
pen = painter.pen()
pen.setWidth(1)
pen.setColor(QtCore.Qt.black)
painter.setPen(pen)
brush = painter.brush()
brush.setColor(QtCore.Qt.black)
brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern)
painter.setBrush(brush)
layout.draw(painter, QtCore.QPointF(0, 0))
layout.drawCursor(painter,QtCore.QPointF(0,0),1)
self.emit(QtCore.SIGNAL("updateBlock(block)"))
return boundingRect
except Exception as e:
print(97,e)
它们都与resizeInlineObject的& drawInlineObject的循环。
结果,我发现了......
height = 0
leading = 16
boundingRect.setRect(0,0,self.document().pageSize().width(),18)
layout = QtGui.QTextLayout(block)
layout.beginLayout()
while True:
line = layout.createLine()
if not line.isValid():
break
height += leading
line.setPosition(QtCore.QPointF(0,height))
line.setLineWidth(797)
height += line.height()
layout.endLayout()
上面的代码会发出resizeInlineObject()
的循环。
和
layout.draw(painter, QtCore.QPointF(0, 0))
上面的代码会发出drawInlineObject()
的循环
对不起,我定义的valiables并不复杂。
问题是我的代码无法显示光标。
为此,我在上面的代码中添加了这段代码。
layout.drawCursor(painter,QtCore.QPointF(0,0),1)
但光标不会出现。
为什么?
这是新代码。我认为这有所改进。
from PySide import QtCore
from PySide import QtGui
import sys
class TextEdit(QtGui.QTextEdit):
def __init__(self,parent=None):
super(TextEdit,self).__init__(parent=None)
self.customDocumentLayout = CustomDocumentLayout(self.document())
self.viewport().resize(797,1123)
self.customDocumentLayout.setPaintDevice(self.viewport())
self.document().setDocumentLayout(self.customDocumentLayout)
self.document().setPageSize(QtCore.QSizeF(797,1123))
self.tcf = TextCharFormatObjectInterface(self)
self.document().documentLayout().registerHandler(QtGui.QTextFormat.UserObject+1,self.tcf)
def keyPressEvent(self,event):
char = QtGui.QTextCharFormat()
char.setObjectType(QtGui.QTextFormat.UserObject+1)
char.setProperty(1,event.text())
tc = self.textCursor()
tc.insertText("\ufffc",char)
return QtGui.QTextEdit.keyPressEvent(self,event)
class TextCharFormatObjectInterface(QtGui.QPyTextObject):
def __init__(self,parent=None):
super(TextCharFormatObjectInterface,self).__init__(parent=None)
self.setParent(parent)
def intrinsicSize(self,doc,posInDocument,format):
print(29)
try:
char = format.toCharFormat()
f_m = QtGui.QFontMetrics(char.font())
rectF = f_m.boundingRect(char.property(1))
size = rectF.size()
return size
except Exception as e:
print(42,e)
def drawObject(self,painter,rect,doc,posInDocument,format):
try:
print(41,rect)
font = painter.font()
font.setPointSize(int(font.pointSize()))
painter.setFont(font)
painter.drawText(rect,str(format.property(1)))
except Exception as e:
print(24,e)
class TextInlineObject(QtGui.QTextInlineObject):
def __init__(self):
super(TextInlineObject,self).__init__()
print(52)
class CustomDocumentLayout(QtGui.QAbstractTextDocumentLayout):
def __init__(self,doc):
super(CustomDocumentLayout,self).__init__(doc)
def resizeInlineObject(self,item,posInDocument,format):
try:
char = format.toCharFormat()
if not char.isValid():
return
handler = self.handlerForObject(char.objectType())
size = handler.intrinsicSize(self.document(),posInDocument,format)
return size
except Exception as e:
print(62,e)
try:
pass
# print("item in resizeInlineObject",item)
# print("ascent in resizeInlineObject",item.ascent())
# print("descent in resizeInlineObject",item.descent())
# print("formatIndex in resizeInlineObject",item.formatIndex())
# print("height in resizeInlineObject",item.height())
# print("isValid in resizeInlineObject",item.isValid())
# print("rect in resizeInlineObject",item.rect())
# print("textDirection in resizeInlineObject",item.textDirection())
# print("textPosition in resizeInlineObject",item.textPosition())
# print("width in resizeInlineObject",item.width())
except Exception as e:
print(65,e)
def positionInlineObject(self,item, posInDocument, format):
try:
pass
# print("item in positionInlineObject",item)
# print("ascent in positionInlineObject",item.ascent())
# print("descent in positionInlineObject",item.descent())
# print("formatIndex in positionInlineObject",item.formatIndex())
# print("height in positionInlineObject",item.height())
# print("isValid in positionInlineObject",item.isValid())
# print("rect in positionInlineObject",item.rect())
# print("textDirection in positionInlineObject",item.textDirection())
# print("textPosition in positionInlineObject",item.textPosition())
# print("width in positionInlineObject",item.width())
except Exception as e:
print(65,e)
def drawInlineObject(self,painter,rect,object,posInDocument,format):
try:
char = format.toCharFormat()
if not char.isValid():
return
handler = self.handlerForObject(char.objectType())
handler.drawObject(painter,rect,self.document(),posInDocument,format)
except Exception as e:
print(76,e)
# self.emit(QtCore.SIGNAL("update(QRectF(float,float,float,float))"))
# handler = self.handlerForObject(format.objectType())
# handler.drawObject(painter,rect,self.document(),posInDocument,format)
# try:
# print("item in positionInlineObject",object)
# print("ascent in positionInlineObject",object.ascent())
# print("descent in positionInlineObject",object.descent())
# print("formatIndex in positionInlineObject",object.formatIndex())
# print("height in positionInlineObject",object.height())
# print("isValid in positionInlineObject",object.isValid())
# print("rect in positionInlineObject",object.rect())
# print("textDirection in positionInlineObject",object.textDirection())
# print("textPosition in positionInlineObject",object.textPosition())
# print("width in positionInlineObject",object.width())
# except Exception as e:
# print(65,e)
def hitTest(self,point,accuracy):
return accuracy
def documentChanged(self,fr, charsRemoved, charsAdded):
"""from fr to charsRemoved and charsAdded"""
# print(97,"fr",fr,"charsRemoved",charsRemoved,"charsAdded",charsAdded)
pass
def documentSize(self):
self.document().setPageSize(QtCore.QSizeF(797,1123))
self.emit(QtCore.SIGNAL("documentSizeChanged(QSizeF(float,float))"))
# print("current document pageSize",self.document().pageSize())
return self.document().pageSize()
def blockBoundingRect(self,block):
try:
boundingRect = block.layout().boundingRect()
# print(108,boundingRect)
height = 0
leading = 16
boundingRect.setRect(0,0,self.document().pageSize().width(),18)
layout = QtGui.QTextLayout(block)
layout.beginLayout()
while True:
line = layout.createLine()
if not line.isValid():
break
height += leading
line.setPosition(QtCore.QPointF(0,height))
line.setLineWidth(797)
height += line.height()
layout.endLayout()
painter = QtGui.QPainter(self.paintDevice())
pen = painter.pen()
pen.setWidth(1)
pen.setColor(QtCore.Qt.black)
painter.setPen(pen)
brush = painter.brush()
brush.setColor(QtCore.Qt.black)
brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern)
painter.setBrush(brush)
layout.draw(painter, QtCore.QPointF(0, 0))
layout.drawCursor(painter,QtCore.QPointF(0,0),1)
self.emit(QtCore.SIGNAL("updateBlock(block)"))
return boundingRect
except Exception as e:
print(97,e)
# print(117,"layout-position",layout.position())
# print(118,"layout-preeditareaposition",layout.preeditAreaPosition())
# print(119,"layout-preeditereatext",layout.preeditAreaText())
# print(120,"layout-linecount",layout.lineCount())
# print(121,"layout-font",layout.font())
# print(122,"layout-additionalFormats",layout.additionalFormats())
# print(123,"layout-text",layout.text())
# print(111,boundingRect)
def draw(self,painter,context):
try:
pass
# print(painter,painter.font(),painter.brush(),painter.pen(),painter.viewport())
except Exception as e:
print(47,e)
def main():
try:
QtGui.QApplication([])
except Exception as e:
print(18,e)
textedit = TextEdit()
textedit.show()
sys.exit(QtGui.QApplication.exec_())
if __name__ == "__main__":
main()