8

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?

madasionka
  • 812
  • 2
  • 10
  • 29
  • You cannot access QTextEdit's QScrollArea because it is not a QScrollArea, it inherits from QAbstractScrollArea, which doesn't have a setWidgetResizable flag – Llopeth Apr 23 '19 at 08:46

5 Answers5

4

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 );
}
Tom Hickson
  • 57
  • 1
  • 1
  • This didn't work for me - when the content of the box was refreshed, the size oscillated between two heights, even though the text was unchanged. – Richard Whitehead Mar 26 '21 at 08:35
  • not working, height is always zero – IceFire Dec 30 '21 at 17:17
  • This works for me, if it does not work for anyone, make sure the QTextEdit widget is visible and shown on the screen before adjusting its size. It the editor is not shown on the screen and you try to use this, it will not work (it didn't for me) but if your run the code after you show() the QTextEdit, it does work. – marko May 14 '22 at 04:55
  • 1
    Size seems to be the number of rows for me, so it should be multiplied by line height? (Using QPlainTextEdit) – thomasa88 Nov 26 '22 at 07:05
3

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());
  • 1
    In Python, Pyside 2, Qt 5.6.1 idealWidth() returns -1 in my case. This may be related to using the no wrap flag but I didn't check. The docs just say textWidth defaults to -1 and I am assuming this is related. Perhaps when -1 use something else. – Rafe Nov 26 '19 at 18:03
2

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.

G.M.
  • 12,232
  • 2
  • 15
  • 18
0

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...

  • Thanks for answering, the problem is that first off all I don't have "\n" new line characters - The text is word wrapped. Secondly the problem is that even if I know the correct size, there is a point at which QTextEdit just provides a scrollbar instead of getting bigger - and that's my issue. – madasionka Dec 08 '17 at 09:23
  • @madasionka can you `disable` scroll-bar peroperty in any way? – BattleTested_закалённый в бою Dec 08 '17 at 09:28
  • Yes, by setting : `textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff)`, but this doesn't change the fact that some of the text is cut off. – madasionka Dec 08 '17 at 09:30
0

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".

NING Li
  • 571
  • 1
  • 4
  • 2