Pregunta

What would be the most efficient and technically (Python/PyQt4) correct way of making arbitrary muti-selection in a QTableView which has a model encompassing hierarchy of QStandardItems (a graph plot data) with custom isSelected data attribute added per item.

In details: Along with the table I have a matplotlib plot which outputs ranges (isSelected attribute comes directly from these ranges) that correspond to my QTableView data and I want to add a bit of interaction between these two gui elements.

i.e matplotlib plot selection is reflected in QTableView and vice versa (which I'm getting by hooking selection change to reading corresponding indexes and feeding them back to graph plot).

Hopefully this explanation makes sense. Thanks.

¿Fue útil?

Solución

As you said, right now you have your QTableView.selectionChanged() feeding the selections back to your matplot. The most efficient approach would be to have your matplot emit a signal for its selection, with the relevant items.

A table view already stores its selections in a QItemSelectionModel, so as far as I can see it would be redundant and unnecessary to store your own isSelected attribute on the items. Your matplot view should know the items it is using and should be able to notify the table view of its selection changes.

Your matplot view can have a signal that you emit, such as selectionChanged(items), and can continue having no knowledge of the table view.

Your table view, as it already knows about the matplot view, can connect to its selectionChanged(items) to the matplot and listen for selection changes. Even if your table is also emitting a signal and has no knowledge of the matplot, you can make the connection in whatever parent class does know of them both.

This is why I think the attribute isn't needed: The only way to make use of that attribute is to scan the entire model, checking each item. Thats not really efficient. The selection should happen in reaction to the signal being emitted.

myMatPlotView.selectionchanged.connect(myTableView.matplotSelected)

And in your matPlotSelected() slot, you can use the selection model to set the items selection:

tableView

def matPlotSelected(self, qStandardItems):

    selModel = self.selectionModel()
    model = self.model()

    for item in qStandardItems:
        idx = model.indexFromItem(item)
        selModel.select(idx, selModel.Select)

Update

In the comments you provided a code snippet, which really helped to isolate what you want to achieve.

Your example

def __init__(self):
    super(myDialog, self).__init__()
    self.t = QtGui.QTreeView()
    self.m = QtGui.QStandardItemModel()
    self.t.setModel(self.m)
    layout = QtGui.QVBoxLayout()
    layout.addWidget(self.t)
    self.setLayout(layout)
    self.l = [
        ['one', False], ['two', True], 
        ['three', False], ['four', True], 
        ['five', False]]
    self.populate()

def populate(self):
    self.m.clear()
    root = self.m.invisibleRootItem()
    for item in self.l:
        e = QtGui.QStandardItem()
        e.setText(item[0])
        root.appendRow(e)

If this is your actual situation, then what I suggested above fits in like this:

def populate(self):
    self.m.clear()
    root = self.m.invisibleRootItem()
    selModel = self.t.selectionModel()
    for item in self.l:
        e = QtGui.QStandardItem()
        e.setText(item[0])
        root.appendRow(e)

        if item[1]:
            idx = self.m.indexFromItem(e)
            selModel.select(idx, selModel.Select)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top