如何在Pyqt5 Python的QTableWidget中的列过滤器中添加搜索栏?
我已经使用pyqt5创建了一个QTableWidget,并成功地在table widget的每一列中添加了filter选项,其中一个答案在stack overflow上可用。过滤器按预期工作,但我想在顶部的过滤器中添加搜索栏来搜索值 在我的实际脚本中,我可能在过滤器中有大约3-4k的唯一值,因此如果有一种方法可以在过滤器中搜索一个值,那么就很容易了 还有,有没有一种方法可以在这里添加滚动条,因为当前如果我向表中添加更多的值,我的筛选区域会越来越大,以累积所有值 我张贴最低限度的工作代码如下 UIDesigner生成的代码:如何在Pyqt5 Python的QTableWidget中的列过滤器中添加搜索栏?,python,python-3.x,pyqt5,qtablewidget,qmenu,Python,Python 3.x,Pyqt5,Qtablewidget,Qmenu,我已经使用pyqt5创建了一个QTableWidget,并成功地在table widget的每一列中添加了filter选项,其中一个答案在stack overflow上可用。过滤器按预期工作,但我想在顶部的过滤器中添加搜索栏来搜索值 在我的实际脚本中,我可能在过滤器中有大约3-4k的唯一值,因此如果有一种方法可以在过滤器中搜索一个值,那么就很容易了 还有,有没有一种方法可以在这里添加滚动条,因为当前如果我向表中添加更多的值,我的筛选区域会越来越大,以累积所有值 我张贴最低限度的工作代码如下 U
from PyQt5 import QtCore, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(10, 10, 771, 561))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(0)
self.tableWidget.setRowCount(0)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
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_())
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QTableWidgetItem
import pandas as pd
from demo import Ui_MainWindow
class DemoTable(QtWidgets.QMainWindow, Ui_MainWindow):
#signalrunningriskmanagertext = QtCore.pyqtSignal(str)
def __init__(self):
super(DemoTable, self).__init__()
self.setupUi(self)
#Set up table data
self.tableWidget.setRowCount(25)
self.tableWidget.setColumnCount(4)
self.tableWidget.setHorizontalHeaderLabels(['A','B','C','D'])
d = {'A': range(0,25),
'B': range(20,45),
'C': ['a','b','c','d','e','f','g','h','i','d','s','n','s','t','h','d','t','s','t','s','e','y','d','b','s'],
'D': ['a','b','c','d','e','f','g','h','i','d','s','n','s','t','h','d','t','s','t','s','e','y','d','b','s']}
df = pd.DataFrame(data=d)
for row in range(0,25):
for column in range(0,4):
item = QTableWidgetItem(str(df.iloc[row,column]))
self.tableWidget.setItem(row, column, item)
#Add filters in column
self.tableWidgetHeader = self.tableWidget.horizontalHeader()
self.tableWidgetHeader.sectionClicked.connect(self.columnfilterclicked)
self.keywords = dict([(i, []) for i in range(self.tableWidget.columnCount())])
self.checkBoxs = []
self.col = None
def slotSelect(self, state):
for checkbox in self.checkBoxs:
checkbox.setChecked(QtCore.Qt.Checked == state)
def menuClose(self):
self.keywords[self.col] = []
for element in self.checkBoxs:
if element.isChecked():
self.keywords[self.col].append(element.text())
self.filterdata()
self.menu.close()
def clearFilter(self):
if self.tableWidget.rowCount() > 0:
for i in range(self.tableWidget.rowCount()):
self.tableWidget.setRowHidden(i, False)
def filterdata(self):
columnsShow = dict([(i, True) for i in range(self.tableWidget.rowCount())])
for i in range(self.tableWidget.rowCount()):
for j in range(self.tableWidget.columnCount()):
item = self.tableWidget.item(i, j)
if self.keywords[j]:
if item.text() not in self.keywords[j]:
columnsShow[i] = False
for key in columnsShow:
self.tableWidget.setRowHidden(key, not columnsShow[key])
def columnfilterclicked(self,index):
self.menu = QtWidgets.QMenu(self)
self.col = index
data_unique = []
self.checkBoxs = []
checkBox = QtWidgets.QCheckBox("Select all", self.menu)
checkableAction = QtWidgets.QWidgetAction(self.menu)
checkableAction.setDefaultWidget(checkBox)
self.menu.addAction(checkableAction)
checkBox.setChecked(True)
checkBox.stateChanged.connect(self.slotSelect)
for i in range(self.tableWidget.rowCount()):
if not self.tableWidget.isRowHidden(i):
item = self.tableWidget.item(i, index)
if item.text() not in data_unique:
data_unique.append(item.text())
checkBox = QtWidgets.QCheckBox(item.text(), self.menu)
checkBox.setChecked(True)
checkableAction = QtWidgets.QWidgetAction(self.menu)
checkableAction.setDefaultWidget(checkBox)
self.menu.addAction(checkableAction)
self.checkBoxs.append(checkBox)
btn = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel,
QtCore.Qt.Horizontal, self.menu)
btn.accepted.connect(self.menuClose)
btn.rejected.connect(self.menu.close)
checkableAction = QtWidgets.QWidgetAction(self.menu)
checkableAction.setDefaultWidget(btn)
self.menu.addAction(checkableAction)
headerPos = self.tableWidget.mapToGlobal(self.tableWidgetHeader.pos())
posY = headerPos.y() + self.tableWidgetHeader.height()
posX = headerPos.x() + self.tableWidgetHeader.sectionPosition(index)
self.menu.exec_(QtCore.QPoint(posX, posY))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = DemoTable()
window.show()
sys.exit(app.exec_())
我的脚本:
from PyQt5 import QtCore, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(10, 10, 771, 561))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(0)
self.tableWidget.setRowCount(0)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
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_())
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QTableWidgetItem
import pandas as pd
from demo import Ui_MainWindow
class DemoTable(QtWidgets.QMainWindow, Ui_MainWindow):
#signalrunningriskmanagertext = QtCore.pyqtSignal(str)
def __init__(self):
super(DemoTable, self).__init__()
self.setupUi(self)
#Set up table data
self.tableWidget.setRowCount(25)
self.tableWidget.setColumnCount(4)
self.tableWidget.setHorizontalHeaderLabels(['A','B','C','D'])
d = {'A': range(0,25),
'B': range(20,45),
'C': ['a','b','c','d','e','f','g','h','i','d','s','n','s','t','h','d','t','s','t','s','e','y','d','b','s'],
'D': ['a','b','c','d','e','f','g','h','i','d','s','n','s','t','h','d','t','s','t','s','e','y','d','b','s']}
df = pd.DataFrame(data=d)
for row in range(0,25):
for column in range(0,4):
item = QTableWidgetItem(str(df.iloc[row,column]))
self.tableWidget.setItem(row, column, item)
#Add filters in column
self.tableWidgetHeader = self.tableWidget.horizontalHeader()
self.tableWidgetHeader.sectionClicked.connect(self.columnfilterclicked)
self.keywords = dict([(i, []) for i in range(self.tableWidget.columnCount())])
self.checkBoxs = []
self.col = None
def slotSelect(self, state):
for checkbox in self.checkBoxs:
checkbox.setChecked(QtCore.Qt.Checked == state)
def menuClose(self):
self.keywords[self.col] = []
for element in self.checkBoxs:
if element.isChecked():
self.keywords[self.col].append(element.text())
self.filterdata()
self.menu.close()
def clearFilter(self):
if self.tableWidget.rowCount() > 0:
for i in range(self.tableWidget.rowCount()):
self.tableWidget.setRowHidden(i, False)
def filterdata(self):
columnsShow = dict([(i, True) for i in range(self.tableWidget.rowCount())])
for i in range(self.tableWidget.rowCount()):
for j in range(self.tableWidget.columnCount()):
item = self.tableWidget.item(i, j)
if self.keywords[j]:
if item.text() not in self.keywords[j]:
columnsShow[i] = False
for key in columnsShow:
self.tableWidget.setRowHidden(key, not columnsShow[key])
def columnfilterclicked(self,index):
self.menu = QtWidgets.QMenu(self)
self.col = index
data_unique = []
self.checkBoxs = []
checkBox = QtWidgets.QCheckBox("Select all", self.menu)
checkableAction = QtWidgets.QWidgetAction(self.menu)
checkableAction.setDefaultWidget(checkBox)
self.menu.addAction(checkableAction)
checkBox.setChecked(True)
checkBox.stateChanged.connect(self.slotSelect)
for i in range(self.tableWidget.rowCount()):
if not self.tableWidget.isRowHidden(i):
item = self.tableWidget.item(i, index)
if item.text() not in data_unique:
data_unique.append(item.text())
checkBox = QtWidgets.QCheckBox(item.text(), self.menu)
checkBox.setChecked(True)
checkableAction = QtWidgets.QWidgetAction(self.menu)
checkableAction.setDefaultWidget(checkBox)
self.menu.addAction(checkableAction)
self.checkBoxs.append(checkBox)
btn = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel,
QtCore.Qt.Horizontal, self.menu)
btn.accepted.connect(self.menuClose)
btn.rejected.connect(self.menu.close)
checkableAction = QtWidgets.QWidgetAction(self.menu)
checkableAction.setDefaultWidget(btn)
self.menu.addAction(checkableAction)
headerPos = self.tableWidget.mapToGlobal(self.tableWidgetHeader.pos())
posY = headerPos.y() + self.tableWidgetHeader.height()
posX = headerPos.x() + self.tableWidgetHeader.sectionPosition(index)
self.menu.exec_(QtCore.QPoint(posX, posY))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = DemoTable()
window.show()
sys.exit(app.exec_())
很好,您提供了一个MRE,但您忘记了最重要的事情:解释搜索栏所需的行为。当用户在搜索栏中键入时,它会从给定的唯一值中筛选选项。这就像在excel过滤器中有搜索栏,您可以在其中键入关键字并过滤可用的唯一值。1)不幸的是,我不使用excel,2)我知道在弹出窗口中必须显示唯一选项,以便选中它们。我说得对吗?3) 如果我在搜索栏中键入内容,那么是否应过滤表格或弹出窗口的选项?对于第2点,是。必须在弹出窗口中选中所有唯一选项。对于第3点,当我在搜索栏中键入时,它应该过滤弹出窗口的选项,并且我应该能够选中和取消选中过滤的选项。很好,您提供了MRE,但您忘记了最重要的事情:解释搜索栏所需的行为。当用户在搜索栏中键入时,它从给定的唯一值中筛选选项。这就像在excel过滤器中有搜索栏,您可以在其中键入关键字并过滤可用的唯一值。1)不幸的是,我不使用excel,2)我知道在弹出窗口中必须显示唯一选项,以便选中它们。我说得对吗?3) 如果我在搜索栏中键入内容,那么是否应过滤表格或弹出窗口的选项?对于第2点,是。必须在弹出窗口中选中所有唯一选项。对于第3点,当我在搜索栏中键入时,它应该过滤弹出窗口的选项,并且我应该能够选中和取消选中过滤的选项。