Reputation: 174
How to show hidden row after applying filter in QTableView. I attached the code below and I applied filter for second column for filter value '2'. it is working as required. if want to show hidden row which contain value '3' in second column. it is not showing the row. I used match command to find row. everything working fine. but row not showing. please help me to resolve this.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class TableModel(QAbstractTableModel):
def __init__(self, data):super().__init__();self._data = data
def data(self, index, role):
if role == Qt.ItemDataRole.DisplayRole or role == Qt.EditRole :return self._data[index.row()][index.column()]
def rowCount(self, index):return len(self._data)
def columnCount(self, index):return len(self._data[0])
class tableview(QTableView):
def __init__(self):
super().__init__()
self.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
self.setFocusPolicy(Qt.FocusPolicy.NoFocus)
self.horizontalHeader().setStyleSheet("::section{Background-color:lightgray;border-radius:10px;}")
self.smodel = QSortFilterProxyModel()
self.smodel.setFilterKeyColumn(1)
self.setModel(self.smodel)
self.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
self.smodel.setSourceModel(TableModel([[1,2],[1,2],[1,3],[1,4]]))
self.smodel.setFilterFixedString('2')
def find(self,key):
start = self.smodel.index(0, 1)
matches = self.smodel.sourceModel().match(start,Qt.DisplayRole,key,hits=-1,flags=Qt.MatchExactly)
for match in matches:self.showRow(match.row())
app = QApplication([])
table=tableview()
table.show()
b=QPushButton();b.clicked.connect(lambda:table.find('3'))
b.show()
app.exec_()
Current result
Required result on button press
Upvotes: 1
Views: 1022
Reputation: 142641
I think filter
and showRow()
/hideRow()
can work in different way - so they may have problem to work together.
Filter
removes data before sending to TableView
, showRow()
/hideRow()
removes row directly in TableView
. If you want to use showRow
then you may need to clear filter
, hide all rows and show rows with 2
and 3
But it may be simpler to use filter
To show only rows with selected value (key = "3"
)
smodel.setFilterFixedString(key)
To clear filter and show all rows
smodel.setFilterFixedString("")
To filter few values you can use regex
self.smodel.setFilterRegExp("2|3")
or you could keep values on list
filtered = ["2", "3"]
self.smodel.setFilterRegExp( "|".join(filtered) )
Minimal working code.
My button toggles row "3"
- first click shows row, second click hides row, etc.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class TableModel(QAbstractTableModel):
def __init__(self, data):
super().__init__()
self._data = data
def data(self, index, role):
if role == Qt.ItemDataRole.DisplayRole or role == Qt.EditRole :
return self._data[index.row()][index.column()]
def rowCount(self, index):
return len(self._data)
def columnCount(self, index):
return len(self._data[0])
class tableview(QTableView):
def __init__(self):
super().__init__()
self.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
self.setFocusPolicy(Qt.FocusPolicy.NoFocus)
self.horizontalHeader().setStyleSheet("::section{Background-color:lightgray;border-radius:10px;}")
self.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
self.smodel = QSortFilterProxyModel()
self.setModel(self.smodel)
self.smodel.setSourceModel(TableModel([[1,2],[1,2],[1,3],[1,4]]))
self.smodel.setFilterKeyColumn(1)
self.filtered = ["2"]
#self.smodel.setFilterFixedString("2")
self.smodel.setFilterRegExp( "|".join(self.filtered) )
def find(self, key):
print('find:', key)
if key in self.filtered:
self.filtered.remove(key)
else:
self.filtered.append(key)
#self.smodel.setFilterFixedString("") # clear filter - show all rows
#self.smodel.setFilterFixedString(key)
#self.smodel.setFilterRegExp("2|3")
self.smodel.setFilterRegExp( "|".join(self.filtered) )
# --- main ---
app = QApplication([])
table = tableview()
table.show()
button = QPushButton(text="Toggle: 3")
button.clicked.connect(lambda:table.find('3'))
button.show()
app.exec()
BTW:
I see only one problem: some chars have special meaning in regex
so adding ie. dot .
to filtered
may hide all rows, so it may need use \.
.
The same problem can be with | ( ) [ ] ^ $
, etc.
Upvotes: 2