madasionka
madasionka

Reputation: 922

How to adjust QTextEdit to fit it's contents

I'm developing a Qt Application and I'm trying to find a way to use QTextEdit as a label with long text without the scroll bar. In my ui I have a QScrollArea and inside of it I want to place a couple off QTextEdit widgets and I only want use scrolling inside QScrollArea. Problem is that no matter how I try to resize the QTextEdit it seems it has a maximum height and cuts of text, even if I set the size manually and QTextEdit::size returns the correct value.

I did the same thing with QLabel and it works fine, but in this case I need some methods that are only provided in QTextEdit.

I found this post: Resizing QT's QTextEdit to Match Text Height: maximumViewportSize()

And the answer given was the following:

I have solved this issue. There were 2 things that I had to do to get it to work:

  1. Walk up the widget hierarchy and make sure all the size policies made sense to ensure that if any child widget wanted to be big/small, then the parent widget would want to be the same thing.
  2. This is the main source of the fix. It turns out that since the QTextEdit is inside a QFrame that is the main widget in a QScrollArea, the QScrollArea has a constraint that it will not resize the internal widget unless the "widgetResizable" property is true. The documentation for that is here: http://doc.qt.io/qt-4.8/qscrollarea.html#widgetResizable-prop. The documentation was not clear to me until I played around with this setting and got it to work. From the docs, it seems that this property only deals with times where the main scroll area wants to resize a widget (i.e. from parent to child). It actually means that if the main widget in the scroll area wants to ever resize (i.e. child to parent), then this setting has to be set to true. So, the moral of the story is that the QTextEdit code was correct in overriding sizeHint, but the QScrollArea was ignoring the value returned from the main frame's sizeHint.

The problem is that I have no idea how to access the QTextEdit's QScrollArea to enable widgetResizable. Can anyone explain how I can achieve this or suggest a different way of resizing QTextEdit to perfectly fit it's content?

Upvotes: 9

Views: 21027

Answers (5)

NING Li
NING Li

Reputation: 621

I make it work in my case:

content_height = field.document().lineCount() * 30
field.setFixedHeight(content_height)
frame.setFixedHeight(content_height + 12)

where "field" is the QTextEdit added to the layout of the hosting QFrame "frame".

Upvotes: 0

Tom Hickson
Tom Hickson

Reputation: 47

This will allow the height of the text box to change as required. You can edit the code a little to handle the width as well.

connect( m_textField, SIGNAL( textChanged() ), this, SLOT( onTextChanged() ) );

void MyClass::onTextChanged()
{
  QSize size = m_textField->document()->size().toSize();

  m_textField->setFixedHeight( size.height() + 3 );
}

Upvotes: 3

G.M.
G.M.

Reputation: 12879

Without a concrete example it's difficult to judge, but... it sounds as if you simply want a QTextEdit whose sizeHint depends on the current document size.

class text_edit: public QTextEdit {
  using super = QTextEdit;
public:
  explicit text_edit (QWidget *parent = nullptr)
    : super(parent)
    {
      setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
      setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
      setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    }
  virtual QSize sizeHint () const override
    {
      QSize s(document()->size().toSize());

      /*
       * Make sure width and height have `usable' values.
       */
      s.rwidth() = std::max(100, s.width());
      s.rheight() = std::max(100, s.height());
      return(s);
    }
protected:
  virtual void resizeEvent (QResizeEvent *event) override
    {

      /*
       * If the widget has been resized then the size hint will
       * also have changed.  Call updateGeometry to make sure
       * any layouts are notified of the change.
       */
      updateGeometry();
      super::resizeEvent(event);
    }
};

Then use as...

QScrollArea sa;
sa.setWidgetResizable(true);
text_edit te;
te.setPlainText(...);
sa.setWidget(&te);
sa.show();

It appears to work as expected in the few tests I've done.

Upvotes: 1

Try this one :

QTextEdit textEdit;
textEdit.setHtml("<p>test test test test test test</p><p>|||||||||</p>");
textEdit.show();
textEdit.setFixedWidth(textEdit.document()->idealWidth() +
                       textEdit.contentsMargins().left() +
                       textEdit.contentsMargins().right());

Upvotes: 3

In ui i defined QTextEdit *textEdit object. I write it as height scalable-content :

int count = 0;
QString str = "";

// set textEdit text
ui->textEdit->setText("hfdsf\ncsad\nfsc\dajkjkjkjhhkdkca\n925");
str = ui->textEdit->toPlainText();

for(int i = 0;i < str.length();i++)
    if(str.at(i).cell() == '\n')
        count++;

// resize textEdit (width and height)
ui->textEdit->resize(ui->textEdit->fontMetrics().width("this is the max-length line in qlabel")
         , ui->textEdit->fontMetrics().height() * (count + 2));

Notice : this work if you change QTextEdit font face or size! just in height scalable (before every thing set your QTextEdit frameShape to BOX).

if you want do width scalable-content, you should do these steps :

  • read QTextEdit(textEdit object) text as line to line
  • calculate every line length
  • select maximum of line length
  • use of QTextEdit::fontMetrics().width(QString str) for investigate str size in width

I hope this can help you...

Upvotes: 0

Related Questions