QCompleter 的多列模型
Multicolumn Model for QCompleter
我正在尝试使用 QCompleter 在 QComboBox 上自动完成。下面的两张图片显示了填充的组合框(左)和第 1 列(右)上的 QCompleter。
只要 QComboBox 和 QCompleter 的模型列相同,此示例就可以正常工作。但是对于此示例,QCompleter 使用第 0 列(city/state)会更直观,但仍然让 QComboBox 使用第 1 列(机场代码)。这是代码:
from PyQt5.QtCore import pyqtSlot, QObject
from PyQt5.QtWidgets import (QApplication, QMainWindow, QComboBox,
QCompleter, QTableView, QLabel)
from PyQt5.QtSql import (QSqlQuery, QSqlQueryModel, QSqlDatabase)
import sys
import sqlite3
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__()
self.setGeometry(300, 300, 400, 300)
fid = open('example.db', 'w')
fid.close()
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName('example.db')
db.open()
query = QSqlQuery(db)
query.exec_('CREATE TABLE "airports" ("city" TEXT, "code" TEXT)')
airports = [('Aberdeen, SD','ABR'), ('Abilene, TX','ABI'),
('Adak Island, AK','ADK'), ('Akiachak, AK','KKI'),
('Akiak, AK','AKI'), ('Akron/Canton, OH','CAK'),
('Akuton, AK','KQA'), ('Alakanuk, AK','AUK'),
('Alamogordo, NM','ALM'), ('Alamosa, CO','ALS'),
('Albany, NY','ALB'), ('Albuquerque, NM','ABQ')]
for item in airports:
sql = 'INSERT INTO airports(city, code) VALUES(?, ?)'
query.prepare(sql)
query.addBindValue(item[0])
query.addBindValue(item[1])
query.exec_()
query.exec_('SELECT * FROM airports')
model = QSqlQueryModel()
model.setQuery(query)
self.cb = QComboBox(parent = self)
self.cb.setModel(model)
self.cb.setModelColumn(1)
self.cb.setView(QTableView(self.cb))
self.cb.setGeometry(50,50, 250, 50)
self.cb.currentIndexChanged.connect(self.indexer)
self.label = QLabel(parent = self)
self.label.setGeometry(20,200, 250, 50)
self.cb.view().setMinimumWidth(500)
self.cb.setEditable(True)
self.completer = QCompleter()
self.completer.setCaseSensitivity(False)
self.cb.setCompleter(self.completer)
self.completer.setModel(model)
self.completer.setCompletionColumn(1)
self.completer.setPopup(QTableView())
self.completer.popup().setMinimumWidth(500)
self.completer.popup().setMinimumHeight(500)
self.completer.activated.connect(self.activatedHandler)
@pyqtSlot(QObject)
def activatedHandler(self, arg):
pass
def indexer(self, idx):
self.label.setText('%d' % idx)
app = QApplication(sys.argv)
main = MainWindow(None)
main.show()
sys.exit(app.exec_())
如果我将 QCompleter 更改为使用零列,即
self.completer.setCompletionColumn(0)
然后正确的组合框行是 select 在完成者完成它的事情之后,但显示的文本是 city/state 而不是机场代码(左下方和中间)。此外,如果用户按下 enter,则组合框会尝试将文本用于 select 行,但找不到它并将组合框行重置为 -1。 (右下)。有什么方法可以改变这种行为,以便在组合框中显示所需的文本(机场代码)?
默认情况下,QCompleter 使用模型 completionColumn 的文本进行搜索和自动完成,因此存在冲突,一个可能的解决方案是重写 pathFromIndex 方法和 return 适当的文本
class CustomCompleter(QCompleter):
def pathFromIndex(self, index):
sibling_index = index.sibling(index.row(), 1)
return super().pathFromIndex(sibling_index)
self.completer = CustomCompleter()
第二期无法复现,等待OP反馈
我正在尝试使用 QCompleter 在 QComboBox 上自动完成。下面的两张图片显示了填充的组合框(左)和第 1 列(右)上的 QCompleter。
只要 QComboBox 和 QCompleter 的模型列相同,此示例就可以正常工作。但是对于此示例,QCompleter 使用第 0 列(city/state)会更直观,但仍然让 QComboBox 使用第 1 列(机场代码)。这是代码:
from PyQt5.QtCore import pyqtSlot, QObject
from PyQt5.QtWidgets import (QApplication, QMainWindow, QComboBox,
QCompleter, QTableView, QLabel)
from PyQt5.QtSql import (QSqlQuery, QSqlQueryModel, QSqlDatabase)
import sys
import sqlite3
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__()
self.setGeometry(300, 300, 400, 300)
fid = open('example.db', 'w')
fid.close()
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName('example.db')
db.open()
query = QSqlQuery(db)
query.exec_('CREATE TABLE "airports" ("city" TEXT, "code" TEXT)')
airports = [('Aberdeen, SD','ABR'), ('Abilene, TX','ABI'),
('Adak Island, AK','ADK'), ('Akiachak, AK','KKI'),
('Akiak, AK','AKI'), ('Akron/Canton, OH','CAK'),
('Akuton, AK','KQA'), ('Alakanuk, AK','AUK'),
('Alamogordo, NM','ALM'), ('Alamosa, CO','ALS'),
('Albany, NY','ALB'), ('Albuquerque, NM','ABQ')]
for item in airports:
sql = 'INSERT INTO airports(city, code) VALUES(?, ?)'
query.prepare(sql)
query.addBindValue(item[0])
query.addBindValue(item[1])
query.exec_()
query.exec_('SELECT * FROM airports')
model = QSqlQueryModel()
model.setQuery(query)
self.cb = QComboBox(parent = self)
self.cb.setModel(model)
self.cb.setModelColumn(1)
self.cb.setView(QTableView(self.cb))
self.cb.setGeometry(50,50, 250, 50)
self.cb.currentIndexChanged.connect(self.indexer)
self.label = QLabel(parent = self)
self.label.setGeometry(20,200, 250, 50)
self.cb.view().setMinimumWidth(500)
self.cb.setEditable(True)
self.completer = QCompleter()
self.completer.setCaseSensitivity(False)
self.cb.setCompleter(self.completer)
self.completer.setModel(model)
self.completer.setCompletionColumn(1)
self.completer.setPopup(QTableView())
self.completer.popup().setMinimumWidth(500)
self.completer.popup().setMinimumHeight(500)
self.completer.activated.connect(self.activatedHandler)
@pyqtSlot(QObject)
def activatedHandler(self, arg):
pass
def indexer(self, idx):
self.label.setText('%d' % idx)
app = QApplication(sys.argv)
main = MainWindow(None)
main.show()
sys.exit(app.exec_())
如果我将 QCompleter 更改为使用零列,即
self.completer.setCompletionColumn(0)
然后正确的组合框行是 select 在完成者完成它的事情之后,但显示的文本是 city/state 而不是机场代码(左下方和中间)。此外,如果用户按下 enter,则组合框会尝试将文本用于 select 行,但找不到它并将组合框行重置为 -1。 (右下)。有什么方法可以改变这种行为,以便在组合框中显示所需的文本(机场代码)?
默认情况下,QCompleter 使用模型 completionColumn 的文本进行搜索和自动完成,因此存在冲突,一个可能的解决方案是重写 pathFromIndex 方法和 return 适当的文本
class CustomCompleter(QCompleter):
def pathFromIndex(self, index):
sibling_index = index.sibling(index.row(), 1)
return super().pathFromIndex(sibling_index)
self.completer = CustomCompleter()
第二期无法复现,等待OP反馈