PDA

View Full Version : QAbstractItemView questions



krudio
2nd November 2007, 22:49
Hello,

I am trying to build my own custom view by subclassing QAbstractItemView, but I am having some problems getting it to display my items.

Basically, my view looks into a model and builds a graphical repsentation of the model using widgets to represent the items. Each widget has its own x and y coordinates that visualRect() uses to render the widgets on the view.

The problem is, visualRect() is only rendering the last item in the model on the view. None of the other items are rendered, even though I have verified that their positioning information is correct, and that visualRect() is returning a valid QRect with the proper size and coordinates. So it seems like visualRect() is only being called for the last item in the model.

Is there any way to ensure that visualRect() gets called for ALL items in the model? I've tried to invoke it manually for each index in my model, but it still doesn't work. It seems like Qt is doing something that I have no control over. Any advice?

Thanks!

marcel
2nd November 2007, 23:01
You should use a QAbstractItemDelegate subclass to custom paint your items, not widgets + QAbstractItemView.

krudio
2nd November 2007, 23:07
You should use a QAbstractItemDelegate subclass to custom paint your items, not widgets + QAbstractItemView.
Unfortunately, I need to use custom QWidgets in this case, due to the limitation of delegates.

jpn
3rd November 2007, 17:01
Hello.

I must say that I fully agree with Marcel. The whole point with item views is to get rid of expensive widgets, to replace them with light items.

Unfortunately, I need to use custom QWidgets in this case, due to the limitation of delegates.
Would you mind describing a bit what you do? Maybe we could find a way to do it with delegate.. ;)

krudio
5th November 2007, 08:54
Hello.

I must say that I fully agree with Marcel. The whole point with item views is to get rid of expensive widgets, to replace them with light items.

Would you mind describing a bit what you do? Maybe we could find a way to do it with delegate.. ;)

Basically, I'm trying to create a custom view that displays a hierarchy of data in a tree format. I am already using a separate software library to calculate the coordinates of each node and it's connecting lines, so I have all the positioning data I need.

We considering doing this using a QGraphicsScene at first, but each node needs to represent an item in a QStandardItemModel, and so the 2D approach simply won't work for us. Therefore, I have relegated to subclassing QAbstractItemView to obtain this functionality.

I am pretty close to getting it functional--I can draw the lines by overriding paintEvent(), but I can't seem to get all the nodes to render. Only the last leaf node in the model seems to display, even though I have verified that each node has the correct positioning data. I have even tried calling visualRect() manually on each item in the model, and still no luck.

Thanks again for the help!

wysota
5th November 2007, 10:37
Overriding paintEvent() won't do the trick if you want to use widgets... The view infrastructure is not suited for using widgets. I second what jpn and marcel have said - the view is meant to be consisting of items, not widgets - what was the limitation of the delegates you meant? Maybe there is a way to overcome it?

If you really need widgets, I suggest you get rid of the abstract item view dependency and implement your view based on QWidget (or QScrollArea). You can take all the functionality you need from the model (like reacting to changes in the model) to operate on your view. Then you can ignore painting the widgets (items) as they'll be painted as real widgets. You'll just have to position them manually from within resizeEvent() or implement a custom layout that will do it for you.

If you decide to implement the view from scratch, I suggest you make use of dataChanged(), layoutChanged(), rowsInserted() and rowsRemoved() signals of the model to populate and update your view. Most of the functionality of the abstract view is related to items and if you don't want to use them as such, you can safely ignore that part and when you do, you'll see that you have only a few methods to implement.

krudio
5th November 2007, 18:57
Well, I'm using the setIndexWidget() method to create the node widgets at each index in the model, and I'm overriding paintEvent() to draw the lines. I have a custom method that is handling the layout of the widgets as well. In any case, I have finally gotten my view to work, barring a few features that I still need to implement. I appreciate the help, and will let you know if I run into any other issues. Thanks!

wysota
5th November 2007, 19:25
A quick note - using setIndexWidget() makes your view unscalable - it will get horribly slow when you increase the number of index widgets.

maximAL
15th January 2008, 00:05
would it be feasible to use a view to represent some time-lines, each containing events?
eg, several time lines, each containing a few events displayed as eg. boxes on the timeline. of course, with full drag and drop support, plus defining begin/end of events by direct manipulating these boxes with the mouse.

an underlying data model would be straight - forward: on the top-level the timelines, each with one level of children for the events constisting of a begin/end time.

now, the problem of course would be mapping the event-items into the the timelines, since a simple grid wouldn't be sufficient (unless maybe the granularity would be high enough, to make the user believe there wasn't a grid - but that might become inefficient very fast).
now, i can imagine just drawing some boxes for the events...but not using widgets would make the whole resizing thing much more complex.

is this possible at all? or would a plain custom widget be the better choice?

wysota
15th January 2008, 01:06
would it be feasible to use a view to represent some time-lines, each containing events?
eg, several time lines, each containing a few events displayed as eg. boxes on the timeline. of course, with full drag and drop support, plus defining begin/end of events by direct manipulating these boxes with the mouse.
Yes, of course.


an underlying data model would be straight - forward: on the top-level the timelines, each with one level of children for the events constisting of a begin/end time.
Seems ok.


now, i can imagine just drawing some boxes for the events...but not using widgets would make the whole resizing thing much more complex.
What would you use widgets for?


or would a plain custom widget be the better choice?
A plain widget? No. But using QGraphicsView is an option.

maximAL
15th January 2008, 10:00
What would you use widgets for?
...
A plain widget? No. But using QGraphicsView is an option.
well, after all it would be nice to be able to use widgets, since the look should be similar to a QTableView (with one column, but the rows should contain the items), what could be achieved with a few basic widgets.
rendering everything myself seems like a daunting task - esp. since i've never done that in Qt ;)

wysota
15th January 2008, 10:59
Consider using QScrollArea then. But if you'll want to use the model with it, you'll have to implement it all yourself. I don't know what exactly would you like to display, but if you are not sure you need widgets, consider not using them and going for the view with a custom delegate or no delegate at all (with a custom view).

maximAL
15th January 2008, 11:32
I don't know what exactly would you like to display

what i want to achieve is a window maybe similar to the central or far right window in this screenshot from muse :

http://www.kde-apps.org/CONTENT/content-pre1/9923-1.png

unfortunaltly i'm working under windows atm, so i can't really try it out now.