【问题标题】:QTableView: update model on the fly and select correct lineQTableView:即时更新模型并选择正确的行
【发布时间】:2015-05-01 01:31:57
【问题描述】:

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

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

你有什么想法吗?

【问题讨论】:

  • 我不太明白你的问题。为什么要以编程方式选择行?如果用户在表格中单击,它将选择该项目/行。如果您担心在表格顶部添加新数据时选择会发生变化,那么您可能希望在添加数据时更新您的选择模型。
  • 我猜您担心在顶部添加新数据会降低所有内容,但选择仍然存在。您可以尝试在底部添加数据并将 QTableView 的布局方向更改为 BottomToTop。我不知道这是否会奏效。另一个选项是存储 rowCount 以及 line 变量并在 table.selectRow(line) 之前检查不同的 rowCount
  • 是的,我认为您在第二条评论中得到了它。除了QTableView是按日期排序的,其他进程添加的item不一定会添加在顶部或底部,所以我需要准确检索选择的item。

标签: python model-view-controller pyqt qtableview


【解决方案1】:

我成功了!来自这篇文章(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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-17
    相关资源
    最近更新 更多