Results 1 to 18 of 18

Thread: Drawing a widget in QItemDelegate's paint method

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    May 2006
    Posts
    70
    Thanks
    12
    Thanked 4 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing a widget in QItemDelegate's paint method

    Alright, I guess what I was going for originally would look something like the screencap in this post:

    http://www.ereslibre.es/?p=61

    I know that's with KDE4.x but I was wondering if there was an easy way to implement it.

    Also, I have Qt 4.3.1 installed now and I'm still getting zero's in my sizeHint() option.rect parameter.

  2. #2
    Join Date
    May 2006
    Posts
    70
    Thanks
    12
    Thanked 4 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing a widget in QItemDelegate's paint method

    I'm beginning to think that there is a bug with the QStyleOptionViewItem parameter in QAbstractItemDelegate's sizeHint() method.

    How can I calculate the sizeHint if I don't know in what rect I'm working in? This makes drawing wrapped text impossible. I want to dynamically adjust the height depending on how much text can fit on screen.

    Ahh well.

  3. #3
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing a widget in QItemDelegate's paint method

    It is possible to implement dynamic word-wrap. I have done it for a QListView.

    See this post: http://www.qtcentre.org/forum/f-qt-p...view-8371.html

    Regards

  4. #4
    Join Date
    May 2006
    Posts
    70
    Thanks
    12
    Thanked 4 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing a widget in QItemDelegate's paint method

    Your code works wonderfully! Thanks.

    But isn't assuming that the parent of the delegate is a QListView a bad thing? So I modified your sizeHint() method to use QAbstractItemView instead of QListView.

    Qt Code:
    1. QString text = index.data(Qt::DisplayRole).toString();
    2. QFontMetrics fm(option.fontMetrics);
    3.  
    4. float rw = float(p->viewport()->size().width());
    5. float tw = fm.width(text);
    6. float ratio = tw/rw;
    7. int lines = int(ratio) + 1;
    8.  
    9. return QSize(rw,lines*fm.height());
    To copy to clipboard, switch view to plain text mode 

    But yes, the gaping flaw is that by using viewport()->size() this delegate will only work when the item consumes the entire width of the view. In a QAbstractTableView we will have problems. I guess I'll tackle one thing at a time.

    Thanks a ton for the help!

  5. #5
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing a widget in QItemDelegate's paint method

    But isn't assuming that the parent of the delegate is a QListView a bad thing?
    I made it for that particular case.
    I didn't think someone else might use it.

    Regards

  6. #6
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing a widget in QItemDelegate's paint method

    BTW:
    I'm beginning to think that there is a bug with the QStyleOptionViewItem parameter in QAbstractItemDelegate's sizeHint() method.

    How can I calculate the sizeHint if I don't know in what rect I'm working in? This makes drawing wrapped text impossible. I want to dynamically adjust the height depending on how much text can fit on screen.
    That QRect is actually based on the sizeHint you return.
    The framework first calls sizeHint for the delegate and then paints it.

    Regards

  7. #7
    Join Date
    May 2006
    Posts
    70
    Thanks
    12
    Thanked 4 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Drawing a widget in QItemDelegate's paint method

    That QRect is actually based on the sizeHint you return.
    The framework first calls sizeHint for the delegate and then paints it.
    Following that frame of thought, then making wrapping text work in a QTreeView and QTableView is different then in the QListView.
    I haven't tested this yet but I think you would do something like this:

    Qt Code:
    1. QSize PluginDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
    2. {
    3. int width;
    4.  
    5. if (qobject_cast<QColumnView *>(parent()) != 0) {
    6. QColumnView *v = qobject_cast<QColumnView *>(parent());
    7. width = v->columnWidths().at(index.column());
    8. } else if (qobject_cast<QHeaderView *>(parent()) != 0) {
    9. //i'm going to leave this out for now because I don't know how to get the width of a QHeaderView cell
    10. width = 100; //dumb value
    11. } else if (qobject_cast<QTableView *>(parent()) != 0) {
    12. QTableView *v = qobject_cast<QTableView *>(parent());
    13. width = v->columnWidth(index.column());
    14. } else if (qobject_cast<QTreeView *>(parent()) !=0) {
    15. QTreeView *v = qobject_cast<QTreeView *>(parent());
    16. width = v->columnWidth(index.column());
    17. } else if (qobject_cast<QListView *>(parent()) != 0) {
    18. QListView *v = qobject_cast<QListView*>(parent());
    19. width = p->viewport()->size().width();
    20. } else {
    21. //specify default value if we are using a non-standard view
    22. width = 400;
    23. }
    24.  
    25. // ... calculate text wrapping and cell/row height based on width.
    26.  
    27. // ... future feature: specify max # of text lines and then elide the text if it's too long. (see QFontMetrics::elidedText() method)
    28.  
    29. }
    To copy to clipboard, switch view to plain text mode 

    I'm sure there is a way to optimize that whole thing too, of course.

    Now if you know for sure that your delegate will only ever be used in a QListView then don't do the above.

  8. #8
    Join Date
    Jan 2009
    Posts
    11
    Thanks
    5

    Default Re: Drawing a widget in QItemDelegate's paint method

    Quote Originally Posted by darkadept View Post
    Alright, I guess what I was going for originally would look something like the screencap in this post:

    http://www.ereslibre.es/?p=61

    I know that's with KDE4.x but I was wondering if there was an easy way to implement it.

    Also, I have Qt 4.3.1 installed now and I'm still getting zero's in my sizeHint() option.rect parameter.

    Did anyone ever come up with similar list to the above. I am trying to produce something similar and finding it very hard

    Thanks
    Andy

  9. #9
    Join Date
    Jan 2009
    Posts
    2
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Question Re: Drawing a widget in QItemDelegate's paint method

    I'm reviving this thread, since I need a solution to exactly this kind of problem.
    I need to create a list of items with a lot of functionality and a "Look" which is quite different to a standard ListView.
    Each item has multiple images, text labels with multiple formats, and multiple "action" areas, with mouse-over "hot" re-draw funtionality.
    Also, anyone knows for sure what the lifetime of each item in a QListView is ? The list of items can be quite large, so I'm hopping it only keps in memory the items currently in view and requests re-draw/re-create of the item when it comes into view.
    To get an ideia of what i need, go have a look at any decently powerful, fully-functional tweeter client.

  10. #10
    Join Date
    Jan 2009
    Posts
    2
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: Drawing a widget in QItemDelegate's paint method

    Ok, I think I've got it.
    In case anyone else needs to do this:
    http://www.qtforum.org/article/25345...tviewitem.html

    Basically create a delegate inheriting QAbstractItemDelegate, with a reference to a widget which "looks" and "acts" like you want your nodes to do.
    Override editorEvent in your delegate and pass the event to your widget, remembering to set it's data first and to adjust mouse position for the widget.

    Then just use the sizeHint event to set data ( it will be called first every time your itemview needs something from your node) and render the widget to the painter in the paint event.

    Presto, virtual itemview having only one "real" widget no matter how many nodes. Tested with 50k items, works beautifully.

Similar Threads

  1. Drawing standard widgets using a custom paint engine
    By Waywocket in forum Qt Programming
    Replies: 26
    Last Post: 21st October 2010, 20:40
  2. Replies: 4
    Last Post: 10th March 2007, 18:01

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
  •  
Qt is a trademark of The Qt Company.