QTableView:动态更新模型和 select 正确的行

QTableView: update model on the fly and select correct line

我有一个 QTableView,其中填充了来自 QSqlTableModel.Each 行的数据,QTableView 表示来自网站的 "article"。文章可以阅读或未读,就像电子邮件一样。状态 read/unread 存储在数据库中,在字段 "new".

如果文章未读,则在视图中以特定方式显示。如果它被阅读,它会以另一种方式显示,就像任何电子邮件管理器中的电子邮件一样。

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

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) 时,我 select 是同一行,但它可以是完全不同的项目。

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

你有什么想法吗?

我做到了!从这个 post (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()