如何在数据库中使用 QSortFilterProxyModel?
Posted
技术标签:
【中文标题】如何在数据库中使用 QSortFilterProxyModel?【英文标题】:How use QSortFilterProxyModel in database? 【发布时间】:2018-08-10 13:03:44 【问题描述】:我有一个 QTableWidget,其中包含来自数据库的数据,我想实时搜索它的内容(当我输入字母时,他会显示结果)?欢迎任何帮助。非常感谢。
这是我的代码:
class Filter:
def __init__(self):
object.__init__(self)
self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
self.db.setDatabaseName("baza.db")
self.filter_model= QSortFilterProxyModel()
def sqlPodaci(self,okvir):
okvir.setObjectName("Okvir aplikacije")
okvir.resize(700,320)
line_edit = QLineEdit(okvir)
line_edit.setGeometry(20, 20, 205, 23)
self.tableWidget = QtWidgets.QTableWidget(okvir)
self.tableWidget.setGeometry(QtCore.QRect(20, 50, 620, 201))
self.tableWidget.setAlternatingRowColors(True)
self.tableWidget.setRowCount(3)
self.tableWidget.horizontalHeader().setVisible(True)
self.tableWidget.verticalHeader().setVisible(False)
###
self.filter_model.setFilterKeyColumn(1)
line_edit.textChanged.connect(self.filter_model.setFilterRegExp)
####
self.Ucitavanje_podataka()
这是从数据库中读取数据的代码:
def Ucitavanje_podataka(self):
status = self.db.open()
if status == False:
QtWidgets.QMessageBox.warning(self, "Error", self.db.lastError().text(), QtWidgets.QMessageBox.Discard)
else:
self.tableWidget.setColumnCount(6)
self.tableWidget.setHorizontalHeaderLabels(['Id','Ime','Prezime','Godine','Adresa','Plata'])
row = 0
sql = " SELECT * FROM Zaposleni"
query = QtSql.QSqlQuery(sql)
while query.next():
self.tableWidget.insertRow(row)
ID=QtWidgets.QTableWidgetItem(str(query.value(0)))
Ime = QtWidgets.QTableWidgetItem(str(query.value(1)))
Prezime = QtWidgets.QTableWidgetItem(str(query.value(2)))
Godine = QtWidgets.QTableWidgetItem(str(query.value(3)))
Adresa = QtWidgets.QTableWidgetItem(str(query.value(4)))
Plata = QtWidgets.QTableWidgetItem(str(query.value(5)))
self.tableWidget.setItem(row,0,ID)
self.tableWidget.setItem(row, 1, Ime)
self.tableWidget.setItem(row, 2, Prezime)
self.tableWidget.setItem(row, 3, Godine)
self.tableWidget.setItem(row, 4, Adresa)
self.tableWidget.setItem(row, 5, Plata)
row=row+1
【问题讨论】:
如果你想使用QSortFilterProxyModel你必须使用QTableView,QTableWidget为了方便它的使用有一个只读的模型所以它不能用于QSortFilterProxyModel。如果您提供有关如何进行过滤的更多详细信息,我可以为您提供解决方案。 谢谢。当我用数据填充表格时,我想按列过滤结果。例如,在第 2 列中,a 有三个名称 eyllanesc 、elena 和 Maximus,当我在 line_edit 中输入“M”时,如果我输入“E”,我只会看到 Maximus,我会得到 eyllanesc 、elena ... 如果单词是:“AB”、“BA”、“CA”、“CB”和A型,应该显示什么? 你希望它只被单词的开头过滤 是的,前提是我按准确的顺序输入字母。示例:M - Maximus、Ma - Maksimus、Mx - 不会显示命中 【参考方案1】:QTableWidget
有一个无法替换的预设模型,因此使用QSortFilterProxyModel
是不可能的,因此您应该使用QTableView
,解决主要问题的一个可能解决方案是仅使用QSqlQueryModel
和使用LIKE
命令制作过滤器。
from PyQt5 import QtWidgets, QtSql
def createConnection():
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("baza.db")
if not db.open():
QtWidgets.QMessageBox.critical(None, "Cannot open database",
"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.", QtWidgets.QMessageBox.Cancel)
return False
return True
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
lineEdit = QtWidgets.QLineEdit()
tableView = QtWidgets.QTableView()
lay.addWidget(lineEdit)
lay.addWidget(tableView)
lineEdit.textChanged.connect(self.onTextChanged)
self.model = QtSql.QSqlQueryModel()
tableView.setModel(self.model)
self.onTextChanged("")
def onTextChanged(self, text):
query = QtSql.QSqlQuery()
query.prepare("SELECT * FROM Zaposleni WHERE Ime LIKE ?")
query.addBindValue("%".format(text))
query.exec_()
self.model.setQuery(query)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
if not createConnection():
sys.exit(-1)
w = Widget()
w.show()
sys.exit(app.exec_())
在前面的示例中,我们希望单词以 QLineEdit 的文本开头,如果要查找它是否包含该单词,则必须将其替换为:
query.addBindValue("%%".format(text))
如果你还想使用QSortFilterProxyModel
,可以看下面的例子:
from PyQt5 import QtCore, QtWidgets, QtSql
def createConnection():
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("baza.db")
if not db.open():
QtWidgets.QMessageBox.critical(None, "Cannot open database",
"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.", QtWidgets.QMessageBox.Cancel)
return False
return True
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
lineEdit = QtWidgets.QLineEdit()
tableView = QtWidgets.QTableView()
lay.addWidget(lineEdit)
lay.addWidget(tableView)
lineEdit.textChanged.connect(self.onTextChanged)
self.model = QtSql.QSqlQueryModel()
self.model.setQuery("SELECT * FROM Zaposleni")
self.proxy = QtCore.QSortFilterProxyModel()
self.proxy.setSourceModel(self.model)
self.proxy.setFilterKeyColumn(1)
tableView.setModel(self.proxy)
def onTextChanged(self, text):
regex = "^".format(text)
self.proxy.setFilterRegExp(QtCore.QRegExp(regex, QtCore.Qt.CaseInsensitive))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
if not createConnection():
sys.exit(-1)
w = Widget()
w.show()
sys.exit(app.exec_())
在前面的示例中,我们希望单词以 QLineEdit 的文本开头,如果要查找它是否包含该单词,则必须将其替换为:
regex = "[]".format(text) if text else ""
【讨论】:
在这个脚本中,我想在三个不同的列中过滤结果。 self.proxy.setFilterKeyColumn(1) 这个代码我搜索一列(在我的情况下是第二列),但我需要搜索三列。对不起,谢谢 你能帮帮我吗? @Maximus 如果您知道 SQL,请使用第一个选项,因为它只是建立允许选择的查询。在第二种情况下,它涉及创建一个继承自 QSortFilterProxyModel 的类并覆盖几个方法并创建其他方法。尝试一下,如果你不能解决它,那么创建一个新问题来展示你的解决方案尝试,当然社区中的某个人可以帮助你。以上是关于如何在数据库中使用 QSortFilterProxyModel?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 中使用 SMO 使用 FILE STREAM 备份和恢复数据库
如何在 Rails 3 的 Postgres 数据库中使用枚举? [关闭]