Nominate our 2022 Qt Champions!

SetItemDelegateForRow vs setItemDelegate?

  • I'm very new to the delegate system and am trying to build a GUI that is similar to photoshop's layers UI. The layers UI is a scrollable list of custom widgets (a frame with a label and 2 toolbar buttons in it):

    |[button][button][ label ]|

    The list is a sub-class of QListView. I have sub-classed QStandardItem for the list items and sub-classed QStyledItemDelegate for my delegate.

    The states of the buttons and text in the labels will be different for each list item (layer). The list starts out empty and list items are added when a specific data file is loaded in the editor (that contains this UI) or when a person manually adds an item to the list through UI. Users can also delete the selected list item from the list.

    My delegate is setup for the custom widget and I have been using setItemDelegateForRow when a new list item is added. Everything works great until I try to delete a list item and re-select the row it used to be on. I'm guessing that the list still stores a pointer to the deleted delegate because I had called setItemDelegateForRow. So I assume I have to update all the existing delegates for the current rows again (i.e. call setItemDelegateForRow with the correct row and delegate). Is that correct?

    Then I started to think if this wasn't the best way to set the delegate for my purposes. Should I be calling setItemDelegate instead? If I do that, I do not want the delegate to render until one item (layer) is added to the listbox. So I would not be able to call setItemDelegate until at least 1 layer (list item) has been added to the listbox, correct? And I'm assuming I only need to call it once as any new layer that is added will have the delegate set already. Also, how does setItemDelegate know the row to draw the widget on? I think I tried this initially and all the widgets were being drawn on top of each other at row 0.

    Sorry for all the questions. Again, I'm new to delegates.

    Thanks in advance for help!

  • The delegate is only called if there is something to draw. So I would go with only one delegate that handles everything and set that in the constructor. You need not to care for the delegate later on, it's all handled by the view automatically.

    The method "paint": gets a pointer to painter. Just use this one to paint. The QStyleOptionViewItem parameter contains a variable rect, that describes the paintable area.

    Be sure to reimplement the sizeHint method, so that the view can calculate the needed space correctly.

    I would recommend to start with [[Doc:QStyledItemDelegate]] as a base class.

  • Thanks, Volker. I will try it. I did have paint and sizeHint already reimplemented but maybe I didn't do something correctly as the list items were drawing on top of each other when I tried setItemDelegate initially.

Log in to reply