如何在 PyQt5 中过滤 SQLite3 table
How filter SQLite3 table in PyQt5
我正在尝试创建一个搜索栏来过滤 table 中的数据,但看起来模型没有链接到 lineEdit table 有效,但我无法过滤使用它的数据库数据(它适用于列表)有什么问题?
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
mainLayout = QVBoxLayout()
conn = sqlite3.connect("banco_cadastro.db.db")
cursor = conn.cursor()
list = (cursor.fetchall())
model = QStandardItemModel(len(list), 5)
model.setHorizontalHeaderLabels(['Clients'])
for row, company in enumerate(list):
item = QStandardItem(company)
model.setItem(row, 0, item)
filter_proxy_model = QSortFilterProxyModel()
filter_proxy_model.setSourceModel(model)
filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
filter_proxy_model.setFilterKeyColumn(0)
MainWindow.setObjectName("MainWindow")
MainWindow.resize(779, 693)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.textChanged.connect(filter_proxy_model.setFilterRegExp)
mainLayout.addWidget(self.lineEdit)
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setObjectName("tableWidget")
MainWindow.setCentralWidget(self.centralwidget)
connection = sqlite3.connect('banco_cadastro.db')
query = "SELECT * FROM cadastro"
result = connection.execute(query)
list = (cursor.fetchall())
for row_number, row_data in enumerate(result):
self.tableWidget.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tableWidget.setItem(row_number, column_number, QtWidgets.QTableWidgetItem(str(data)))
connection.close()
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
免责声明:在此 post 中,我将只关注背景 objective 而不是 OP 的错误(例如将 QStandardItemModel 与 QTableWidget 结合使用,或无用的尝试使用不连接任何东西的 QSortFilterProxyModel)。
我将借此机会展示如何使用 PyQt5(它也适用于 PySide2)过滤 sqlite 表的不同方法(相同的概念可以应用于其他数据库)。
- QTableWidget + sqlite3 模块
一个可能的解决方案是遍历行并验证它是否满足所需条件,如果满足则该行将可见,否则该行将被隐藏。
import sqlite3
from PyQt5 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableWidget()
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.connection = sqlite3.connect("database.db")
self.populate_table("SELECT * FROM foo_table")
self.edit.textChanged.connect(self.filter_table)
def populate_table(self, query, values=None):
cursor = self.connection.cursor()
if values is None:
cursor.execute(query)
else:
cursor.execute(query, values)
name_of_columns = [e[0] for e in cursor.description]
self.table.setColumnCount(len(name_of_columns))
self.table.setRowCount(0)
self.table.setHorizontalHeaderLabels(name_of_columns)
self.combo.clear()
self.combo.addItems(name_of_columns)
for i, row_data in enumerate(cursor.fetchall()):
self.table.insertRow(self.table.rowCount())
for j, value in enumerate(row_data):
item = QtWidgets.QTableWidgetItem()
item.setData(QtCore.Qt.DisplayRole, value)
self.table.setItem(i, j, item)
def filter_table(self, text):
if text:
filter_column = self.combo.currentIndex()
for i in range(self.table.rowCount()):
item = self.table.item(i, filter_column)
if self.filter_row(item, text):
self.table.showRow(i)
else:
self.table.hideRow(i)
else:
for i in range(self.table.rowCount()):
self.table.showRow(i)
def filter_row(self, item, text):
return text in item.text()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
另一种可能的解决方案是删除所有数据并使用过滤器发出新请求。
import sqlite3
from PyQt5 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableWidget()
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.connection = sqlite3.connect("database.db")
self.populate_table("SELECT * FROM foo_table")
self.edit.textChanged.connect(self.filter_table)
def populate_table(self, query, values=None):
cursor = self.connection.cursor()
if values is None:
cursor.execute(query)
else:
cursor.execute(query, values)
name_of_columns = [e[0] for e in cursor.description]
self.table.setColumnCount(len(name_of_columns))
self.table.setRowCount(0)
self.table.setHorizontalHeaderLabels(name_of_columns)
self.combo.clear()
self.combo.addItems(name_of_columns)
for i, row_data in enumerate(cursor.fetchall()):
self.table.insertRow(self.table.rowCount())
for j, value in enumerate(row_data):
item = QtWidgets.QTableWidgetItem()
item.setData(QtCore.Qt.DisplayRole, value)
self.table.setItem(i, j, item)
def filter_table(self, text):
if text:
self.populate_table(
"SELECT * FROM foo_table WHERE {} LIKE ?".format(
self.combo.currentText()
),
["%{}%".format(text)],
)
else:
self.populate_table("SELECT * FROM foo_table")
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
- QTableView + QStandardItemModel + sqlite3 模块
同上逻辑:
import sqlite3
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableView()
self.model = QtGui.QStandardItemModel()
self.table.setModel(self.model)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.connection = sqlite3.connect("database.db")
self.populate_table("SELECT * FROM foo_table")
self.edit.textChanged.connect(self.filter_table)
def populate_table(self, query):
cursor = self.connection.cursor()
cursor.execute(query)
name_of_columns = [e[0] for e in cursor.description]
self.model.setColumnCount(len(name_of_columns))
self.model.setRowCount(0)
self.model.setHorizontalHeaderLabels(name_of_columns)
self.combo.clear()
self.combo.addItems(name_of_columns)
for i, row_data in enumerate(cursor.fetchall()):
self.model.insertRow(self.model.rowCount())
for j, value in enumerate(row_data):
item = QtGui.QStandardItem()
item.setData(value, QtCore.Qt.DisplayRole)
self.model.setItem(i, j, item)
def filter_table(self, text):
if text:
filter_column = self.combo.currentIndex()
for i in range(self.model.rowCount()):
item = self.model.item(i, filter_column)
if self.filter_row(item, text):
self.table.showRow(i)
else:
self.table.hideRow(i)
else:
for i in range(self.model.rowCount()):
self.table.showRow(i)
def filter_row(self, item, text):
return text in item.text()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
import sqlite3
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableView()
self.model = QtGui.QStandardItemModel()
self.table.setModel(self.model)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.connection = sqlite3.connect("database.db")
self.populate_table("SELECT * FROM foo_table")
self.edit.textChanged.connect(self.filter_table)
def populate_table(self, query, values=None):
cursor = self.connection.cursor()
if values is None:
cursor.execute(query)
else:
cursor.execute(query, values)
name_of_columns = [e[0] for e in cursor.description]
self.model.setColumnCount(len(name_of_columns))
self.model.setRowCount(0)
self.model.setHorizontalHeaderLabels(name_of_columns)
self.combo.clear()
self.combo.addItems(name_of_columns)
for i, row_data in enumerate(cursor.fetchall()):
self.model.insertRow(self.model.rowCount())
for j, value in enumerate(row_data):
item = QtGui.QStandardItem()
item.setData(value, QtCore.Qt.DisplayRole)
self.model.setItem(i, j, item)
def filter_table(self, text):
if text:
self.populate_table(
"SELECT * FROM foo_table WHERE {} LIKE ?".format(
self.combo.currentText()
),
["%{}%".format(text)],
)
else:
self.populate_table("SELECT * FROM foo_table")
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
还有使用 QSortFilterProxyModel 的选项:
import sqlite3
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableView()
self.model = QtGui.QStandardItemModel()
self.proxy = QtCore.QSortFilterProxyModel()
self.proxy.setSourceModel(self.model)
self.proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.table.setModel(self.proxy)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.connection = sqlite3.connect("database.db")
self.populate_table("SELECT * FROM foo_table")
self.combo.currentIndexChanged.connect(self.proxy.setFilterKeyColumn)
self.edit.textChanged.connect(self.proxy.setFilterRegExp)
def populate_table(self, query, values=None):
cursor = self.connection.cursor()
if values is None:
cursor.execute(query)
else:
cursor.execute(query, values)
name_of_columns = [e[0] for e in cursor.description]
self.model.setColumnCount(len(name_of_columns))
self.model.setRowCount(0)
self.model.setHorizontalHeaderLabels(name_of_columns)
self.combo.clear()
self.combo.addItems(name_of_columns)
for i, row_data in enumerate(cursor.fetchall()):
self.model.insertRow(self.model.rowCount())
for j, value in enumerate(row_data):
item = QtGui.QStandardItem()
item.setData(value, QtCore.Qt.DisplayRole)
self.model.setItem(i, j, item)
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
- QTableView + QSqlQueryModel
在这种情况下,最好的选择是使用 sql 更改查询来制作过滤器:
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableView()
self.model = QtSql.QSqlQueryModel()
self.table.setModel(self.model)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.populate_table("SELECT * FROM foo_table")
self.edit.textChanged.connect(self.filter_table)
def populate_table(self, query, values=None):
q = QtSql.QSqlQuery(query)
if values is not None:
for value in values:
q.addBindValue(value)
print(value)
if not q.exec_():
print(q.lastError().text())
self.model.setQuery(q)
self.combo.clear()
for i in range(self.model.columnCount()):
self.combo.addItem(self.model.headerData(i, QtCore.Qt.Horizontal))
def filter_table(self, text):
if text:
self.populate_table(
"SELECT * FROM foo_table WHERE {} LIKE ?".format(
self.combo.currentText()
),
["%{}%".format(text)],
)
else:
self.populate_table("SELECT * FROM foo_table")
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("database.db")
if not db.open():
sys.exit(-1)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
另一种选择是应用隐藏行的技术或使用 QSortFilterProxyModel。
- QTableView + QSqlTableModel
在这种情况下,应该使用 setFilter 方法:
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableView()
self.model = QtSql.QSqlTableModel()
self.table.setModel(self.model)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.model.setTable("foo_table")
self.model.select()
self.combo.clear()
for i in range(self.model.columnCount()):
self.combo.addItem(self.model.headerData(i, QtCore.Qt.Horizontal))
self.edit.textChanged.connect(self.filter_table)
def filter_table(self, text):
f = " {} LIKE '%{}%'".format(self.combo.currentText(), text) if text else text
self.model.setFilter(f)
self.model.select()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("database.db")
if not db.open():
sys.exit(-1)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
另一种选择是应用隐藏行的技术或使用 QSortFilterProxyModel。
我正在尝试创建一个搜索栏来过滤 table 中的数据,但看起来模型没有链接到 lineEdit table 有效,但我无法过滤使用它的数据库数据(它适用于列表)有什么问题?
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
mainLayout = QVBoxLayout()
conn = sqlite3.connect("banco_cadastro.db.db")
cursor = conn.cursor()
list = (cursor.fetchall())
model = QStandardItemModel(len(list), 5)
model.setHorizontalHeaderLabels(['Clients'])
for row, company in enumerate(list):
item = QStandardItem(company)
model.setItem(row, 0, item)
filter_proxy_model = QSortFilterProxyModel()
filter_proxy_model.setSourceModel(model)
filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
filter_proxy_model.setFilterKeyColumn(0)
MainWindow.setObjectName("MainWindow")
MainWindow.resize(779, 693)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.textChanged.connect(filter_proxy_model.setFilterRegExp)
mainLayout.addWidget(self.lineEdit)
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setObjectName("tableWidget")
MainWindow.setCentralWidget(self.centralwidget)
connection = sqlite3.connect('banco_cadastro.db')
query = "SELECT * FROM cadastro"
result = connection.execute(query)
list = (cursor.fetchall())
for row_number, row_data in enumerate(result):
self.tableWidget.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tableWidget.setItem(row_number, column_number, QtWidgets.QTableWidgetItem(str(data)))
connection.close()
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
免责声明:在此 post 中,我将只关注背景 objective 而不是 OP 的错误(例如将 QStandardItemModel 与 QTableWidget 结合使用,或无用的尝试使用不连接任何东西的 QSortFilterProxyModel)。
我将借此机会展示如何使用 PyQt5(它也适用于 PySide2)过滤 sqlite 表的不同方法(相同的概念可以应用于其他数据库)。
- QTableWidget + sqlite3 模块
一个可能的解决方案是遍历行并验证它是否满足所需条件,如果满足则该行将可见,否则该行将被隐藏。
import sqlite3
from PyQt5 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableWidget()
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.connection = sqlite3.connect("database.db")
self.populate_table("SELECT * FROM foo_table")
self.edit.textChanged.connect(self.filter_table)
def populate_table(self, query, values=None):
cursor = self.connection.cursor()
if values is None:
cursor.execute(query)
else:
cursor.execute(query, values)
name_of_columns = [e[0] for e in cursor.description]
self.table.setColumnCount(len(name_of_columns))
self.table.setRowCount(0)
self.table.setHorizontalHeaderLabels(name_of_columns)
self.combo.clear()
self.combo.addItems(name_of_columns)
for i, row_data in enumerate(cursor.fetchall()):
self.table.insertRow(self.table.rowCount())
for j, value in enumerate(row_data):
item = QtWidgets.QTableWidgetItem()
item.setData(QtCore.Qt.DisplayRole, value)
self.table.setItem(i, j, item)
def filter_table(self, text):
if text:
filter_column = self.combo.currentIndex()
for i in range(self.table.rowCount()):
item = self.table.item(i, filter_column)
if self.filter_row(item, text):
self.table.showRow(i)
else:
self.table.hideRow(i)
else:
for i in range(self.table.rowCount()):
self.table.showRow(i)
def filter_row(self, item, text):
return text in item.text()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
另一种可能的解决方案是删除所有数据并使用过滤器发出新请求。
import sqlite3
from PyQt5 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableWidget()
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.connection = sqlite3.connect("database.db")
self.populate_table("SELECT * FROM foo_table")
self.edit.textChanged.connect(self.filter_table)
def populate_table(self, query, values=None):
cursor = self.connection.cursor()
if values is None:
cursor.execute(query)
else:
cursor.execute(query, values)
name_of_columns = [e[0] for e in cursor.description]
self.table.setColumnCount(len(name_of_columns))
self.table.setRowCount(0)
self.table.setHorizontalHeaderLabels(name_of_columns)
self.combo.clear()
self.combo.addItems(name_of_columns)
for i, row_data in enumerate(cursor.fetchall()):
self.table.insertRow(self.table.rowCount())
for j, value in enumerate(row_data):
item = QtWidgets.QTableWidgetItem()
item.setData(QtCore.Qt.DisplayRole, value)
self.table.setItem(i, j, item)
def filter_table(self, text):
if text:
self.populate_table(
"SELECT * FROM foo_table WHERE {} LIKE ?".format(
self.combo.currentText()
),
["%{}%".format(text)],
)
else:
self.populate_table("SELECT * FROM foo_table")
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
- QTableView + QStandardItemModel + sqlite3 模块
同上逻辑:
import sqlite3
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableView()
self.model = QtGui.QStandardItemModel()
self.table.setModel(self.model)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.connection = sqlite3.connect("database.db")
self.populate_table("SELECT * FROM foo_table")
self.edit.textChanged.connect(self.filter_table)
def populate_table(self, query):
cursor = self.connection.cursor()
cursor.execute(query)
name_of_columns = [e[0] for e in cursor.description]
self.model.setColumnCount(len(name_of_columns))
self.model.setRowCount(0)
self.model.setHorizontalHeaderLabels(name_of_columns)
self.combo.clear()
self.combo.addItems(name_of_columns)
for i, row_data in enumerate(cursor.fetchall()):
self.model.insertRow(self.model.rowCount())
for j, value in enumerate(row_data):
item = QtGui.QStandardItem()
item.setData(value, QtCore.Qt.DisplayRole)
self.model.setItem(i, j, item)
def filter_table(self, text):
if text:
filter_column = self.combo.currentIndex()
for i in range(self.model.rowCount()):
item = self.model.item(i, filter_column)
if self.filter_row(item, text):
self.table.showRow(i)
else:
self.table.hideRow(i)
else:
for i in range(self.model.rowCount()):
self.table.showRow(i)
def filter_row(self, item, text):
return text in item.text()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
import sqlite3
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableView()
self.model = QtGui.QStandardItemModel()
self.table.setModel(self.model)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.connection = sqlite3.connect("database.db")
self.populate_table("SELECT * FROM foo_table")
self.edit.textChanged.connect(self.filter_table)
def populate_table(self, query, values=None):
cursor = self.connection.cursor()
if values is None:
cursor.execute(query)
else:
cursor.execute(query, values)
name_of_columns = [e[0] for e in cursor.description]
self.model.setColumnCount(len(name_of_columns))
self.model.setRowCount(0)
self.model.setHorizontalHeaderLabels(name_of_columns)
self.combo.clear()
self.combo.addItems(name_of_columns)
for i, row_data in enumerate(cursor.fetchall()):
self.model.insertRow(self.model.rowCount())
for j, value in enumerate(row_data):
item = QtGui.QStandardItem()
item.setData(value, QtCore.Qt.DisplayRole)
self.model.setItem(i, j, item)
def filter_table(self, text):
if text:
self.populate_table(
"SELECT * FROM foo_table WHERE {} LIKE ?".format(
self.combo.currentText()
),
["%{}%".format(text)],
)
else:
self.populate_table("SELECT * FROM foo_table")
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
还有使用 QSortFilterProxyModel 的选项:
import sqlite3
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableView()
self.model = QtGui.QStandardItemModel()
self.proxy = QtCore.QSortFilterProxyModel()
self.proxy.setSourceModel(self.model)
self.proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.table.setModel(self.proxy)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.connection = sqlite3.connect("database.db")
self.populate_table("SELECT * FROM foo_table")
self.combo.currentIndexChanged.connect(self.proxy.setFilterKeyColumn)
self.edit.textChanged.connect(self.proxy.setFilterRegExp)
def populate_table(self, query, values=None):
cursor = self.connection.cursor()
if values is None:
cursor.execute(query)
else:
cursor.execute(query, values)
name_of_columns = [e[0] for e in cursor.description]
self.model.setColumnCount(len(name_of_columns))
self.model.setRowCount(0)
self.model.setHorizontalHeaderLabels(name_of_columns)
self.combo.clear()
self.combo.addItems(name_of_columns)
for i, row_data in enumerate(cursor.fetchall()):
self.model.insertRow(self.model.rowCount())
for j, value in enumerate(row_data):
item = QtGui.QStandardItem()
item.setData(value, QtCore.Qt.DisplayRole)
self.model.setItem(i, j, item)
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
- QTableView + QSqlQueryModel
在这种情况下,最好的选择是使用 sql 更改查询来制作过滤器:
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableView()
self.model = QtSql.QSqlQueryModel()
self.table.setModel(self.model)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.populate_table("SELECT * FROM foo_table")
self.edit.textChanged.connect(self.filter_table)
def populate_table(self, query, values=None):
q = QtSql.QSqlQuery(query)
if values is not None:
for value in values:
q.addBindValue(value)
print(value)
if not q.exec_():
print(q.lastError().text())
self.model.setQuery(q)
self.combo.clear()
for i in range(self.model.columnCount()):
self.combo.addItem(self.model.headerData(i, QtCore.Qt.Horizontal))
def filter_table(self, text):
if text:
self.populate_table(
"SELECT * FROM foo_table WHERE {} LIKE ?".format(
self.combo.currentText()
),
["%{}%".format(text)],
)
else:
self.populate_table("SELECT * FROM foo_table")
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("database.db")
if not db.open():
sys.exit(-1)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
另一种选择是应用隐藏行的技术或使用 QSortFilterProxyModel。
- QTableView + QSqlTableModel
在这种情况下,应该使用 setFilter 方法:
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.edit = QtWidgets.QLineEdit()
self.combo = QtWidgets.QComboBox()
self.table = QtWidgets.QTableView()
self.model = QtSql.QSqlTableModel()
self.table.setModel(self.model)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.edit, 0, 0)
grid.addWidget(self.combo, 0, 1)
grid.addWidget(self.table, 1, 0, 1, 2)
self.model.setTable("foo_table")
self.model.select()
self.combo.clear()
for i in range(self.model.columnCount()):
self.combo.addItem(self.model.headerData(i, QtCore.Qt.Horizontal))
self.edit.textChanged.connect(self.filter_table)
def filter_table(self, text):
f = " {} LIKE '%{}%'".format(self.combo.currentText(), text) if text else text
self.model.setFilter(f)
self.model.select()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("database.db")
if not db.open():
sys.exit(-1)
ex = Widget()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
另一种选择是应用隐藏行的技术或使用 QSortFilterProxyModel。