如何在QTextEdit实例(PySide/PyQt)中垂直居中放置单行?

问题描述:

我有一个从QTextEdit继承的行编辑器,我正在使用它来编辑显示富文本的视图项目。对于QTextEdit.setAlignment第二个参数是`QtAligntment”和the docs说:如何在QTextEdit实例(PySide/PyQt)中垂直居中放置单行?

有效比对是Qt.AlignLeft,Qt.AlignRight,Qt.AlignJustify和 Qt.AlignCenter(其水平中心)。

也就是说,对于垂直对齐没有原生支持。是否有一种间接方式将文字垂直居中放置在QTextEdit

相关链接

Center the Text of QTextEdit horizontally and vertically:不幸的是,公认的答案使用QLineEdit这不会为我工作。

线索?

在下面的我发现了一个关于如何做到这一点在C++/Qt的线索。我几乎能够遵循它,但并不完全,因为它是C++:

http://www.qtcentre.org/threads/26003-Vertical-centering-of-a-QTextEdit

我将它砍我自己的几天,并尝试回答这个问题我自己,而是想现在发布,以防某人已经破解了它,或者以不同的/更好的方式完成了破解。

对于垂直居中的单行编辑,您只需计算正确的固定高度。

使用example delegate from your previous question,可以实现这样的:

class RichTextLineEdit(QtGui.QTextEdit): 
    def __init__(self, parent=None): 
     ...  
     margin = 1 
     self.document().setDocumentMargin(margin) 
     fontMetrics = QtGui.QFontMetrics(self.font()) 
     height = fontMetrics.height() + (margin + self.frameWidth()) * 2 
     self.setFixedHeight(height) 

(NB:重新实现的sizeHintminimumSizeHint方法可能是冗余的原始示例)。

+0

这很好,比我试图从线索中推测的方法简单得多。 – neuronet

+0

因此,当我改变字体大小时,这开始表现得非常奇怪(文本在两个垂直位置之间切换,每次击键都来回切换)。当我足够增加边距时,这种情况会停止,但需要停止的边距取决于字体大小!我现在正在研究这个问题,构建一个SSCCE,并且在我发现这个谜团时会在这里或另一个问题上发布。 – neuronet

+0

我把它作为一个单独的答案:如果你想要任意字体大小,上述方法变得复杂.... – neuronet

虽然接受的答案适用于默认字体大小,当我改变字体大小或垂直边距(见注释)打破。下面的文本行编辑类将文本垂直居中,对于我测试过的所有字体大小和垂直边距。

它使用QTextDocument设置编辑器,然后将其分配给QTextEdit实例。 QTextDocument无论如何都为QTextEdit提供了后端容器,并且内置了用于处理字体大小和边距的功能,并为编辑器提供了额外的控制层。

实际上,我发现使用QTextDocument让我以更直观的方式解决问题,而无需深入研究帧宽度,字体度量等所有那些基本的机制,而我们在单纯使用本地QTextEdit方法时做过。

请注意,它使用setViewportMargins()而不是setContentMargins()(这是您可能期望它使用的),因为后者用于设置插入布局的内容的边距。下面的编辑器是一个独立的小部件,没有放入任何布局,所以setContentMargins()不会做任何事情。

import sys 
from PySide import QtGui, QtCore 

class TextLineEdit(QtGui.QTextEdit): 
    topMarginCorrection = -4 #not sure why needed  
    returnPressed = QtCore.Signal() 
    def __init__(self, fontSize = 10, verticalMargin = 2, parent = None): 
     QtGui.QTextEdit.__init__(self, parent) 
     self.setAttribute(QtCore.Qt.WA_DeleteOnClose) 
     self.setLineWrapMode(QtGui.QTextEdit.NoWrap) 
     self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 
     self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 
     self.setFontPointSize(fontSize) 
     self.setViewportMargins(-verticalMargin, self.topMarginCorrection , 0, 0) #left, top, right, bottom 
     #Set up document with appropriate margins and font 
     document = QtGui.QTextDocument() 
     currentFont = self.currentFont() 
     currentFont.setPointSize(fontSize) 
     document.setDefaultFont(currentFont) 
     document.setDocumentMargin(verticalMargin) 
     self.setFixedHeight(document.size().height()) 
     self.setDocument(document) 

    def keyPressEvent(self, event): 
     '''stops retun from returning newline''' 
     if event.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return): 
      self.returnPressed.emit() 
      event.accept() 
     else: 
      QtGui.QTextEdit.keyPressEvent(self, event) 


def main(): 
    app = QtGui.QApplication(sys.argv) 
    myLine = TextLineEdit(fontSize = 15, verticalMargin = 8) 
    myLine.show()  
    sys.exit(app.exec_()) 


if __name__ == "__main__": 
    main()