Results 1 to 5 of 5

Thread: Vertical centering of a QTextEdit

  1. #1
    Join Date
    Jul 2009
    Location
    Italy, Pieve Ligure (GE)
    Posts
    55
    Thanks
    7
    Thanked 6 Times in 6 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Lightbulb Vertical centering of a QTextEdit

    This post is actually a sequel to this thread. I created a new thread to give some visibility to a solution which might have some interest; please advise if this breaks some forum policy.

    THE PROBLEM

    Vertically centering a text in a QWebView widget is not very complex; with some experiments, I found that the following HTML text is enough:
    Qt Code:
    1. <html><body><table height='100%' width='100%'><tr><td valign='middle' style='text-align: center;'>%1</td></tr></table></body></html>
    To copy to clipboard, switch view to plain text mode 
    where %1 is supposed to be .arg'ed with the text to display.

    If a (read-only) QTextEdit is used instead of a QWebView, neither the above HTML not any other combination of HTML tags I could think of achieves the intended result: the text always remains at the top of the widget. The point in using QTextEdit instead of QWebView is to avoid the overhead of a full-fledged web browser (also in terms of executable file size and, IIUC, in terms of licensing) when only a few words of styled text have to be shown in a small widget.

    I tried a number of other tricks and none worked: QTextEdit::setAlignment(Qt::AlignVCenter) does not work (and is in fact excluded from the relevant documentation). QTextFormatChar::setVerticalAlignment(QTextCharFor mat::AlignMiddle) applies to a different purpose. Attempting to set the page size of the QTextEdit document to the size of the widget (myTextEdit.document()->setPageSize( QSize(myTextEdit.width(), myTextEdit.height()) ) brought no result. In fact I made more attempts than I can remember...

    I picture the situation imagining that QTextEdit has no concept of itself as a physical frame; it is rather a viewport on a document which is only 'tall' as itself and then centering vertically makes no sense (in the middle of what? Of a document, which is only high as the text it contains?). Actual Qt code may be different, but this is the picture I made for myself.

    THE SOLUTION

    The basic idea is to simulate the vertical centering by playing with the top margin of the document root frame. This is the function I use:
    Qt Code:
    1. void ValignMiddle(QTextEdit * pTextEdit)
    2. {
    3. // retrieve total text document height and widget height
    4. int nDocHeight = (int)pTextEdit->document()->size().height();
    5. if(nDocHeight == 0) // if no document, do nothing
    6. return;
    7. int nCtrlHeight= pTextEdit->height(); // the TextEdit control height
    8.  
    9. // access the document top frame and its format
    10. QTextFrame * pFrame = pTextEdit->document()->rootFrame();
    11. QTextFrameFormat frameFmt = pFrame->frameFormat();
    12.  
    13. // get current top margin and compute the 'black' height of the document
    14. int nTopMargin = (int)frameFmt.topMargin(); // the frame top margin
    15. int nBBDocH = nDocHeight - nTopMargin; // the height of the document 'bounding box'
    16.  
    17. // compute and set appropriate frame top margin
    18. if(nCtrlHeight <= nBBDocH) // if the control is shorter than the document
    19. nTopMargin = 2; // set a nominal top margin
    20. else // if the control is taller than the document
    21. nTopMargin = (nCtrlHeight - nBBDocH)/2 - 2; // set half of the excess as top margin
    22. frameFmt.setTopMargin(nTopMargin);
    23.  
    24. // SET A BORDER!! (using the same colour as the background)
    25. frameFmt.setBorder(1);
    26. frameFmt.setBorderBrush(QColor(0xFFFFFF));
    27. pFrame->setFrameFormat(frameFmt); // apply the new format
    28. }
    To copy to clipboard, switch view to plain text mode 
    (nBBDocH should probably also discount the root frame bottom margin; for my application, it made no real difference. The "-2" in line 21 is a rough visual correction as a bottom margin slightly larger than the top margin 'looks better').

    The real TRICK are lines 25 and 26 (it took me two days of trials and errors to discover it). The frame top margin is only obeyed if the frame has some border (if I do not wnat it to show, I use the same colour as the background); if no border is defined, the top margin is ignored and the text appears at the top of the widget.

    The above code can of course be improved, but works; I use it in several contexts. However, it needs two additions:
    • the top margin needs to be re-computed when the widget is resized.
    • the actual document height is not computed until after the widget is initially shown (this only applies if the QTextEdit widget is filled with static text when the dialogue it belongs to is initially constructed).

    So two event handlers have to be added:
    Qt Code:
    1. void MyDialogueClass::resizeEvent(QResizeEvent * event)
    2. {
    3. // when the dialogue box is resized, the widget is probably resized too.
    4. // Re-display the QTextEdit contents from scratch, as the document / margins dimensions are obsolete
    5. DisplayTextEditText(/* needed params */);
    6. ValignMiddle(ui->myTextEdit);
    7. }
    8.  
    9. void MyDialogueClass::showEvent(QShowEvent * event)
    10. {
    11. // once the widget is shown, recompute the top margin from the now-actual doc sizes
    12. ValignMiddle(ui->myTextEdit);
    13. }
    To copy to clipboard, switch view to plain text mode 
    With these three methods, the text ends up properly centered in the middle of the QTextEdit widget.

    In most situations, it probably makes sense to subclass QTextEdit and include these 3 methods in the subclassed widget itself (I didn't show it, for the sake of simplicity).

    A little question to end: vertical centering of a text in a widget is a rather common need; is all the above really needed?

    Cheers,

    M.
    Last edited by miwarre; 25th November 2009 at 10:10. Reason: spelling error

  2. #2

    Default Re: Vertical centering of a QTextEdit

    A little question to end: vertical centering of a text in a widget is a rather common need; is all the above really needed?
    If what you want to do is show HTML text, then it is not. A much easier way to center the text is to use a QLabel.

    This program that takes two arguments, a style sheet and som HTML text, and displays it centered in a QLabel:

    Qt Code:
    1. # include <QLabel>
    2. # include <QApplication>
    3.  
    4. int main(int argc, char *argv[])
    5. {
    6. QApplication app(argc, argv);
    7. QLabel *window = new QLabel;
    8.  
    9. window->resize (320,240);
    10. window->setStyleSheet(argv[1]);
    11. window->setText (argv[2]);
    12.  
    13. window->show();
    14. return app.exec();
    15. }
    To copy to clipboard, switch view to plain text mode 

    BTW, by putting a QLabel inside a QPushButton, it is possible to create fancy, HTML-styled buttons.

  3. #3
    Join Date
    Apr 2008
    Posts
    45
    Thanks
    3
    Thanked 2 Times in 2 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Vertical centering of a QTextEdit

    That HTML should work ina text edit.

    Alterativea are to consult QFontMetrics and construct your document accordingly.
    Why you are wanting to vertically center text in a text edit is beyond me.

  4. #4
    Join Date
    Sep 2014
    Posts
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Vertical centering of a QTextEdit

    @miwarre, I know it's been almost 6 years, but I want to thank you for sharing this solution. It may be for a very specific use case, but it works well. And I didn't even need to set the border (Qt 5.5).

  5. #5
    Join Date
    Jun 2014
    Posts
    98
    Thanks
    43
    Thanked 4 Times in 4 Posts
    Platforms
    Windows

    Default Re: Vertical centering of a QTextEdit

    Quote Originally Posted by Scorp2us View Post
    That HTML should work ina text edit.

    Alterativea are to consult QFontMetrics and construct your document accordingly.
    Why you are wanting to vertically center text in a text edit is beyond me.
    Not sure about original author, but I need to because I have a line editor built out of text edit, can't use line edit b/c I have delegate user creates/edits html that then shows as rich text. See Summerfield PyQt book, chapter 13-14 he has a worked out example, but doesn't deal with vertical alignment.

Similar Threads

  1. How to draw vertical text via QTextEdit
    By nifei in forum Qt Programming
    Replies: 8
    Last Post: 1st October 2010, 17:10
  2. Replies: 1
    Last Post: 21st November 2009, 20:38
  3. Draw vertical Line in QTextEdit
    By ericV in forum Qt Programming
    Replies: 3
    Last Post: 22nd July 2009, 15:50
  4. Drawing on QTextEdit
    By jgrauman in forum Qt Programming
    Replies: 3
    Last Post: 7th February 2009, 09:40
  5. Text block centering in Qt4.4 QTextEdit
    By mla1290 in forum Qt Programming
    Replies: 3
    Last Post: 10th July 2008, 17:46

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.