QTableView:动态更新模型并选择正确的行

时间:2015-02-28 09:43:21

标签: python model-view-controller pyqt qtableview

我有一个QTableView,填充了来自QSqlTableModel的数据.QTableView的每一行代表一个来自网站的“文章”。这些文章可以是读取或未读取的,就像电子邮件一样。状态读取/未读取存储在数据库中的“新”字段下。

如果文章未读,则会在视图中以某种方式显示。如果它被读取,它将以另一种方式显示,如任何电子邮件管理器中的电子邮件。

当用户点击文章未读时,该文章被标记为已读,这意味着存储数据的模型已更新:

def markOneRead(self, element):

    """Slot to mark an article read"""

    table = self.liste_tables_in_tabs[self.onglets.currentIndex()]
    model = self.liste_models_in_tabs[self.onglets.currentIndex()]
    proxy = self.liste_proxies_in_tabs[self.onglets.currentIndex()]
    new = table.model().index(element.row(), 12).data()

    if new == 0:
        return
    else:

        # Save the current line
        line = table.selectionModel().currentIndex().row()

        # Update the model
        table.model().setData(table.model().index(line, 12), 0)

        try:
            # Try to update the model
            model.setQuery(self.query)
            proxy.setSourceModel(model)
            table.setModel(proxy)
        except AttributeError:
            pass

        # Once the model is updated, reselect the line saved
        table.selectRow(line)

虽然这种方法大部分时间都有效,但我只将当前行号保存在变量“line”中。因此,如果模型已经改变(从程序的任何其他进程),当我执行table.selectRow(line)时,我选择相同的行yes,但它可以是完全不同的项。

因此,在更新模型之前,我需要一种更精确的方式来存储点击的项目。

你有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我设法做到了!从这篇文章(C ++):How to refresh a QSqlTableModel while preserving the selection?

python中生成的代码是:

def markOneRead(self, element):

    """Slot to mark an article read"""

    table = self.liste_tables_in_tabs[self.onglets.currentIndex()]
    new = table.model().index(element.row(), 12).data()

    if new == 0:
        return
    else:

        # Save the current line
        line = table.selectionModel().currentIndex().row()
        selected_id = table.selectionModel().selection().indexes()[0].data()

        # Change the data in the model
        table.model().setData(table.model().index(line, 12), 0)

        # Update the view after the model is updated
        self.updateView(selected_id)


def updateView(self, current_item_id=None):

    """Method to update the view after a model change.
    If an item was selected, the item is re-selected"""

    model = self.liste_models_in_tabs[self.onglets.currentIndex()]
    table = self.liste_tables_in_tabs[self.onglets.currentIndex()]
    proxy = self.liste_proxies_in_tabs[self.onglets.currentIndex()]

    if current_item_id is not None:
        selected_id = current_item_id
    else:
        try:
            selected_id = table.selectionModel().selection().indexes()[0].data()
        except IndexError:
            selected_id = None

    try:
        # Try to update the model
        model.setQuery(self.query)
        proxy.setSourceModel(model)
        table.setModel(proxy)
    except AttributeError:
        pass

    if selected_id is not None:
        for index in range(1, model.rowCount() + 1):
            table.selectRow(index)
            if table.selectionModel().selection().indexes()[0].data() == selected_id:
                # If the previously selected item is found, leave
                return
        # If we are still here, the old item wasn't found, so deselect all
        table.clearSelection()