I use QTableWidget in a project. But there is no search feature in QTableWidget.
How to set filter option in qtablewidget
QTableView allows searching. But this time QTableView, non-English characters are not sorted correctly. QTableWidget sort is great. I want to use QTableView. How can I fix the non-English character sorting in QTableView.
QTableWidget Code
class GuiQTableWidget(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle("QTableWidget")
v_box = QVBoxLayout()
v_box.addWidget(self.prepare_table())
self.setLayout(v_box)
self.setMinimumHeight(750)
self.setFixedWidth(self.width())
def prepare_table(self):
letter_list = [ 'A','B','C','Ç','G','Ğ','I','I','O','Ö','P','S','Ş','U','Ü','Y','Z',
'a','b','c','ç','g','ğ','ı','i','o','ö','p','s','ş','u','ü','y','z' ]
table = QTableWidget()
table.setColumnCount(1)
table.setHorizontalHeaderLabels(["Letter"])
table.setRowCount(len(letter_list))
for row, letter in enumerate(letter_list):
table.setItem(row, 0, QTableWidgetItem(letter))
h_header = table.horizontalHeader()
h_header.setSectionResizeMode(QHeaderView.Stretch)
table.setSortingEnabled(True)
table.setAlternatingRowColors(True)
return table
QTableView
class GuilQTableView(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
# sort
self.h_header.sortIndicatorChanged.connect(self.sort)
# filter
self.line_search.textChanged.connect(self.filter)
def init_ui(self):
self.setWindowTitle("QTableView")
self.table = QTableView()
self.h_header = self.table.horizontalHeader()
self.model = QStandardItemModel()
self.proxyFilter = QSortFilterProxyModel()
self.line_search = QLineEdit()
lbl_search = QLabel("Letter Search")
h_search = QHBoxLayout()
h_search.addWidget(lbl_search)
h_search.addWidget(self.line_search)
v_box = QVBoxLayout()
v_box.addLayout(h_search)
v_box.addWidget(self.prepare_table(self.table, self.model, self.proxyFilter, self.h_header))
self.setLayout(v_box)
self.setMinimumHeight(750)
self.setFixedWidth(self.width())
def prepare_table(self, table, model, proxyFilter, h_header):
letter_list = [ 'A','B','C','Ç','G','Ğ','I','I','O','Ö','P','S','Ş','U','Ü','Y','Z',
'a','b','c','ç','g','ğ','ı','i','o','ö','p','s','ş','u','ü','y','z' ]
model.setColumnCount(1)
model.setRowCount(len(letter_list))
model.setHorizontalHeaderLabels(['Letter'])
for row, letter in enumerate(letter_list):
model.setItem(row, 0, QStandardItem(letter))
proxyFilter.setSourceModel(model)
proxyFilter.setFilterKeyColumn(0)
proxyFilter.setSortCaseSensitivity(Qt.CaseSensitive)
table.setModel(proxyFilter)
table.setAlternatingRowColors(True)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.setSelectionMode(QAbstractItemView.ExtendedSelection)
h_header.setSectionResizeMode(QHeaderView.Stretch)
return table
def sort(self, sortOrder):
if sortOrder == Qt.AscendingOrder:
self.model.sort(0, Qt.AscendingOrder)
else:
self.model.sort(0, Qt.DescendingOrder)
self.h_header.setSortIndicatorShown(True)
def filter(self, text):
regExp = QRegExp(text, Qt.CaseInsensitive, QRegExp.Wildcard)
self.proxyFilter.setFilterRegExp(regExp)
QTableWidget is sorting correctly. QTableView lists the non-English characters (Ç,G,Ğ,İ,Ö,Ş,Ü, ç,ğ,ı,ö,ş,ü) at the bottom of the list. How can I fix the non-English character sorting in QTableView.
In the case of QTableWidget
, the operator <
of QTableWidgetItem
is used, which in this case uses QString that takes as reference the locality of the characters and the case of QSortFilterProxyModel uses the python string that does not take the locality as reference, that's why you see that difference, the solution is to overwrite the lessThan()
method of QSortFilterProxyModel
On the other hand it is not necessary to use the sortIndicatorChanged
signal since the QTableView
uses it internally advising the model.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class SortFilterProxyModel(QSortFilterProxyModel):
def lessThan(self, left, right):
leftData = self.sourceModel().data(left)
rightData = self.sourceModel().data(right)
return QTableWidgetItem(leftData) < QTableWidgetItem(rightData)
class GuilQTableView(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
# filter
self.line_search.textChanged.connect(self.filter)
def init_ui(self):
self.setWindowTitle("QTableView")
self.table = QTableView()
self.table.setSortingEnabled(True)
self.h_header = self.table.horizontalHeader()
self.model = QStandardItemModel()
self.proxyFilter = SortFilterProxyModel()
self.line_search = QLineEdit()
lbl_search = QLabel("Letter Search")
h_search = QHBoxLayout()
h_search.addWidget(lbl_search)
h_search.addWidget(self.line_search)
v_box = QVBoxLayout()
v_box.addLayout(h_search)
v_box.addWidget(self.prepare_table(self.table, self.model, self.proxyFilter, self.h_header))
self.setLayout(v_box)
self.setMinimumHeight(750)
self.setFixedWidth(self.width())
def prepare_table(self, table, model, proxyFilter, h_header):
letter_list = [ 'A','B','C','Ç','G','Ğ','I','I','O','Ö','P','S','Ş','U','Ü','Y','Z',
'a','b','c','ç','g','ğ','ı','i','o','ö','p','s','ş','u','ü','y','z' ]
model.setColumnCount(1)
model.setRowCount(len(letter_list))
model.setHorizontalHeaderLabels(['Letter'])
for row, letter in enumerate(letter_list):
model.setItem(row, 0, QStandardItem(letter))
proxyFilter.setSourceModel(model)
proxyFilter.setFilterKeyColumn(0)
proxyFilter.setSortCaseSensitivity(Qt.CaseSensitive)
table.setModel(proxyFilter)
table.setAlternatingRowColors(True)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.setSelectionMode(QAbstractItemView.ExtendedSelection)
h_header.setSectionResizeMode(QHeaderView.Stretch)
return table
def filter(self, text):
regExp = QRegExp(text, Qt.CaseInsensitive, QRegExp.Wildcard)
self.proxyFilter.setFilterRegExp(regExp)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = GuilQTableView()
w.show()
sys.exit(app.exec_())