I have a created a QTableWidget using pyqt5 and managed to add filter option in each column of the table widget successfully with one of the answers available on stack overflow. filters works as expected but I wanted to add search bar in the filter at the top to search for the values.
In my python script I would probably have around more than 50 unique values in filter. So it becomes easy if there’s a way to search for a value in the filter.
Also, Is there a way we can add scroll bar in this because currently if I add more values to the table, my filter area gets bigger and bigger to accumulate all values.
Here is My complete python code :
import csv
import sys
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QTableWidget, QCheckBox, QWidgetAction, QMenu, QDialogButtonBox, QTableWidgetItem
from PyQt5.QtGui import QFont
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent=parent)
self.verticalLayout = QVBoxLayout(self)
self.filterall = QTableWidget(self)
self.filterall.setColumnCount(0)
self.filterall.setRowCount(0)
self.verticalLayout.addWidget(self.filterall)
self.loadAll()
self.horizontalHeader = self.filterall.horizontalHeader()
self.horizontalHeader.sectionClicked.connect(self.on_view_horizontalHeader_sectionClicked)
self.keywords = dict([(i, []) for i in range(self.filterall.columnCount())])
self.checkBoxs = []
self.col = None
def slotSelect(self, state):
for checkbox in self.checkBoxs:
checkbox.setChecked(QtCore.Qt.Checked == state)
def on_view_horizontalHeader_sectionClicked(self, index):
#self.clearFilter()
self.menu = QMenu(self)
#self.menu.setStyleSheet('QMenu { menu-scrollable: true; }')
self.col = index
data_unique = []
self.checkBoxs = []
checkBox = QCheckBox("Select all", self.menu)
checkableAction = QWidgetAction(self.menu)
checkableAction.setDefaultWidget(checkBox)
self.menu.addAction(checkableAction)
checkBox.setChecked(True)
checkBox.stateChanged.connect(self.slotSelect)
for i in range(self.filterall.rowCount()):
if not self.filterall.isRowHidden(i):
item = self.filterall.item(i, index)
font = QFont()
font.setBold(False)
self.filterall.horizontalHeaderItem(index).setFont(font)
if item.text() not in data_unique:
data_unique.append(item.text())
checkBox = QCheckBox(item.text(), self.menu)
checkBox.setChecked(True)
checkableAction = QWidgetAction(self.menu)
checkableAction.setDefaultWidget(checkBox)
self.menu.addAction(checkableAction)
self.checkBoxs.append(checkBox)
btn = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
QtCore.Qt.Horizontal, self.menu)
btn.accepted.connect(self.menuClose)
btn.rejected.connect(self.menu.close)
checkableAction = QWidgetAction(self.menu)
checkableAction.setDefaultWidget(btn)
self.menu.addAction(checkableAction)
headerPos = self.filterall.mapToGlobal(self.horizontalHeader.pos())
posY = headerPos.y() + self.horizontalHeader.height()
posX = headerPos.x() + self.horizontalHeader.sectionPosition(index)
self.menu.exec_(QtCore.QPoint(posX, posY))
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 loadAll(self):
with open("sample.csv", "r") as inpfil:
reader = csv.reader(inpfil, delimiter=',')
csheader = next(reader)
ncol = len(csheader)
data = list(reader)
row_count = len(data)
self.filterall.setRowCount(row_count)
self.filterall.setColumnCount(ncol)
self.filterall.setHorizontalHeaderLabels(str('%s' % ', '.join(map(str, csheader))).split(","))
for ii in range(0, row_count):
mainins = data[ii]
for var in range(0, ncol):
self.filterall.setItem(ii, var, QTableWidgetItem(mainins[var]))
def clearFilter(self):
for i in range(self.filterall.rowCount()):
self.filterall.setRowHidden(i, False)
def filterdata(self):
columnsShow = dict([(i, True) for i in range(self.filterall.rowCount())])
for i in range(self.filterall.rowCount()):
for j in range(self.filterall.columnCount()):
item = self.filterall.item(i, j)
if self.keywords[j]:
if item.text() not in self.keywords[j]:
columnsShow[i] = False
font = QFont()
font.setBold(True)
self.filterall.horizontalHeaderItem(j).setFont(font)
for key, value in columnsShow.items():
self.filterall.setRowHidden(key, not value)
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
I would to see my code working such that when user type in searchbar, it filters option from the given unique values. It is like having search bar in excel filters where you can type keyword and filter available unique values.
Expected Sample Output :
Excel like Filtering
My code filtering as shown below :
python code filtering
My sample.csv file has data (19 records) as this shown in below screenshot:
sample.csv file
Jenit Patel is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.