Results 1 to 17 of 17

Thread: QTreeView, Delegates and Persistent Widgets

  1. #1
    Join Date
    Jun 2008
    Posts
    88
    Thanks
    4
    Thanked 4 Times in 3 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11
    Wiki edits
    1

    Default QTreeView, Delegates and Persistent Widgets

    I've created a QTreeView with a custom model and would like to display custom widgets for manipulating the data.

    To do this Qt tells us to use the QItemDelegate (or the abstract one...) but this only provides an editor for the EditRole. In other words it only shows the delegate widget when a cell/index is in edit mode.

    I want to ALWAYS show the widget not just display it after an EditTrigger. (Please for the love of god dont ask why, thats just what this GUI requires)

    My model has some values that are boolean values. I would like to display (ie. in the default DisplayRole) these values in a QCheckBox. I dont want the user to have to double click to get to the check box. There's nothing worse than having to triple click to change the value.

    I could probably do a trick like paint a fake checkbox and change the EditTriggers to allow for a single click to toggle the value but that's a pretty ugly hack. It seems like Qt should support this behavior if it doesnt already. Any thoughts? I know that many people have asked this question before and as far as I can tell there are no satisfactory answers out there. How about we come up with a real solution.

    This may be the way to do it but its SUCKS and I wasn't able to actually get it to work. But calling
    Qt Code:
    1. QTreeView.openPersistentEditor(index)
    To copy to clipboard, switch view to plain text mode 
    should work. I tried it with the following code but nothing happened. But even if that did work... its besides the point, it pretty lame that you have to call that on every cell/index in your view. I have a pretty big model so it would be nice if I could do that on the entire treeview or at least on a given row/column.

    This seems like a pretty big oversight if its not natively supported. And it probably could use some better documentation

    Python:
    Qt Code:
    1. checkboxColumn = 2
    2. root = self._view.rootIndex()
    3. for i in range(self._view.model().rowCount(root)):
    4. self._view.openPersistentEditor(root.child(i, checkboxColumn))
    To copy to clipboard, switch view to plain text mode 

    Also to clarify... this is not just for check boxes... I might want to display a custom widget, or a combo box persistently.
    Last edited by chezifresh; 19th November 2008 at 00:46.

  2. #2
    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: QTreeView, Delegates and Persistent Widgets

    Why not use Qt::CheckStateRole and display the checkbox not as an editor but as a regular feature of the delegate?

  3. #3
    Join Date
    Jun 2008
    Posts
    88
    Thanks
    4
    Thanked 4 Times in 3 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11
    Wiki edits
    1

    Default Re: QTreeView, Delegates and Persistent Widgets

    That works for check boxes but how about comboboxes or custom widgets?

    Is there an easy way to override the delegate paint event to paint a real widget? One that responds to mouse events, not just a pixmap.

    I found that the persistent editor nearly does the job. I've modified my QTreeView derivation to implement an openPersistentEditorForColumn method. This will require quite a bit of tweaking to make it look right since the persistent editor does not recognize the parent's colors (which makes it look especially weird if you have alternating row colors on)... but thats a problem I'm bound to have.

    I suppose to make my life easier I can use the CheckStateRole when dealing with boolean values so I dont have to muck with the QCheckBox to make it paint right.

    I'll continue with the persistent editor and try to report back if it works out well (without having to hack it together)

    It still seems like this should be easier to do

  4. #4
    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: QTreeView, Delegates and Persistent Widgets

    The problem with inserting real widgets is that they slow down the view significantly when the number of items grows to more than 10 That's why you should avoid things like persistant editors. If you want comboboxes, they are easy to render, so by using QStyle you should be able to mimic them while the item is inactive. But for this particular situation I would suggest to open a single editor when you need it (you can react on clicking the view). Another solution is to have the editor as a totally external widget and update it when the item is changed (you can use QDataWidgetMapper for that).

  5. The following user says thank you to wysota for this useful post:

    chezifresh (19th November 2008)

  6. #5
    Join Date
    Jun 2008
    Posts
    88
    Thanks
    4
    Thanked 4 Times in 3 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11
    Wiki edits
    1

    Default Re: QTreeView, Delegates and Persistent Widgets

    Thanks for the replies. I'll have to consider if its worth the extra work/processing time to use persistent editors. For the time being at least I'll use the builtin checkboxes for boolean values and non-persistent editors for drop downs.

  7. #6
    Join Date
    Feb 2009
    Posts
    51
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QTreeView, Delegates and Persistent Widgets

    Quote Originally Posted by wysota View Post
    Why not use Qt::CheckStateRole and display the checkbox not as an editor but as a regular feature of the delegate?
    Hi Wysota,

    Pardon my ignorance, but I've been trying to do the same thing: implement a treeview with checkboxes and so far cannot get it to work. Could you elaborate more on how to use the Qt::ChectStateRole to achieve this?

    Thank you
    Sincerely,

    Wieland J.

  8. #7
    Join Date
    Jun 2008
    Posts
    88
    Thanks
    4
    Thanked 4 Times in 3 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11
    Wiki edits
    1

    Default Re: QTreeView, Delegates and Persistent Widgets

    I found that it kind of sucks using an QAbstractItemModel. So I'm now using a QStandardItemModel which is AWESOME.

    Qt Code:
    1. class StandardAssetItem(QtGui.QStandardItem):
    2. '''The StandardAssetItem represents a row/column cell in the Qt model.
    3. '''
    4. SUPPORTED_ROLES = [ Qt.EditRole, Qt.DisplayRole, Qt.CheckStateRole ]
    5.  
    6. def __init__(self, mydata):
    7. QtGui.QStandardItem.__init__(self)
    8.  
    9. self._mydata = mydata
    10. if type(mydata) == types.BooleanType:
    11. checkstate = Qt.Unchecked
    12. if mydata == True:
    13. checkstate = Qt.Checked
    14.  
    15. self.setCheckState(checkstate)
    16. self.setCheckable(True)
    17. self.setEditable(False)
    18.  
    19. elif type(mydata) == types.StringType:
    20. self.setText(mydata)
    21.  
    22. else:
    23. self.setEditable(False)
    24.  
    25. def setData(self, variant, role):
    26. if role not in self.SUPPORTED_ROLES:
    27. return QtGui.QStandardItem.setData(self, variant, role)
    28.  
    29. value = None
    30. if role in [ Qt.EditRole, Qt.DisplayRole ]:
    31. value = variant.toPyObject()
    32. if type(value) == PyQt4.QtCore.QString:
    33. # convert it to a std string.
    34. value = str(value)
    35. elif role == Qt.CheckStateRole:
    36. checkstate, okay = variant.toInt()
    37. value = checkstate == Qt.Checked
    38.  
    39. if self._mydata != value:
    40. self._mydata = value
    41. # and tell the world the value changed
    42.  
    43. QtGui.QStandardItem.setData(self, variant, role)
    To copy to clipboard, switch view to plain text mode 

    Then in your subclass of the standard item model you use this item instead of QModelIndexes (you dont need to subclass StandardItem, but it might be useful to do)

  9. #8
    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: QTreeView, Delegates and Persistent Widgets

    Quote Originally Posted by jwieland View Post
    Pardon my ignorance, but I've been trying to do the same thing: implement a treeview with checkboxes and so far cannot get it to work. Could you elaborate more on how to use the Qt::ChectStateRole to achieve this?
    You have to make your model aware of that role. So you have to make it store it somewhere and return data for it when asked from within the data() method. You also need to modify the flags returned by the model for items you wish checkable so that they return ItemIsUserCheckable.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #9
    Join Date
    Apr 2007
    Location
    Sunny Darwin, NT Australia
    Posts
    186
    Thanks
    29
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QTreeView, Delegates and Persistent Widgets

    Quote Originally Posted by chezifresh View Post
    I found that it kind of sucks using an QAbstractItemModel. So I'm now using a QStandardItemModel which is AWESOME.

    Qt Code:
    1. ...
    To copy to clipboard, switch view to plain text mode 

    Then in your subclass of the standard item model you use this item instead of QModelIndexes (you dont need to subclass StandardItem, but it might be useful to do)
    Hey I don't follow you here, I don't know python and can't understand what your code does or which methods you're over-riding. I assume you got your table view to accept a single click ? that's what I want to do with my view too. Can you please expand on what you've done ?

  11. #10
    Join Date
    Jun 2008
    Posts
    88
    Thanks
    4
    Thanked 4 Times in 3 Posts
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11
    Wiki edits
    1

    Default Re: QTreeView, Delegates and Persistent Widgets

    I'm just subclassing QStandardItem and passing in a value in the constructor. Then based on the type of the value it either builds a check box or a normal QTreeView cell.

    Now of course you dont need to subclass QStandardItem, you can just check if your value is a boolean call:

    Qt Code:
    1. // for boolean values
    2. int checkstate = Qt::Unchecked;
    3. if mydata == true
    4. checkstate = Qt::Checked;
    5.  
    6. item->setCheckState(checkstate);
    7. item->setCheckable(true);
    8. item->setEditable(false);
    To copy to clipboard, switch view to plain text mode 

    (that code might not be absolutely correct, I just wanted to make sure you could understand the C++ version of what I'm doing_

    In my code I'm actually passing in a pointer to my object, and when setData on the QStandardItem is called I also update my object.... that way my object and the model are sync'd up without having to write my own model from scratch using a QAbstractItemModel. This works pretty well for me since I'm not to worried about the hierarchy of my model changing or things getting reordered outside of the view. If you need to worry about that then you might rethink things or at the very least implement a subject-observer to detect changes

  12. #11
    Join Date
    Mar 2006
    Location
    San Francisco, CA
    Posts
    23
    Thanks
    9
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Question Re: QTreeView, Delegates and Persistent Widgets

    Hi ...

    So, if we could go back to combo boxes for a second, how many clicks on a view item does your program need to open a combo box ? One or more .. ?

    Thanks.

  13. #12
    Join Date
    Apr 2007
    Location
    Sunny Darwin, NT Australia
    Posts
    186
    Thanks
    29
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QTreeView, Delegates and Persistent Widgets

    Quote Originally Posted by barnabyr View Post
    Hi ...

    So, if we could go back to combo boxes for a second, how many clicks on a view item does your program need to open a combo box ? One or more .. ?

    Thanks.
    You can do it with one click. I implemented my own method which uses a custom delegate and re-implements the editorEvent(). The following code is for a check box, but it wouldn't be much diferent for any other type of widget.

    Qt Code:
    1. // Trap the mouse button in editorEvent and check/uncheck the checkbox by calling setData()
    2. // which is a subclassed member of the model this delegate is attached to.
    3. bool CheckBoxDelegate::editorEvent ( QEvent * event,
    4. const QStyleOptionViewItem & /* option */,
    5. const QModelIndex & index )
    6. {
    7. if (event->type() == QEvent::MouseButtonRelease)
    8. {
    9. bool checkState = index.model()->data(index, Qt::CheckStateRole).toBool();
    10. model->setData(index, !checkState);
    11. }
    12. return true; // Event has been handled here.
    13. }
    To copy to clipboard, switch view to plain text mode 

  14. #13
    Join Date
    Mar 2006
    Location
    San Francisco, CA
    Posts
    23
    Thanks
    9
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QTreeView, Delegates and Persistent Widgets

    Quote Originally Posted by vieraci View Post
    You can do it with one click. I implemented my own method which uses a custom delegate and re-implements the editorEvent(). The following code is for a check box, but it wouldn't be much diferent for any other type of widget.
    Hmm. Well for a check box it's easy. You are just toggling the state based on the mouse release event. But for a combobox you have to populate the combo and then actually care about which one was selected. Which all needs to happen though more events. I guess, because of the complexity, that's why the standard way of implementing the delegate is through the createEditor(), setEditorData(), setModelData() paradigm.

    I'd be interested to see an example if you have one ....

  15. #14
    Join Date
    Jan 2008
    Location
    Poland
    Posts
    687
    Thanks
    4
    Thanked 140 Times in 132 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QTreeView, Delegates and Persistent Widgets

    for a combobox you can make a real QComboBox for each item, but set WA_DontShowOnScreen, and instead of this render it in delegate's paint method using QWidget::render() (you have to set the eventFilter on every widget so you can react on PaintEvents). Then enable mouseTracking in the view (or it's viewport - dont remember) and handle mouse movement and clicks in editorEvent().
    I would like to be a "Guru"

    Useful hints (try them before asking):
    1. Use Qt Assistant
    2. Search the forum

    If you haven't found solution yet then create new topic with smart question.

  16. #15
    Join Date
    Apr 2007
    Location
    Sunny Darwin, NT Australia
    Posts
    186
    Thanks
    29
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QTreeView, Delegates and Persistent Widgets

    You don't have to make a real combo box, it is populated in createEditor() method and don't forget, it's data is already set. All that has to be done is in the editorEvent() method, just call showPopup(). (I haven't tested but it should be this easy).
    Last edited by vieraci; 6th July 2009 at 23:57. Reason: updated contents

  17. #16
    Join Date
    Sep 2009
    Posts
    22
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTreeView, Delegates and Persistent Widgets

    Hi...
    I think that my question isn't out of argument from the others, so I post here.

    I have to obtain a result similar to that in the attached photo.
    I started from different Qt examples in order to test different ways to obtain some results and then put them together.
    At the moment I'm a bit stuck on a problem (the first): how to present data from the model in a frame like the one on the right of the sample photo. I tried to modify the spinboxdelegate example to visualize/edit/modify the data from the table in a lateral frame, but with no succes, because I don't know how to place the widget created by
    QWidget *SpinBoxDelegate::createEditor function. I tried to reimplement the paint method, but the problem is always the same...
    The 2nd problem is: I'm reading a lot of documentation trying to comprehend if delegates are the best solution to achieve my goal. At the moment I think so... But if someone has got much experience in this kind of programming and can indicate me an eventually better way, I'll surely evaluate it.

    Note: At the moment I'm stuck on the first problem... The second is a little bigger, but It is part of the evaluation process.

    I really hope someone can help me!
    Best regards and Thanks in advance for your help.
    Alex
    Attached Images Attached Images

  18. #17
    Join Date
    Sep 2009
    Posts
    22
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTreeView, Delegates and Persistent Widgets

    Any help?
    Now I tried another way to obtain my goal.
    I started from a little and simple example of the treemodel and I created a model containing items from a file. As item I used QStandardItem, as model I used QStandardItemModel, and I visualized all in a QTreeView. I stored in the various Items different kind of data: an icon with DecorationRole, a string with DisplayRole and some custom data with UserRole. Now my problem is:
    the data that I want to edit when I doubleclick an item are stored in UserRole because if I store them with EditRole they become the same as DisplayRole ('cause of the standard implementation of QStandardItem).
    My questions are:
    1. How can I edit data in UserRole?
    2. If that is not possible, I suppose I have to subclass QStandardItem and reimplement data and setData methods... Is it possible to reimplement only this two methods to obtain a different behaviour for DisplayRole and EditRole? Could someone please post an example?
    3. Any hints on how to edit data? I think a custom delegate would be the better way, do you?

    Thanks,
    Alex

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.