Изменение размера QTextEdit QT в соответствии с высотой текста: MaximumViewportSize()
Я пытаюсь использовать виджет QTextEdit внутри формы, содержащей несколько виджетов QT. Сама форма находится внутри QScrollArea, который является центральным виджетом для окна. Мое намерение состоит в том, что любая необходимая прокрутка будет происходить в главной QScrollArea (а не внутри каких-либо виджетов), и любые виджеты внутри автоматически изменят свою высоту, чтобы сохранить их содержимое.
Я попытался реализовать автоматическое изменение высоты с помощью QTextEdit, но столкнулся с нечетной проблемой. Я создал подкласс QTextEdit и переопределил sizeHint() следующим образом:
QSize OperationEditor::sizeHint() const {
QSize sizehint = QTextBrowser::sizeHint();
sizehint.setHeight(this->fitted_height);
return sizehint;
}
this-> fit_height поддерживается в актуальном состоянии через этот слот, который подключен к сигналу QTextEdit "contentsChanged()":
void OperationEditor::fitHeightToDocument() {
this->document()->setTextWidth(this->viewport()->width());
QSize document_size(this->document()->size().toSize());
this->fitted_height = document_size.height();
this->updateGeometry();
}
Политика размера подкласса QTextEdit:
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
Я принял этот подход после прочтения этого поста.
Вот моя проблема:
Когда QTextEdit постепенно изменяет размеры, заполняя окно, оно перестает увеличиваться и начинает прокручиваться в QTextEdit, независимо от того, какая высота возвращается из sizeHint(). Если у меня изначально sizeHint() возвращает какое-то большое постоянное число, то QTextEdit очень большой и хорошо содержится во внешней QScrollArea, как и следовало ожидать. Однако, если sizeHint постепенно настраивает размер QTextEdit, а не просто делает его действительно большим для запуска, тогда он завершается, когда заполняет текущее окно и начинает прокручивать вместо увеличения.
Я проследил, что эта проблема заключается в том, что независимо от того, что возвращает мой sizeHint(), он никогда не изменит размер QTextEdit больше, чем значение, возвращаемое из MaximumViewportSize(), которое наследуется от QAbstractScrollArea. Обратите внимание, что это не тот же номер, что и viewport()-> MaximumSize(). Я не могу понять, как установить это значение.
Глядя на исходный код QT, MaximumViewportSize() возвращает "размер области просмотра, как если бы полосы прокрутки не имели допустимого диапазона прокрутки". Это значение в основном вычисляется как текущий размер виджета минус (2 * frameWidth + margins) плюс любая ширина / высота полосы прокрутки. Это не имеет большого смысла для меня, и мне неясно, почему это число будет использоваться где-либо таким образом, который заменяет реализацию sizeHint() подкласса. Кроме того, кажется странным, что одно целое число "frameWidth" используется для вычисления как ширины, так и высоты.
Кто-нибудь может пролить свет на это? Я подозреваю, что мое плохое понимание механизма компоновки QT виновато здесь.
Изменить: после первоначальной публикации, у меня была идея переопределить MaximumViewportSize(), чтобы вернуть то же самое, что sizeHint(). К сожалению, это не сработало, так как у меня все та же проблема.
2 ответа
Я решил эту проблему. Мне нужно было сделать 2 вещи, чтобы заставить его работать:
Пройдите по иерархии виджетов и убедитесь, что все политики размеров имеют смысл, чтобы любой дочерний виджет хотел быть большим / маленьким, тогда родительский виджет хотел бы быть тем же самым.
Это основной источник исправления. Оказывается, поскольку QTextEdit находится внутри QFrame, который является основным виджетом в QScrollArea, у QScrollArea есть ограничение, заключающееся в том, что он не будет изменять размер внутреннего виджета, если свойство "widgetResizable" не имеет значение true. Документация для этого находится здесь: http://doc.qt.io/qt-4.8/qscrollarea.html. Документация мне не была понятна, пока я не поиграл с этим параметром и не заставил его работать. Из документов видно, что это свойство имеет дело только со временем, когда основная область прокрутки хочет изменить размер виджета (то есть от родителя к потомку). На самом деле это означает, что если основной виджет в области прокрутки хочет когда-либо изменить размер (то есть дочерний к родительскому), то этот параметр должен быть установлен в true.
Итак, мораль этой истории в том, что код QTextEdit был корректным в переопределении sizeHint, но QScrollArea игнорировал значение, возвращаемое из sizeHint основного фрейма.
Ура! Оно работает!
Вы можете попробовать установить minimumSize
собственность QTextEdit
чтобы увидеть, если это заставит макет расти.
Я не понимаю большую часть схемы компоновки Qt, но установка минимального и максимального размера в значительной степени делает то, что я хочу. Ну, в большинстве случаев в любом случае.