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

4
我有一个从 QTextEdit 继承的行编辑器,我正在使用它来编辑显示富文本的视图项目。 QTextEdit.setAlignment 的第二个参数是“QtAligntment'”,文档 表示:

有效的对齐方式是 Qt.AlignLeft、Qt.AlignRight、Qt.AlignJustify 和 Qt.AlignCenter(水平居中)。

也就是说,没有原生支持垂直对齐的功能。有没有一种间接的方法在 QTextEdit 中垂直居中文本? 相关链接

将QTextEdit的文本水平和垂直居中:不幸的是,被接受的答案使用了无法适用于我的 QLineEdit提示?

在以下内容中,我找到了有关如何在 C++/Qt 中执行此操作的线索。我几乎能够跟随它,但没有完全跟上,因为它是为 c++ 编写的:

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

我会自己试着解决这个问题,大概需要几天时间,但是想现在发布这个帖子,以防有人已经解决了它或者用不同/更好的方式解决了它。

2个回答

2

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

使用您先前问题中的示例委托,可以像这样实现:

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)

(注:在原始示例中,重新实现的sizeHintminimumSizeHint方法可能是多余的。)

这很好用,比我原本打算从线索中尝试实现的方法简单得多。 - eric
事实证明,当我改变字体大小时,它开始表现得非常奇怪(文本在两个垂直位置之间切换,每次按键都会来回切换)。当我增加足够的边距时,这种情况就不会发生,但需要停止它的边距取决于字体大小!我正在努力解决这个问题,构建一个SSCCE,并在我解决这个谜团后在这里或单独的问题中发布。 - eric
我将其作为单独的答案:如果您想要任意字体大小,则上述方法会变得复杂... - eric

1
尽管已接受的答案适用于默认字体大小,但当我更改字体大小或垂直边距时(请参见评论),它会出错。下面的文本行编辑类使文本在我测试的所有字体大小和垂直边距上垂直居中。
它使用 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()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接