[PySide] simple QTableView example
Aaron Richiger
a.richi at bluewin.ch
Fri Oct 18 12:29:15 CEST 2013
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/pyside/attachments/20131018/423d3099/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: todo_list.py
Type: text/x-python
Size: 10158 bytes
Desc: not available
URL: <http://lists.qt-project.org/pipermail/pyside/attachments/20131018/423d3099/attachment.py>
More information about the PySide
mailing list