[PySide] simple QTableView example

Aaron Richiger a.richi at bluewin.ch
Sun Oct 13 13:52:14 CEST 2013


Hello Frank!

You're welcome. I will send you more details later (do not have too much 
time for the moment). But just to give you the direction:

If the animation is a must-have, I would not go the way with QTableView 
nor the way with QListView or QTreeView. Without animation, those are 
perfect, but if you really want the fancy animations, I would do it like 
this:

- Implement a widget to show a TODO-Item
- Show them absolutely positioned one after the other
- Implement buttons for "Add new", "Sort", "Filter"
- In case of sort or filtering: calculate new position for each item, 
animate it to new position using QParallelAnimationGroup

See you later!
Aaron





Am 13.10.2013 13:18, schrieb Frank Rueter | OHUfx:
> Great, thanks Tibold and Aaron! That all makes sense.
>
> Incidentally I do have planned a bit more than just the standard table 
> UI but thought I'd leave that for when I'm more comfortable with the 
> basic concepts again.
> So am keen to test all suggested approaches and have a feeling I might 
> have to go with a custom solution as I want some animation to happen 
> when sorting (each line moving to it's new position) - but that's for 
> later, for now I will stick to the basics.
>
> Aaron, when trying the setItemDelegateForColumn (sorry, how could I 
> not have seen this one before) things work fine but I have to cast the 
> incoming data to int() explicitly in side the setEditorData. The 
> setModelData method seems to automatically cast the integer back to a 
> string. Is this the right way to do it?
>
>     def setEditorData(self, spinBox, index):
>         value = index.model().data(index)
>         spinBox.setValue(*int(value)*)*# cast string to int*
>
>     def setModelData(self, spinBox, model, index):
>         spinBox.interpretText()
>         value = spinBox.value()
>         model.setData(index, *value*)*# no need to cast int back to 
> string?*
>
>
> Looking ahead: If I want to make the rows/tasks animate to their new 
> positions upon sorting, can I re-implement the paint methods of, say, 
> a QAbstractItemView or do I have to go back further and do more manual 
> work?
> I need to stick to the standard PySide package for this for various 
> reasons.
>
> Cheers and thanks again Tibold, Aaron and Sebastian, you are a great 
> help as usual!
>
> frank
>
>
>
> On 13/10/13 12:39 AM, Aaron Richiger wrote:
>> Hello!
>>
>> Tibolds approach would work (and could result in a nicer UI). Both 
>> solutions are possible, some thoughts about the QTableView approach:
>>
>> - your app smells like a future database app. QTableView is in 
>> advantage then, because by using QSqlTableModel, you get all the 
>> mapping betwenn the db and the model for free.
>> - By using QTableView, sorting, filtering etc. is already included 
>> and if your table has manymany rows, it will be much faster than any 
>> self implemented filtering/sorting algorithm. But as long, as your 
>> todo list doesn't have thousands of entries (and I hope so for 
>> you:-), performance isn't an argument.
>>
>> Changes to your code to have the spinbox in the middle column only:
>>
>>         priorityDelegate = SpinBoxDelegate(tableView)
>>         tableView.setItemDelegateForColumn(1, priorityDelegate)
>>
>> Like this, the first column remains "text-editable", and for the last 
>> column with the checkbox, you don't even necessarily have to 
>> implement a new delegate, reimplementing .flags(), setData() and 
>> data() methods of your model is enough (but if you want a pure 
>> checkbox without a label next to it, you have to write your own 
>> delegate, I could send you the code).
>>
>> Feel free to choose what ever way you want, both are perfectly 
>> doable, having advantages where the other variant has disadvantages...
>>
>> Cheers
>> Aaron
>>
>>
>> Am 13.10.2013 00:06, schrieb Tibold Kandrai:
>>> If you ask me personally, I wouldn't use QTableWidget. Look into 
>>> QTreeView or QListWidget.
>>> I think they are more suitable for such tasks and are easier to handle.
>>> With QTreeView you can use QItemDelegate, to create a special rendering.
>>> With QListWidget you can simply add a widget per row and inside the 
>>> widget you can put whatever.
>>> ATM I'm in the middle of a 2000 km road trip so I can't rally 
>>> provide you sample's, but if you need help next week I'm glad to 
>>> give you samples how to use these widgets.
>>> Cheers,
>>> Tibold Kandrai
>>> *From:* Frank Rueter | OHUfx
>>> *Sent:* ?Saturday?, ?12? ?October? ?2013 ?22?:?49
>>> *To:* Tibold Kandrai
>>> *Cc:* pyside at qt-project.org
>>> Is this the best way to do it though? I.e. having one item per cell? 
>>> s there another way at all?
>>> I'm still a bit lost in the model/view design and can't find the 
>>> answer online.
>>>
>>> I'm simply trying to have each row represent a "task" with a 
>>> title/description (string), a status (boolean) and a priority 
>>> (integer). For the integer I need a spin box and for the boolean I 
>>> need a checkbox. The examples I found online all seem to be doing 
>>> something slightly different and often use different ways which 
>>> makes matters more confusing.
>>>
>>> Here is what I have at the moment:
>>> http://pastebin.com/H3GD0xVB
>>>
>>> The "status" and "priority" values don't display currnelty as I 
>>> haven't figured out how to properly assign a delegate to just those 
>>> cells. At the top I tried to define a n item delegete for a spin box 
>>> but I'm not sure how to properly assign it.
>>>
>>> Do I have to make the delegate draw different widgets (spin box / 
>>> checkbox) depending on data type, or can/should I use a different 
>>> delegate for each cell?
>>>
>>> I'm sure the answer is right in front of me, could you please help 
>>> one more time please?!
>>>
>>> Cheers,
>>> frank
>>>
>>>
>>> On 11/10/13 4:00 PM, Tibold Kandrai wrote:
>>>
>>>     If you mean to use a QStandardItem per cell then yes.
>>>     Also for storing values that you want to display, use the
>>>     Qt.DisplayRole as role.
>>>
>>>     Cheers,
>>>     Tibold Kandrai
>>>     ------------------------------------------------------------------------
>>>     From: Frank Rueter | OHUfx <mailto:frank at ohufx.com>
>>>     Sent: ?11/?10/?2013 14:35
>>>     To: Tibold Kandrai <mailto:kandraitibold at gmail.com>
>>>     Cc: pyside at qt-project.org <mailto:pyside at qt-project.org>
>>>     Subject: Re: [PySide] simple QTableView example
>>>
>>>     one more silly question if I may:
>>>     So if I have a task like this:
>>>             newTask = {'title':'new task', 'priority':1, 'status':False}
>>>
>>>     and need to store the data in one row in the model I should use
>>>     three different items, one for each value, right?!
>>>
>>>     e.g.:
>>>
>>>             newTask = {'title':'new task', 'priority':1, 'status':False}
>>>             row = self.model.rowCount()
>>>             for column, attr in enumerate(['title', 'priority',
>>>     'status']):
>>>                 newItem = QtGui.QStandardItem(newTask[attr])
>>>                 self.model.setItem(row, column, newItem)
>>>
>>>     then juggle delegates or widgets to use a spin box for the
>>>     integer and a checkbox for the boolean...
>>>
>>>     Thanks for the help!
>>>
>>>     Cheers,
>>>     frank
>>>
>>>     On 10/10/13 11:44 PM, Tibold Kandrai wrote:
>>>
>>>         Hey,
>>>         I'm not sure I understand the problem correctly.
>>>         If you want to store data in a cell or a QStandardItem, then
>>>         you need to use setData() and data().
>>>         Generally you shouldn't need to subclass QStandardItem or
>>>         QStandardItemModel.
>>>         Here is an example how:
>>>         # Define roles
>>>         FINISHED_ROLE = QtCore.Qt.UserRole + 1
>>>         PRIORITY_ROLE = QtCore.Qt.UserRole + 2
>>>         # Create model
>>>         model = QtGui.QStandardItemModel()
>>>         item = QtGui.QStandarItem()
>>>         model.appendRow(item)
>>>         item_index = item.index()
>>>         # Store data using the item
>>>         item.setData(finished, FINISHED_ROLE)
>>>         item.setData(priority, PRIORITY_ROLE)
>>>         # Store data using the model
>>>         model.setData(item_index, finished, FINISHED_ROLE)
>>>         model.setData(item_index, priority, PRIORITY_ROLE)
>>>         # Retrieve data using the item
>>>         finished = item.data(FINISHED_ROLE)
>>>         priority = item.data(PRIORITY_ROLE)
>>>         # Retrieve data using the model
>>>         finished = model.data(item_index, FINISHED_ROLE)
>>>         priority = model.data(item_index, PRIORITY_ROLE)
>>>         In some cases like click event handlers, you have the model
>>>         and the item index, there it's easier to use the model
>>>         methods instead of finding the item and then getting the data. ?
>>>         Hope it helps.
>>>         Cheers,
>>>         Tibold
>>>         *From:* Frank Rueter | OHUfx
>>>         *Sent:* ?2013? ?October? ?10?, ?Thursday ?19?:?37
>>>         *To:* pyside at qt-project.org
>>>         After looking at some more examples I think my approach of
>>>         storing multiple values in one item is fundamentally flawed.
>>>         Instead I should be using one item per cell and assign the
>>>         respective data, right?!
>>>
>>>         I shall re-write the example accordingly, sorry for the noise.
>>>
>>>         frank
>>>
>>>         On 10/10/13 6:34 PM, Frank Rueter | OHUfx wrote:
>>>
>>>             I meant QTableView not QStandardTableView :/
>>>
>>>             On 10/10/13 6:33 PM, Frank Rueter | OHUfx wrote:
>>>
>>>                 Hi all,
>>>
>>>                 after a bit of a break from PySide I am trying to
>>>                 wrap my head around the model/view stuff again and
>>>                 am trying to understand how a very simple example
>>>                 would work where a QStandarItem has properties
>>>                 "title", "priority" and "finished" which are
>>>                 displayed via a QStandardTableView.
>>>
>>>                 I am struggling with understanding how to properly
>>>                 display the above three properties in the table's
>>>                 columns. I tried setting the data() method on the
>>>                 model like this:
>>>
>>>                 /    def data(self, index,
>>>                 role=QtCore.Qt.DisplayRole)://
>>>                 //        '''Return data based on index and role'''//
>>>                 //        item = self.itemFromIndex(index)//
>>>                 //        if index.column() == 0://
>>>                 //            return item.title//
>>>                 //        elif index.column() == 1://
>>>                 //            return item.finished//
>>>                 //        elif index.column() == 2://
>>>                 //            return item.priority/
>>>
>>>                 but for some reason it errors saying item does not
>>>                 have attribute "finished" even though my item object
>>>                 s declared like this:
>>>
>>>                 /class TaskItem(QtGui.QStandardItem)://
>>>                 //    '''Item to hold a task for the todo list'''//
>>>                 ////
>>>                 //    def __init__(self, title, finished=False,
>>>                 priority=1)://
>>>                 //        super(TaskItem, self).__init__(title)//
>>>                 //        self.title = title//
>>>                 //        self.finished = finished//
>>>                 //        self.priority = priority/
>>>
>>>
>>>                 When printing the item's attributes via dir() I see
>>>                 that, when the model is populated, the last item it
>>>                 attempts to call is not my custom item object, but
>>>                 something else with less attributes and methods.
>>>                 Clearly there is something I haven't quite
>>>                 understood about this process.
>>>
>>>                 Also, if I use the models data() method as pointed
>>>                 out above, I get checkboxes in the cells which I
>>>                 don't want at this stage.
>>>
>>>                 Can somebody please help me understand where I go wrong?
>>>                 Attached is the whole test code.
>>>
>>>                 Cheers,
>>>                 frank
>>>
>>>                 P.S.: I am aware that the controller code shouldn't
>>>                 necessarily live in the QWidget's methods, this is
>>>                 just for testing which I will clean up once I get
>>>                 how it all connects again
>>>
>>>
>>>                 _______________________________________________
>>>                 PySide mailing list
>>>                 PySide at qt-project.org
>>>                 http://lists.qt-project.org/mailman/listinfo/pyside
>>>
>>>
>>>
>>>
>>>             _______________________________________________
>>>             PySide mailing list
>>>             PySide at qt-project.org
>>>             http://lists.qt-project.org/mailman/listinfo/pyside
>>>
>>>
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> PySide mailing list
>>> PySide at qt-project.org
>>> http://lists.qt-project.org/mailman/listinfo/pyside
>>
>>
>>
>> _______________________________________________
>> PySide mailing list
>> PySide at qt-project.org
>> http://lists.qt-project.org/mailman/listinfo/pyside
>
>
>
> _______________________________________________
> PySide mailing list
> PySide at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/pyside

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/pyside/attachments/20131013/5f43c4d9/attachment.html>


More information about the PySide mailing list