Results 1 to 9 of 9

Thread: Editable text in QGraphicsView

  1. #1
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Editable text in QGraphicsView

    Hi people!

    I have two issues to discuss. They are related to QGraphicsView and displaying text.

    My problem is that I want to have an item composed of a shape item (let's say a rectangle) and an editable text inside it. The trivial implementation would be to have a QGraphicsRectItem with a QGraphicsTextItem child. The problem is, that when you click the text to edit it, the text item gets a rectangle border around it which I don't like.

    A solution would be to subclass and reimplement paint(), making sure the frame is not drawn. But here we encounter the problem - there is no method to render the text! That makes it impossible to modify the way QGraphicsTextItem works, you can only extend it.

    Extend:
    Qt Code:
    1. void MyItem::paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget){
    2. // do something here
    3. QGraphicsTextItem::paint(painter, option, widget);
    4. // or here to extend
    5. }
    To copy to clipboard, switch view to plain text mode 

    Original (simplified):
    Qt Code:
    1. void QGraphicsTextItem::paint(...)
    2. {
    3. if (dd->control) {
    4. //...
    5. dd->control->drawContents(painter, r); // draws text
    6. //...
    7. }
    8.  
    9. if (option->state & (QStyle::State_Selected | QStyle::State_HasFocus)) {
    10. painter->setPen(QPen(Qt::black, 1));
    11. painter->setBrush(Qt::NoBrush);
    12. painter->drawRect(dd->boundingRect); // draws the frame I don't want
    13. }
    14. }
    To copy to clipboard, switch view to plain text mode 

    As you see the text is rendered directly from within QTextControl, which is not part of the public API (and this is the second issue I wanted to discuss - why is it not part of the API?). The problem would be solved if we had a protected method available that calls the text control for us. Then I could do:

    Qt Code:
    1. void MyItem::paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget){
    2. // do something here
    3. renderText(painter); // this would render the text
    4. // or here to extend
    5. }
    To copy to clipboard, switch view to plain text mode 

    Unfortunately this is not possible right now (4.2.2). To be honest I don't need and I don't want the text item at all. I'd like to subclass the rect item and add text capabilities to it. It would be simple if we had access to QTextControl. Right now I can only try to emulate it using QTextLayout which seems very complicated to me (I want the cursor to be shown - that makes it complicated). Do you have a better idea how to do it or maybe you have a working snippet of code that uses QTextLayout to achieve what I want?

    I think the Trolls made a simmilar mistake here as they did with the proxy model and they corrected it in 4.1 by introducing QAbstractProxyModel. I think they should do the same for QGraphicsTextItem (introducing QAbstractTextItem). What do you think?

  2. #2
    Join Date
    Jan 2006
    Posts
    128
    Thanked 28 Times in 27 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Editable text in QGraphicsView

    Quote Originally Posted by wysota View Post
    Qt Code:
    1. if (option->state & (QStyle::State_Selected | QStyle::State_HasFocus))
    To copy to clipboard, switch view to plain text mode 
    Just a quick idea for the rect. What happens when you edit the state, to tell the style that it was not selected at all? (You probably could do that via extension?)

    Or would it then stop drawing the cursor too?

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Editable text in QGraphicsView

    Quote Originally Posted by camel View Post
    What happens when you edit the state, to tell the style that it was not selected at all? (You probably could do that via extension?)

    Or would it then stop drawing the cursor too?
    Yes, this seems to work:
    Qt Code:
    1. class MyGraphicsTextItem : public QGraphicsTextItem {
    2. public:
    3. MyGraphicsTextItem(QGraphicsItem *parent=0, QGraphicsScene *scene=0)
    4. : QGraphicsTextItem(parent, scene){}
    5. void paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0 ){
    6. QStyleOptionGraphicsItem option2 = *option;
    7. option2.state = 0;
    8. QGraphicsTextItem::paint(painter, &option2, widget);
    9. }
    10. };
    To copy to clipboard, switch view to plain text mode 

    Still, it's kind of a hack and I'd prefer to do it without the text item at all (otherwise I'd have to subclass the text item and reimplement the shape functionality, which of course is an option too but I'd like to avoid it).

    There is another terrible hack that just might work. I might cut out the QTextControl declaration and put it into my project. As the class is present in Qt, it'll work, at least under non-Windows systems (AFAIK Windows need the symbols to be exported and QTextControl is not).

  4. #4
    Join Date
    Jan 2006
    Location
    Norway
    Posts
    124
    Thanked 38 Times in 30 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Editable text in QGraphicsView

    The code where you copy the style option and remove the state will always work; it's not a hack. It's better if you only remove the state flags that affect focus rect drawing, though.

    Qt Code:
    1. option.state &= ~(QStyle::State_Selected | QStyle::State_HasFocus);
    To copy to clipboard, switch view to plain text mode 

    If you rip out QTextControl, you're on your own ;-). I don't know it's really worth it if all you want is to remove a rectangle.
    Bitto / Andreas Aardal Hanssen - andreas dot aardal dot hanssen at nokia
    Nokia Software Manager, Qt Development

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Editable text in QGraphicsView

    Quote Originally Posted by Bitto View Post
    The code where you copy the style option and remove the state will always work; it's not a hack.
    I meant that it's a hacky way to extend a class. There should be a way to obtain this without having to modify the state. This is one of few places in Qt where you can't modify the behaviour of the object just by directly calling some methods.

    To be honest I "love" situations when I want to do something what wasn't meant to do by the class designer and I find out that the respective method is part of the class pimpl

    It's better if you only remove the state flags that affect focus rect drawing, though.

    Qt Code:
    1. option.state &= ~(QStyle::State_Selected | QStyle::State_HasFocus);
    To copy to clipboard, switch view to plain text mode 
    True, but in this case it completely doesn't matter.

    If you rip out QTextControl, you're on your own ;-).
    Oh yes, I'm aware of that, but why didn't QTextControl make it into the public API? I'm sure people would like to put their hands on it.

    I don't know it's really worth it if all you want is to remove a rectangle.
    Maybe I wasn't clear. I'd like to have access to QTextControl regardless of the rectangle (and the graphicsview).

  6. #6
    Join Date
    Jan 2006
    Location
    Norway
    Posts
    124
    Thanked 38 Times in 30 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Editable text in QGraphicsView

    QProxyModel is dangerous, because it maps indices without mapping their positions. I can't see the parallell to QProxyModel from QGraphicsTextItem, could you explain?

    QGraphicsTextItem is just as powerful as QTextEdit, but it's a graphics item. You have complete QTextDocument access. I understand from your first post that you want a way to remove the focus rectangle, and you found a way. What other limitations have you run into? I understand that you want QTextControl to be public, but I don't understand why. ;-)
    Bitto / Andreas Aardal Hanssen - andreas dot aardal dot hanssen at nokia
    Nokia Software Manager, Qt Development

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Editable text in QGraphicsView

    Quote Originally Posted by Bitto View Post
    QProxyModel is dangerous, because it maps indices without mapping their positions. I can't see the parallell to QProxyModel from QGraphicsTextItem, could you explain?
    That you couldn't correct it without breaking binary compatibility and so another class had to be introduced. And that class is an abstract class, that is easy to extend. It's just a confusing way to say I'd like to see QGraphicsAbstractTextItem (or QAbstractGraphicsTextItem or whatever) that would have a protected method rendering the text on a specified rectangle of the item.

    The drawback I mentioned is not the only one I think the item has. For instance you can limit the width of the item, but you can't limit its height (of course you can clip the painter, but that's not the same). There is QGraphicsSimpleTextItem, but it only allows you to display plain text in a rectangle, so it's quite limited compared to QGraphicsTextItem.

    Let me make myself clear - I don't deny your (or whoever implemented the class) work on the item or the whole framework. It would just be nice to have that separate method to easily extend the item. It doesn't need to be virtual, so maybe it wouldn't break binary compatibility?


    QGraphicsTextItem is just as powerful as QTextEdit, but it's a graphics item.
    Yes, I don't deny that.
    You have complete QTextDocument access.
    True, but the document only holds the logical structure of its contents, not the way it is rendered. As you know the text will be laid out only when it needs to be rendered (though Q*TextLayout if I remember correctly). I know you can use the layout to get the same capabilities QTextControl has, but it is against the paradigm of reusing already written code.

    I understand from your first post that you want a way to remove the focus rectangle, and you found a way.
    I want to be able to have editable text without using a separate item. I iterate over item's children and each time I'd have to filter out the text item from the list of children. It's ok when you have to do it once, but such little quirks add to themselves and one ends up with quite a complex code. It has nothing to do with the graphics view of course, as it gives me a possibility to do what I want by adding that child item and connecting appropriate signals and slots.

    What other limitations have you run into?
    I'm just beginning to have fun with the framework

    I find it a bit annoying that the QStyle::State_MouseOver is set for an item if the mouse is over one of its children, regardless of the boundingRect() or shape() of the parent item. I can work it around by testing against the shape (if the parent and child shapes are distinct) or testing colliding items. Right now I'm reimplementing hover enter and hover leave events (as they don't "propagate" to parent items) and set my own "hover" flag there, but it won't work if the child's shape is part of its parent shape as the parent will also receive its hover enter event (provided that it accepts hover events). Of course I could implement a method that corrects the hover flag for the parent (and its parent, etc.) when you enter or leave the child item, but again it makes the code complex. How about having a flag that enables/disables propagation of child events? The behaviour is a bit different than with widgets, as widgets are always inside their parents, so such propagation makes more sense there.

    I understand that you want QTextControl to be public, but I don't understand why. ;-)
    Because I want to be able to render complex text without a QTextEdit or QGraphicsTextItem and without the need to construct everything from scratch using QTextLayout. The class is already present in the code, so why not make it public? It won't compromise the framework in any way, right?

    Thanks for your input, I appreciate that and hope for more. I know I can be very annoying sometimes

  8. #8
    Join Date
    Jan 2006
    Location
    Norway
    Posts
    124
    Thanked 38 Times in 30 Posts
    Qt products
    Qt3 Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Smile Re: Editable text in QGraphicsView

    What's wonderful about the Graphics View framework is that everyone wants to do everything with it. That's what I call a true success indicator. It's so easy to learn, and very inspiring to use, and Qt developers can only see more and more possibilities. That's when you know the API is a success. Now, that some parts of the API don't behave exactly like you would want, I can only see that as natural. Actually I see that as a good thing. It's a sign that you're working with the framework, instead of fighting it.

    Now, the trick is to find out how to extend the API, without bloating it. We knew in advance that the text item would be a target of endless customization requests, and we are just extending it as we go along. QTextControl might be made public at one point, but as it is today, it probably can't do half of what you'd expect it to do... But then again, we need to see exactly what it is you want to do (as you wrote just now). Hover event behavior: you will probably notice that parents and children propagate hover events, whereas siblings do not. That's by design, and works for most cases, but not all. Maybe we can do something to help you out, if this doesn't fit your application well.

    The best approach is to file a suggestion, or report an inconvenience in the API, by posting to http://www.trolltech.com/bugreport-form. With a proper line of argumentation, I'm sure you'll see that APIs will evolve in your direction.
    Bitto / Andreas Aardal Hanssen - andreas dot aardal dot hanssen at nokia
    Nokia Software Manager, Qt Development

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Editable text in QGraphicsView

    Quote Originally Posted by Bitto View Post
    QTextControl might be made public at one point, but as it is today, it probably can't do half of what you'd expect it to do... But then again, we need to see exactly what it is you want to do (as you wrote just now).
    True. Exposing the class would freeze its API seizing its evolution.

    Hover event behavior: you will probably notice that parents and children propagate hover events, whereas siblings do not. That's by design, and works for most cases, but not all. Maybe we can do something to help you out, if this doesn't fit your application well.
    Oh, I'm sure it's by design and in most cases it makes sense. Although it seems to be a faulty behaviour when a child is outside its parent's shape (or even bounding rect).

    The best approach is to file a suggestion, or report an inconvenience in the API, by posting to http://www.trolltech.com/bugreport-form. With a proper line of argumentation, I'm sure you'll see that APIs will evolve in your direction.
    Yes, I already filed some suggestions some time ago (regarding Interview), but they had to wait because implementing them directly would cause binary compatibility to be lost (virtual methods were needed). We'll see if they make it into 4.3 I'm just beginning with the graphics view framework so I want to find ways of doing things instead of blaiming Qt right away and sending bug reports or suggestions.

Similar Threads

  1. Unhandled exception in qatomic
    By NewGuy in forum Qt Programming
    Replies: 14
    Last Post: 23rd July 2013, 09:49
  2. Problem pasting text into a QTextEdit
    By Spockmeat in forum Qt Programming
    Replies: 8
    Last Post: 14th March 2009, 14:36
  3. visible text of textedit
    By regix in forum Qt Programming
    Replies: 3
    Last Post: 26th June 2006, 09:02
  4. Finding text on Text edit
    By jyoti kumar in forum Qt Programming
    Replies: 2
    Last Post: 18th May 2006, 13:20
  5. QTextEdit API questions (plain text)
    By Gaspar in forum Qt Programming
    Replies: 4
    Last Post: 16th May 2006, 06:03

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.