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()
我有一个 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()