如果没有您提供 MCVE,很难分析问题出在哪里,因此我的回复在不考虑您当前代码的情况下实现了您的要求,因为它必须满足以下要求:
- 您必须有 2 个表:相关的对象和历史。
- 表objects保存了过滤历史的名字,和你使用的objectName类似,但是一般2个widget可以访问相同的历史,如果连接建立相同的名字
- 在历史表中,保存了与对象表的 id 相关联的单词信息。
在我的示例中,我使用以下说明来创建它们:
CREATE TABLE IF NOT EXISTS objects (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE);
CREATE TABLE IF NOT EXISTS history (id INTEGER PRIMARY KEY AUTOINCREMENT, id_object INTEGER REFERENCES objects (id), word TEXT NOT NULL, UNIQUE (id_object, word));
为了测试它,我创建了一个数据,如果你已经有数据,那么你必须消除if test:
里面的所有东西。
最后,为了更好地理解我的解决方案,我展示了一个根据选择而变化的 QTableView。
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
def createConnection():
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db_path = 'test.db'
db.setDatabaseName(db_path)
if not db.open():
QMessageBox.critical(None, qApp.tr("Cannot open database"),
qApp.tr("Unable to establish a database connection.\n"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information "
"how to build it.\n\n"
"Click Cancel to exit."),
QMessageBox.Cancel)
return False
test = True
if test:
query = QtSql.QSqlQuery()
if not query.exec_('CREATE TABLE IF NOT EXISTS objects (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE);'):
return False
if not query.exec_('CREATE TABLE IF NOT EXISTS history (id INTEGER PRIMARY KEY AUTOINCREMENT, id_object INTEGER REFERENCES objects (id), word TEXT NOT NULL, UNIQUE (id_object, word));'):
return False
for i in range(3):
query.prepare('INSERT INTO objects (name) VALUES (?)')
query.addBindValue("obj{}".format(i))
if not query.exec_():
print(query.lastError().text())
import requests
import random
word_site = "http://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-type=text/plain"
response = requests.get(word_site)
WORDS = response.content.decode().splitlines()
print(WORDS)
for i in range(3):
for text in random.sample(WORDS, 50):
query.prepare('INSERT INTO history (id_object, word) VALUES (?, ?)')
query.addBindValue(i+1)
query.addBindValue(text)
if not query.exec_():
print(query.lastError().text())
return True
class Completer(QtWidgets.QCompleter):
def __init__(self, parent=None):
super(Completer, self).__init__(parent)
self._last_words = []
def splitPath(self, path):
if path[-1] != ' ':
words = path.split()
self._last_words = words[:-1] if len(words) > 1 else []
return [words[-1]]
else:
QtCore.QTimer.singleShot(0, self.popup().hide)
return []
def pathFromIndex(self, index):
val = super(Completer, self).pathFromIndex(index)
return ' '.join(self._last_words + [val])
class HistoryManager(QtCore.QObject):
nameChanged = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(HistoryManager, self).__init__(parent)
model = QtSql.QSqlRelationalTableModel(self)
model.setTable("history")
model.setRelation(1, QtSql.QSqlRelation("objects", "id", "name"))
model.select()
self._proxy = QtCore.QSortFilterProxyModel(self)
self._proxy.setSourceModel(model)
self._proxy.setFilterKeyColumn(1)
# proxy.setFilterFixedString("obj1")
self._widgets = {}
self._completer = Completer(self)
self._completer.setModel(self._proxy)
self._completer.setCompletionColumn(2)
def register_widget(self, widget, objectname):
# TODO
if callable(getattr(widget, "setCompleter")):
widget.installEventFilter(self)
self._widgets[widget] = objectname
return True
return False
def eventFilter(self, obj, event):
if obj in self._widgets:
if event.type() == QtCore.QEvent.FocusIn:
name = self._widgets[obj]
self._proxy.setFilterFixedString(name)
obj.setCompleter(self._completer)
self.nameChanged.emit(name)
elif event.type() == QtCore.QEvent.FocusOut:
obj.setCompleter(None)
self._proxy.setFilterFixedString("")
self.nameChanged.emit("")
return super(HistoryManager, self).eventFilter(obj, event)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._manager = HistoryManager()
model = QtSql.QSqlRelationalTableModel(self)
model.setTable("history")
model.setRelation(1, QtSql.QSqlRelation("objects", "id", "name"))
model.select()
self._proxy = QtCore.QSortFilterProxyModel(self)
self._proxy.setSourceModel(model)
self._proxy.setFilterKeyColumn(1)
tv = QtWidgets.QTableView()
tv.setModel(self._proxy)
vlay = QtWidgets.QVBoxLayout()
for i in range(3):
le = QtWidgets.QLineEdit()
vlay.addWidget(le)
self._manager.register_widget(le, "obj{}".format(i))
vlay.addStretch()
lay = QtWidgets.QHBoxLayout(self)
lay.addWidget(tv, stretch=1)
lay.addLayout(vlay)
self._manager.nameChanged.connect(self._proxy.setFilterFixedString)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
if not createConnection():
sys.exit(-1)
manager = HistoryManager()
w = Widget()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())