[PySide] simple QTableView example
Frank Rueter | OHUfx
frank at ohufx.com
Sat Oct 19 00:35:20 CEST 2013
Perfect, thanks once again!
On 18/10/13 11:29 PM, Aaron Richiger wrote:
> Hi Frank!
>
> You're welcome! By catching the resizeEvent in the MainWindow, you can
> then update() it.
>
> def resizeEvent(self, event):
> self.update()
>
> When resizing taskContainer in the update() method, you of course
> should replace the fix value of 300 by something more dynamic,
> "self.scrollArea.width() - 2" works perfectly for me. Minus 2 because
> of the border width of the scrollarea, otherwise a horizontal
> scrollbar shows up... Therefore I made scrollArea a class member. You
> get the entire code in the attachment.
>
> Cheers!
> Aaron
>
>
>
> Am 18.10.2013 08:20, schrieb Frank Rueter | OHUfx:
>> Hi Aaron,
>>
>> thanks again for this example, it's a huge help!
>> I have re-written everything from scratch following your example and
>> everything is going well, I just can't figure out how to make the
>> TaskWidget scale horizontally when the main application window is scaled.
>> I have tried re-implementing sizeHint() on the container widget but
>> to no avail.
>> What am I missing?
>>
>> Cheers,
>> frank
>>
>> On 15/10/13 1:22 AM, Aaron Richiger wrote:
>>> Hello Frank!
>>>
>>> I just implemented the approach I told you yesterday (without
>>> QTableView, QListView, etc because you wanted animations). You can
>>> see the code of the working app in the attachment, it's in a
>>> classical MVC setup. Because dealing with databases is a bit more
>>> work when not using QSqlTableModel, I save and load tasks and user
>>> settings between sessions using pickle. I did not spend much time on
>>> a nice design, it's just to give you some sample code in case you
>>> really want the animations. With some more lines of code, you can
>>> pimp the design according to your wishes.
>>>
>>> Have a nice day!
>>> Aaron
>>>
>>>
>>>
>>> Am 13.10.2013 13:54, schrieb Frank Rueter | OHUfx:
>>>> sweet, that was my hunch, just didn't want to barge in the wrong
>>>> direction.
>>>> I will keep doing some more basics as per the suggestions from you
>>>> and the others before embarking on this one, but have an idea now
>>>> how to tackle it.
>>>>
>>>> Cheers,
>>>> frank
>>>>
>>>> On 13/10/13 1:52 PM, Aaron Richiger wrote:
>>>>> 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
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> 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/20131019/7ae06fe5/attachment.html>
More information about the PySide
mailing list