i am creating a treeview (QTreeView), and i set a model
(QAbstractItemModel) for it (using setModel() method).
now i update the model (with new data), and call treeview.update()
with the hope that my treeview will be redrawn to reflect the new
data.
however, that doesnt update the view. i looked closer, and confirm
that even after treeview.update() is called, the rowCount() method of
the model is not executed at all. which means the update() doesnt do
anything with the new model data.
i must missed something. anybody please tell me how to fix this problem?
thanks,
Jun
_______________________________________________
PySide mailing list
PyS...@lists.pyside.org
http://lists.pyside.org/listinfo/pyside
the slot QAbstractItemView.update() wants a QModelIndex as a parameter
http://www.pyside.org/docs/pyside/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.update
This means you need to pass the QModelIndex of the data you added to the model.
--
Daniele Esposti
My Blog http://www.expobrain.net
LinkedIn http://www.linkedin.com/in/danieleesposti
Twitter http://www.twitter.com/#!/expobrain
this means i need to call update() method of the model, right?
how about the update() method of the TreeView widget? do i need to call it?
thanks a lot,
I think you might fix this by emitting one of the row change signals
from your model. For example, rowsInserted --
http://developer.qt.nokia.com/doc/qt-4.8/qabstractitemmodel.html#rowsInserted
.
Joel
update(QModelIndex) is a slot in QAbstractItemView (and which is the
superclass of QTreeView); QAbstractItemModel doesn't have any update()
method at all.
What you can do (as far as I know about your code) is to emit a
rowsAboutToBeInserted() before adding the data to your model and
rowsInserted() after the data is added to your model. The view
connected to your model will show your data automatically.
On 7 February 2012 11:23, Jun Koi <junko...@gmail.com> wrote:
> On Tue, Feb 7, 2012 at 7:08 PM, Daniele Esposti <ex...@expobrain.net> wrote:
>> Hi Jun,
>>
>> the slot QAbstractItemView.update() wants a QModelIndex as a parameter
>> http://www.pyside.org/docs/pyside/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.update
>>
>> This means you need to pass the QModelIndex of the data you added to the model.
>
> this means i need to call update() method of the model, right?
>
> how about the update() method of the TreeView widget? do i need to call it?
>
> thanks a lot,
> Jun
--
Daniele Esposti
My Blog http://www.expobrain.net
LinkedIn http://www.linkedin.com/in/danieleesposti
Twitter http://www.twitter.com/#!/expobrain
As other suggested, model.rowsInserted(parent, start, end).emit() is the
signal you need. To show you the way one could do this, I shortly
changed the Simple Tree View example of PySide (quick and dirty, I know,
but it shows enough)... You may add new items filling in the LineEdits
and then clicking the button. The only magic line is the last one of the
method TreeModel.addData().
Hope this helps (and for the future, it would be probably a good idea to
change the treeview example of PySide to make it ready for use with
dynamic models...).
Code:
# -*- coding: utf-8 -*-
'''
@author: Aaron Richiger
@contact: a.r...@bluewin.ch
@date: 08.02.2011
'''
from PySide.QtGui import *
from PySide.QtCore import *
import sys
class TreeItem(object):
def __init__(self, data, parent=None):
self.parentItem = parent
self.itemData = data
self.childItems = []
def appendChild(self, item):
self.childItems.append(item)
def child(self, row):
return self.childItems[row]
def childCount(self):
return len(self.childItems)
def columnCount(self):
return len(self.itemData)
def data(self, column):
try:
return self.itemData[column]
except IndexError:
return None
def parent(self):
return self.parentItem
def row(self):
if self.parentItem:
return self.parentItem.childItems.index(self)
return 0
class TreeModel(QAbstractItemModel):
def __init__(self, rootItem, parent=None):
super(TreeModel, self).__init__(parent)
self.rootItem = rootItem
def columnCount(self, parent = QModelIndex()):
if parent.isValid():
return parent.internalPointer().columnCount()
else:
return self.rootItem.columnCount()
def data(self, index, role):
if not index.isValid():
return None
if role != Qt.DisplayRole:
return None
item = index.internalPointer()
return item.data(index.column())
def flags(self, index):
if not index.isValid():
return Qt.NoItemFlags
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.rootItem.data(section)
return None
def index(self, row, column, parent = QModelIndex()):
if not self.hasIndex(row, column, parent):
return QModelIndex()
if not parent.isValid():
parentItem = self.rootItem
else:
parentItem = parent.internalPointer()
childItem = parentItem.child(row)
if childItem:
return self.createIndex(row, column, childItem)
else:
return QModelIndex()
def parent(self, index):
if not index.isValid():
return QModelIndex()
childItem = index.internalPointer()
parentItem = childItem.parent()
if parentItem == self.rootItem:
return QModelIndex()
return self.createIndex(parentItem.row(), 0, parentItem)
def rowCount(self, parent = QModelIndex()):
if parent.column() > 0:
return 0
if not parent.isValid():
parentItem = self.rootItem
else:
parentItem = parent.internalPointer()
return parentItem.childCount()
def addData(self, data, parent):
lines = data.split('\n')
parents = [parent]
indentations = [0]
number = 0
while number < len(lines):
position = 0
while position < len(lines[number]):
if lines[number][position] != ' ':
break
position += 1
lineData = lines[number][position:].strip()
if lineData:
# Read the column data from the rest of the line.
columnData = [s.strip() for s in lineData.split(';') if s]
if position > indentations[-1]:
# The last child of the current parent is now the new
# parent unless the current parent has no children.
if parents[-1].childCount() > 0:
parents.append(parents[-1].child(parents[-1].childCount() - 1))
indentations.append(position)
else:
while position < indentations[-1] and len(parents) > 0:
parents.pop()
indentations.pop()
# Append a new item to the current parent's list of
children.
parents[-1].appendChild(TreeItem(columnData, parents[-1]))
number += 1
self.rowsInserted.emit(self, self.rowCount() - 1,
self.rowCount() - 1)
if __name__ == '__main__':
app = QApplication(sys.argv)
widget = QWidget()
data = '''
Getting Started; How to familiarize yourself with Qt Designer
Launching Designer; Running the Qt Designer application
The User Interface; How to interact with Qt Designer
Designing a Component; Creating a GUI for your application
Creating a Dialog; How to create a dialog
Composing the Dialog; Putting widgets into the dialog example'''
rootItem = TreeItem(("Title", "Summary"))
model = TreeModel(rootItem)
model.addData(data, rootItem)
treeView = QTreeView(widget)
treeView.setModel(model)
lbTitle = QLabel('Title:', widget)
lbSummary = QLabel('Summary:', widget)
leTitle = QLineEdit(widget)
leSummary = QLineEdit(widget)
pbAddItem = QPushButton('Add this item', widget)
pbAddItem.clicked.connect(lambda: model.addData(leTitle.text() +
';' + leSummary.text(), model.rootItem))
grid = QGridLayout(widget)
grid.addWidget(treeView, 0, 0, 1, 2)
grid.addWidget(lbTitle, 1, 0, 1, 1)
grid.addWidget(lbSummary, 2, 0, 1, 1)
grid.addWidget(leTitle, 1, 1, 1, 1)
grid.addWidget(leSummary, 2, 1, 1, 1)
grid.addWidget(pbAddItem, 3, 1, 1, 1)
widget.show()
sys.exit(app.exec_())
Am 07.02.2012 13:47, schrieb Daniele Esposti:
> Hi Jun,
>
> update(QModelIndex) is a slot in QAbstractItemView (and which is the
> superclass of QTreeView); QAbstractItemModel doesn't have any update()
> method at all.
>
> What you can do (as far as I know about your code) is to emit a
> rowsAboutToBeInserted() before adding the data to your model and
> rowsInserted() after the data is added to your model. The view
> connected to your model will show your data automatically.
>
> On 7 February 2012 11:23, Jun Koi<junko...@gmail.com> wrote:
>> On Tue, Feb 7, 2012 at 7:08 PM, Daniele Esposti<ex...@expobrain.net> wrote:
>>> Hi Jun,
>>>
>>> the slot QAbstractItemView.update() wants a QModelIndex as a parameter
>>> http://www.pyside.org/docs/pyside/PySide/QtGui/QAbstractItemView.html#PySide.QtGui.PySide.QtGui.QAbstractItemView.update
>>>
>>> This means you need to pass the QModelIndex of the data you added to the model.
>> this means i need to call update() method of the model, right?
>>
>> how about the update() method of the TreeView widget? do i need to call it?
>>
>> thanks a lot,
>> Jun
>
>
_______________________________________________
this is awesome, thanks!!!
however, inserting new data is not the only thing i want to do. i also
want to modify some data of the model.
so what i really want is to ask the view to redraw a particular row
after i update the data of that row.
what is the best way to do that?
(for the record, i also use the model similar to what Aaron posted
above, as i also reused the SimpleTreeModel demo)
thanks again for all of your generous help. this community is amazing!
best,
have a look at all this wonderful signals :-D
http://www.pyside.org/docs/pyside/PySide/QtCore/QAbstractItemModel.html#signals
--
Daniele Esposti
My Blog http://www.expobrain.net
LinkedIn http://www.linkedin.com/in/danieleesposti
Twitter http://www.twitter.com/#!/expobrain
with this awesome demo, i can add a new data to the view with
TreeModel.addData(), like in the code you wrote above.
for example, i created a new tree node like this:
....
NewData
now, if i want to create a subnode for NewData, so it will be like this:
....
NewData
|____ MyChildData
i guess to do that, again i need to use TreeModel.addData(), but the
difference is that this time i need the model of NewData, so it will
create a subnode, but not the model of the TreeView (the root) like
when i created NewData
so the question is: how can i get the model of the NewData i created above?
(i suppose that i need to modify the addData() function, so it returns
the model of the newly created node, but i have no idea how to do
that)
to be consistent the addData() method should accept your data and the
parent QModelIndex where the data will be added, so the method
signature will be something like addData(data, parent=QModelIndex()).
By convention an invalid QModelIndex represent the root item of a tree
view.
The return value of addData should be the QModelIndex instance which
points to your data, so you can call again the addData() method
passing the new data as the parent.
Talking about code:
...
index1 = model.addData(data1) # Add data to the root item and return
the QModelIndex instance
index2 = model.addData(data2, parent=index1) # Add data as child of
the previously added data
Read carefully the docs about the QModelIndex here
http://www.pyside.org/docs/pyside/PySide/QtCore/QModelIndex.html
because it's very important when working with models and views. And
QAbstarctItemModel too
http://www.pyside.org/docs/pyside/PySide/QtCore/QAbstractItemModel.html
.
--
Daniele Esposti
My Blog http://www.expobrain.net
LinkedIn http://www.linkedin.com/in/danieleesposti
Twitter http://www.twitter.com/#!/expobrain