Results 1 to 7 of 7

Thread: How to write rich text at a specific position given a const QPainter object?

  1. #1
    Join Date
    May 2010
    Posts
    18
    Qt products
    Qt4
    Platforms
    Windows

    Default How to write rich text at a specific position given a const QPainter object?

    I want to create a class method for drawing rich text at a specific position with a specific QPainter object:

    Qt Code:
    1. void MyWidget::drawRichText(QString html, QPointF position, const QPainter* qp);
    To copy to clipboard, switch view to plain text mode 

    How do I implement this method? The solution I was able to come up with by searching on Google was the following:

    Qt Code:
    1. void MyWidget::drawRichText(QString html, QPointF position, QPainter* qp)
    2. {
    3. td.setHtml(html);
    4. qp->translate(position); // Move the painter to the desired location
    5. td.drawContents(qp);
    6. qp->translate(-position); // Move the painter back to where it was before
    7. }
    To copy to clipboard, switch view to plain text mode 

    which I already find quite distasteful as I make changes to a painter object which may be used after me (which is why I discretely move the painter back after I have used it, but I realize that the more changes I make to it that I don't want to be permanent, the greater the risk is that I will forget to change some of them back). I cannot make a personal copy of it either, since QPainter uses the Q_DISABLE_COPY macro.

    Actually, the proposed solution won't even work in my case since I need to pass qp as const, and the translate method cannot be called on const QPainter objects.

    (Besides, I realized that if someone has already moved the pointer before me, the pointer will move to the wrong location. But maybe that's a secondary issue. I don't know. Anyway...)

    So, how do I implement this function assuming that the QPainter object is declared const (and is located at (0, 0) when the method is called)?
    Last edited by TriKri; 7th October 2016 at 18:13.

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to write rich text at a specific position given a const QPainter object?

    Quote Originally Posted by TriKri View Post
    which I already find quite distasteful as I make changes to a painter object which may be used after me (which is why I discretely move the painter back after I have used it, but I realize that the more changes I make to it that I don't want to be permanent, the greater the risk is that I will forget to change some of them back).
    Moving a painter and then moving it back is a common construct, nothing distasteful about it.
    If a method changes more then it can save() and restore() the painter, but that is also more "expensive".

    Quote Originally Posted by TriKri View Post
    Actually, the proposed solution won't even work in my case since I need to pass qp as const, and the translate method cannot be called on const QPainter objects.
    A const painter wouldn't make sense, unless it is not needed for drawing and only as a reference for, e.g. what pen or font is being used in drawing operations elsewhere.

    Quote Originally Posted by TriKri View Post
    (Besides, I realized that if someone has already moved the pointer before me, the pointer will move to the wrong location. But maybe that's a secondary issue. I don't know. Anyway...)
    Then the other method hasn't cleaned up correctly or hasn't called the method correctly.

    Quote Originally Posted by TriKri View Post
    So, how do I implement this function assuming that the QPainter object is declared const (and is located at (0, 0) when the method is called)?
    That's what you have now, no?

    Cheers,
    _

  3. #3
    Join Date
    Sep 2016
    Posts
    5
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Symbian S60

    Default Re: How to write rich text at a specific position given a const QPainter object?

    Quote Originally Posted by anda_skoa View Post
    Moving a painter and then moving it back is a common construct, nothing distasteful about it.
    If a method changes more then it can save() and restore() the painter, but that is also more "expensive".



    A const painter wouldn't make sense, unless it is not needed for drawing and only as a reference for, e.g. what pen or font is being used in drawing operations elsewhere.


    Then the other method hasn't cleaned up correctly or hasn't called the method correctly.


    That's what you have now, no?

    Cheers,
    _
    nice.. it is,,, thanks for post

  4. #4
    Join Date
    May 2010
    Posts
    18
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to write rich text at a specific position given a const QPainter object?

    Quote Originally Posted by anda_skoa View Post
    Moving a painter and then moving it back is a common construct, nothing distasteful about it.
    That may be your opinion, but I don't agree. If you have to clean after yourself it becomes easy to make a mistake as you may forget to do so. If you have made many changes that you need to undo, the risk of making at least some mistake starts to become quite high. It should be easy to write bug-free code and hard to make a mistake. In a high-level language, as much cleaning as possible should be abstracted away. Why isn't there for example a method for drawing at a specific location that moves the painter back and forth for you so you don't have to do that yourself? Or why isn't it possible to make a copy of the painter? That would make a lot of cleaning unnecessary. What is the justification for making QPainter uncopiable?

    Quote Originally Posted by anda_skoa View Post
    If a method changes more then it can save() and restore() the painter, but that is also more "expensive".
    That may be a useful strategy. (Still feel a copy would have been better in this case, though.) Why aren't the methods called push and pop? That would make it more clear what they actually do. I at first thought that you could only have one state saved at a time and that you would write over the old saved state if you called save twice.

    Quote Originally Posted by anda_skoa View Post
    Then the other method hasn't cleaned up correctly or hasn't called the method correctly.
    See what I mean? :P I want to avoid the risk completely of getting in that situation.

    Quote Originally Posted by anda_skoa View Post
    A const painter wouldn't make sense, unless it is not needed for drawing and only as a reference for, e.g. what pen or font is being used in drawing operations elsewhere.
    I didn't think the painter got modified when I painted with it. Why does it do that? I guess I cannot declare it const then.

  5. #5
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to write rich text at a specific position given a const QPainter object?

    Quote Originally Posted by TriKri View Post
    That may be your opinion, but I don't agree. If you have to clean after yourself it becomes easy to make a mistake as you may forget to do so. If you have made many changes that you need to undo, the risk of making at least some mistake starts to become quite high. It should be easy to write bug-free code and hard to make a mistake. In a high-level language, as much cleaning as possible should be abstracted away. Why isn't there for example a method for drawing at a specific location that moves the painter back and forth for you so you don't have to do that yourself? Or why isn't it possible to make a copy of the painter? That would make a lot of cleaning unnecessary. What is the justification for making QPainter uncopiable?
    In C++ one of the core principles is to not prematurely pessimise, e.g. not cleary newly allocated memory by default, and it is always possible to add more convenience but almost never possible to remove default overhead.

    Automatically saving and restoring the state would incur the cost of doing that even when it is not necessary, e.g. when the code is aware of the state changes and changes state as required.
    A full save/restore is costly, so code that only changes, e.g. the pen, can simply keep the old pen and set that again instead of incuring a full save/restore overhead.

    If you want to have a fully scoped based save/restore, you could easily do that with a RAII class, e.g. like QMutexLocker does for QMutex lock/unlock or QScopedValueRollback does for single values.

    You could even consider contributing such a "QScopedPainterState" to Qt.

    All drawing methods, i.e. the QPainter API, actually draw at a specified location, because the location is either inherent in what is being drawn, e.g. coordinates of a rectangle, or passed as an argument, e.g. for text.

    I guess one could have added overloads to QTextDocument, but since there are many types of transformations one would either need a lot of overloads or one that takes a QTransform object.
    The assumption probably was that the code using the text document would know best where to draw.

    My guess on the painter not being copyable is to avoid developers assuming that these copies would be independent, while they would actually be more like shared pointers.
    I.e. these copies, if that were possible, would all work on the same paint device, and to work properly each copy would have to go through a full save and restore for each call.
    Not sure developers would understand that something as apparently simple as creating a copy would increase the overhead of each draw call or would require extra code to make a copy "current".

    Quote Originally Posted by TriKri View Post
    That may be a useful strategy. (Still feel a copy would have been better in this case, though.) Why aren't the methods called push and pop?
    Yes, I guess they could have been called pushState() and popState(), just push/pop would not have enough meaning in the context of drawing.

    Quote Originally Posted by TriKri View Post
    I at first thought that you could only have one state saved at a time and that you would write over the old saved state if you called save twice.
    Right, fortunately the behavior is documented.

    Quote Originally Posted by TriKri View Post
    See what I mean? :P I want to avoid the risk completely of getting in that situation.
    As pointed out above you can always do that and even specifically in a way that only saves/restores things you change, only incurring the necessary cost and not more.

    Quote Originally Posted by TriKri View Post
    I didn't think the painter got modified when I painted with it. Why does it do that? I guess I cannot declare it const then.
    As you said yourself, a const would indicate that nothing changes, while of course there is change, e.g. pixels in an image change for draw calls, state changes for setter or transformation calls.

    Would be highly confusing if you passed a const painter and suddenly end up with different content in the thing you are painting on, wouldn't it?

    Cheers,
    _

  6. #6
    Join Date
    May 2010
    Posts
    18
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to write rich text at a specific position given a const QPainter object?

    Quote Originally Posted by anda_skoa View Post
    In C++ one of the core principles is to not prematurely pessimise, e.g. not cleary newly allocated memory by default, and it is always possible to add more convenience but almost never possible to remove default overhead.
    Hm, that makes sense, better getting the constructs right the first time than getting them wrong and having to live with them forever.

    Quote Originally Posted by anda_skoa View Post
    Not sure developers would understand that something as apparently simple as creating a copy would increase the overhead of each draw call or would require extra code to make a copy "current".
    Of course, that's a good point.

    Quote Originally Posted by anda_skoa View Post
    You could even consider contributing such a "QScopedPainterState" to Qt.
    If I ever write such a wrapper, I will consider contributing with it.

    Quote Originally Posted by anda_skoa View Post
    Would be highly confusing if you passed a const painter and suddenly end up with different content in the thing you are painting on, wouldn't it?
    Not at all – what should get modified is the thing you paint on, and I don't see why the thing you paint with should be modified?

  7. #7
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to write rich text at a specific position given a const QPainter object?

    Quote Originally Posted by TriKri View Post
    Hm, that makes sense, better getting the constructs right the first time than getting them wrong and having to live with them forever.
    And no API is perfect, sometimes less then ideal API is kept as changing it would otherwise have massive impact on existing code.

    Your idea of using instance copying for keeping states is quite good IMHO from a readability point of view, though it might also require a different approach in savind/restoring state then


    Quote Originally Posted by TriKri View Post
    If I ever write such a wrapper, I will consider contributing with it.
    Excellent :-)
    I've never actually considered that until you brought it up.

    It is small improvements like this that allow a framework to evolve rather than to stagnate.

    Quote Originally Posted by TriKri View Post
    Not at all – what should get modified is the thing you paint on, and I don't see why the thing you paint with should be modified?
    Theoretically true, the paint device is held by pointer and the pointer value doesn't change so the QPainter method could call non-const paint device methods.

    Maybe there are even compilers which generated warnings for this or it was done for consistency (methods starting with an imperative verb usually do change the state of the object they are invoked on)

    Cheers,
    _

Similar Threads

  1. Replies: 3
    Last Post: 19th January 2016, 18:22
  2. Positioning Rich Text when using QPainter
    By millsks in forum Qt Programming
    Replies: 8
    Last Post: 23rd June 2009, 08:21
  3. Replies: 13
    Last Post: 29th April 2009, 16:51
  4. Drawing Rich Formatted Text with QPainter
    By millsks in forum Qt Programming
    Replies: 1
    Last Post: 5th March 2009, 20:59
  5. Rich text with QPainter?
    By sarefo in forum Qt Programming
    Replies: 3
    Last Post: 7th April 2008, 15:40

Tags for this Thread

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.