QGraphicsTextItem 中的文字对齐

QGraphicsTextItem 类可以放到 QGraphicsScene 或者 QGraphicsItem 上,用来显示格式化的文本内容,如 HTML,当然纯文本也可以显示。如果只是显示纯文本,可以使用 QGraphicsSimpleTextItem 类。

下面的内容都以 QGraphicsTextItem 作为例子。

这段代码展示了如何使用 QGraphicsTextItem

# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui

app = QtGui.QApplication(sys.argv)

view = QtGui.QGraphicsView()
scene = QtGui.QGraphicsScene(0, 0, 350, 250, view)
view.setScene(scene)

item0 = QtGui.QGraphicsTextItem()
item0.setPlainText('this is plain text')
scene.addItem(item0)
item0.setPos(50, 50)

item1 = QtGui.QGraphicsTextItem()
item1.setHtml('this is bold text with html strong tag')
scene.addItem(item1)
item1.setPos(50, 100)

item2 = QtGui.QGraphicsTextItem()
item2.setPlainText('this is the first line\nthis is the second line\nthis is the third line')
scene.addItem(item2)
item2.setPos(50, 150)

view.show()

sys.exit(app.exec_())

效果如下图:

可以看到内容是默认左对齐的,那么如何居中对齐或右对齐呢?我们首先想到的是使用 HTML ,HTML 中居中对齐有两种方式,一种直接使用 align="center" ,另一种使用 css 设置 text-align: center;

写成HTML:

<div align="center">this is the first line<br>this is the second line<br>this is the third line</div>
<br><br><br>
<div style="text-align: center;">this is the first line<br>this is the second line<br>this is the third line</div>

用浏览器查看效果如下:

在 PyQt4 中:

setHtml('<div align="center">this is the first line<br>this is the second line<br>this is the third line</div>')
setHtml('<div style="text-align: center;">this is the first line<br>this is the second line<br>this is the third line</div>')

很不幸,没有起作用:

此路不通,但是即便可行,这种方式还有个问题,当我们使用编辑模式修改 QGraphicsTextItem 的内容时,样式会遭到破坏。

我们使用另外一种方式,QGraphicsTextItem 有个 document (self) 方法,返回一个 QTextDocument 对象,查看文档,可以发现 QTextDocument 可以通过 QTextOption 来设置文本属性。使用 option.setAlignment(QtCore.Qt.AlignCenter) 可以设置文本居中。

item = QtGui.QGraphicsTextItem()
document = item.document()
option = document.defaultTextOption()
option.setAlignment(QtCore.Qt.AlignCenter)
document.setDefaultTextOption(option)
item.setPlainText('this is the first line\nthis is the second line\nthis is the third line')

令人抓狂的是还是不管用。到底怎么回事?我们添加一行代码看看:

print document.textWidth()

打印结果是 -1.0 ,这说明什么?说明 document 是没有宽度的,就很好理解了,没有宽度,就没有右边界,居中当然没法算了,右对齐也没法算,所以默认还是左对齐。通过设置宽度就可以解决这个问题。

item.setTextWidth(200)

大功告成,文字居中对齐了。但是还有问题,这个宽度 200 是我随便设置的,万一设成 100 就发现文字折行了。我们需要更完美的解决,进一步查看 QTextDocument 文档可以发现其提供了一个 idealWidth (self) 的方法,该方法返回了 document 的理想宽度。完整代码如下:

# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui

app = QtGui.QApplication(sys.argv)

view = QtGui.QGraphicsView()
view.setWindowTitle('QGraphicsTextItem')
scene = QtGui.QGraphicsScene(0, 0, 350, 350, view)
view.setScene(scene)

y = 50

for align in (QtCore.Qt.AlignLeft, QtCore.Qt.AlignCenter, QtCore.Qt.AlignRight):
    item = QtGui.QGraphicsTextItem()
    document = item.document()
    option = document.defaultTextOption()
    option.setAlignment(align)
    document.setDefaultTextOption(option)
    item.setPlainText('this is the first line\nthis is the second line\nthis is the third line')
    item.setTextWidth(document.idealWidth())
    scene.addItem(item)
    item.setPos(50, y)

    y += 100

view.show()

sys.exit(app.exec_())

效果如下图: