get the exact height of QTextDocument in pixels

2019-04-16 01:36发布

问题:

I need to get the actual height of QTextDocument in order to be able to set the containing QPlainTextEdit to a minimum height (while keeping its width constant) so that it shows the whole content without the vertical scrollbar. I tried to follow this question (closed with with accepted answer) How do I determine the height of a QTextDocument? but it does not do what it promises.

A piece of code:

from PyQt5.QtWidgets import QApplication, QPlainTextEdit
app = QApplication([])
w = QPlainTextEdit()
w.setPlainText("Hello!")
print(w.document().size())
w.setPlainText("Hello!\nHello again!")
print(w.document().size())

prints out:

PyQt5.QtCore.QSizeF(35.0, 1.0)
PyQt5.QtCore.QSizeF(64.0, 2.0)

It seems that the width is measured correctly in pixels but the height just shows the number of lines instead of pixels. I think multiplying it with font pixel metric height does not help because there can be mixed formatting (in general it can be a rich text / HTML) and line spacing, document margins and maybe some other complicated stuff based on implementation details... etc.

So is there a way out?

回答1:

So I finally found a solution but it is really ugly. If anyone knows anything better, please publish it.

from PyQt5.QtWidgets import QApplication, QPlainTextEdit

app = QApplication([])
w = QPlainTextEdit()
# test various formatting
w.appendHtml("<h1>Hello!</h1>")
w.appendHtml("<b>Hello!</b>")
w.appendPlainText("Hello!")
doc = w.document()
layout = doc.documentLayout()
h = 0
b = doc.begin()
while b != doc.end():
    h += layout.blockBoundingRect(b).height()
    b = b.next()

# magic formula: I do not know why the document margin is already
# once included in the height of the last block, and I do not know
# why there must be the number 1 at the end... but it works
w.setFixedHeight(h + doc.documentMargin() + 2 * w.frameWidth() + 1)

w.show()
app.exec_()

So this should show the box without scroll bar. If you decrease the height by 1, the scroll bar appears. This should work with any number of lines, document margins, frame widths, formatting etc. Hopefully.



回答2:

Shot in the dark without testing

Have you looked @ pageSize?

From the docs:

This property holds the page size that should be used for laying out the document

The units are determined by the underlying paint device. The size is measured in logical pixels when painting to the screen, and in points (1/72 inch) when painting to a printer.

By default, for a newly-created, empty document, this property contains an undefined size.

If you set the pageSize, as directed by the other thread, I'd expect you'd get the value out in the pixels that QPlainTextEdit::setMinimumHeight needs.



标签: qt pyqt pyside