如何对QAbstractTextDocumentLayout进行子类化,如何显示游标

时间:2018-02-07 03:11:14

标签: python qt pyside

我想制作像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角色(我还没有安装它,但我想我能做到。)

Kumimoji Wiki in Japanese

3.Tatenakayoko(与Kumimoji有一点差别)

Tatenakayoko Wiki in Japanese

4.Bunchu(Kacchu)(与Kumimoji有一点差别)

Bunchu Wiki in Japanese

5.表达像Tex / LaTex这样的数学公式。

Tex Wiki in English

Tex / LaTex非常漂亮。我希望我能做到这一点。

总之,我想表达排版。

Typesetting Wiki in English

其他

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()

0 个答案:

没有答案