PyQt: как обрабатывать автоматическое изменение размеров виджетов при изменении их содержимого - PullRequest
11 голосов
/ 20 июля 2009

У меня возникают некоторые проблемы с размером виджетов qt4 при изменении их содержимого.

Я проиллюстрирую свои проблемы двумя простыми сценариями:

Сценарий 1:

У меня есть виджет QLineEdit. Иногда, когда я изменяю его содержимое с помощью QLineEdit.setText (), однострочная строка больше не помещается в виджет с его текущим размером. Я должен выбрать виджет и использовать клавиши со стрелками для прокрутки строки в обоих направлениях, чтобы увидеть все это.

Сценарий 2:

У меня есть виджет QTextEdit. Иногда, когда я изменяю его содержимое с помощью QTextEdit.setHtml (), отображаемый HTML-контент больше не помещается в виджет с его текущим размером. Виджет начинает отображать горизонтальные и / или вертикальные полосы прокрутки, и я могу использовать их для прокрутки содержимого HTML.

В таких сценариях я бы хотел иметь некоторую логику, которая решает, будет ли после изменения содержимого новое содержимое больше не помещаться в виджет, и автоматически увеличивает размер виджета, чтобы все соответствовало.

Как обрабатываются эти сценарии? Я использую PyQt4.

Редактировать: после прочтения как комментария, так и первого ответа (в котором упоминается ввод содержимого в виджет), я еще раз рассмотрел вопрос. Я был неприятно удивлен, обнаружив ужасную опечатку. Я имел в виду QTextBrowser, когда писал QTextEdit, извиняюсь за то, что ввел вас в заблуждение. То есть: у меня есть виджет, который отображает HTML-код, который я изменяю, и я бы хотел, чтобы этот виджет рос настолько, чтобы отображать все без полос прокрутки.

Что касается QLineEdit вместо QLabel - я выбрал QLineEdit, поскольку заметил, что не могу выделить текст из QLabel с помощью мыши для его копирования. С QLineEdit это возможно.

Ответы [ 5 ]

8 голосов
/ 22 июля 2009

Я отвечаю на C ++ здесь, так как это то, с чем я больше всего знаком, и ваша проблема не относится к PyQt.

Обычно вам просто нужно позвонить QWidget::updateGeometry(), когда sizeHint() мог измениться, точно так же, как вам нужно позвонить QWidget::update(), когда содержимое могло измениться.

Однако ваша проблема в том, что sizeHint() не изменяется при добавлении текста в QLineEdit и QTextEdit. По причине: люди не ожидают, что их диалоги будут расти по типу:)

Тем не менее, если вам действительно нужно поведение типа «расти как вы» в этих виджетах, вам нужно наследовать их и переопределять sizeHint() и minimumSizeHint(), чтобы вернуть больший размер, и, возможно, setText(), append() и т. д. для вызова updateGeometry(), чтобы заметить изменение размера подсказки

Расчет sizehint не будет полностью тривиальным, и для QLineEdit будет гораздо проще, чем для QTextEdit (что тайно QAbstractScrollArea), но вы можете взглянуть на sizeHint() и minimumSizeHint() реализации для вдохновения (также для QComboBox, в котором есть режим, чтобы делать именно то, что вы хотите: QComboBox::AdjustToContents.

РЕДАКТИРОВАТЬ: ваши два варианта использования (QTextBrowser без полос прокрутки и QLineEdit вместо QLabel только для выделения текста там) могут быть решены с помощью QLabel и достаточно недавнего Qt. QLabel получил как уведомление о щелчке по ссылке, так и так называемые «текстовые флаги взаимодействия» (одним из которых является TextSelectableByMouse) в Qt 4.2. Единственное отличие, которое мне удалось разглядеть, заключается в том, что загрузка нового контента не происходит автоматически, в нем нет истории, и в QLabel нет подсказок по микрофокусам (т. Е. Переход от ссылки к ссылке).

2 голосов
/ 15 декабря 2010

Возможно взгляните на Python QT Automatic Widget Resizer . Он написан на Python, но может дать вам некоторые идеи о том, как делать то, что вам нужно.

2 голосов
/ 27 июля 2009

В случае QTextBrowser вы можете получить размер документа, используя

QTextBrowser::document()->size();

после установки html, а затем изменения его размера в QTextBrowser.

1 голос
/ 30 ноября 2009

я добился аналогичного эффекта, используя следующий класс C ++:

textedit.h

#ifndef TEXTEDIT_H
#define TEXTEDIT_H

#include <QTextEdit>

class TextEdit : public QTextEdit
{
  Q_DISABLE_COPY( TextEdit )

public:
  TextEdit( QWidget* parent = NULL );
  TextEdit( const QString& text, QWidget* parent = NULL );
  virtual ~TextEdit();

  void fitToDocument( Qt::Orientations orientations );
  virtual QSize sizeHint() const;

private:
  int fittedHeight_;
  Qt::Orientations fittedOrientations_;
  int fittedWidth_;
};

#include "textedit-inl.h"

#endif // TEXTEDIT_H

TextEdit-inl.h

#ifndef TEXTEDITINL_H
#define TEXTEDITINL_H

#include "textedit.h"

inline TextEdit::TextEdit( QWidget* parent ) :
    QTextEdit( parent ), fittedOrientations_( 0 )
{ }

inline TextEdit::TextEdit( const QString& text, QWidget* parent ) :
    QTextEdit( text, parent ), fittedOrientations_( 0 )
{ }

inline TextEdit::~TextEdit()
{ }

inline QSize TextEdit::sizeHint() const
{
  QSize sizeHint = QTextEdit::sizeHint();
  if( fittedOrientations_ & Qt::Horizontal )
    sizeHint.setWidth( fittedWidth_ );
  if( fittedOrientations_ & Qt::Vertical )
    sizeHint.setHeight( fittedHeight_ );
  return sizeHint;
}

#endif // TEXTEDITINL_H

textedit.cpp

#include "textedit.h"

void TextEdit::fitToDocument( Qt::Orientations orientations )
{
  QSize documentSize( document()->size().toSize() );
  QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
  if( orientations & Qt::Horizontal ) {
    fittedWidth_ = documentSize.width() + (width() - viewport()->width());
    sizePolicy.setHorizontalPolicy( QSizePolicy::Fixed );
  }
  if( orientations & Qt::Vertical ) {
    fittedHeight_ = documentSize.height() + (width() - viewport()->width());
    sizePolicy.setVerticalPolicy( QSizePolicy::Fixed );
  }
  fittedOrientations_ = orientations;
  setSizePolicy( sizePolicy );
  updateGeometry();
}

например, вызов TextEdit::fitToDocument( Qt::Horizontal ) установит ширину виджета на фиксированную ширину, достаточно большую, чтобы соответствовать документу и его окружению (например, вертикальная полоса прокрутки, если она есть). если ваша цель состоит в том, чтобы это происходило при каждом изменении содержимого, подключите сигнал QTextEdit::textChanged() к слоту, который вызывает TextEdit::fitToDocument().

Что касается вашей проблемы с QLabel, решение простое: позвоните QLabel::setTextInteractionFlags( Qt::LinksAccessibleByMouse | Qt::TextSelectableByMouse ).

0 голосов
/ 28 ноября 2009

Ok реализовать метод sizeHint(). И каждый раз, когда ваш контент меняет размер, звоните updateGeometry() При изменении содержимого без изменения размера используйте update(). (updateGeometry() автоматический вызов update()).

...