[PyQt] [PYQT5]Highlight search results in qtablewidget(select and highlight that text or character not all of the row or column)

Maurizio Berti maurizio.berti at gmail.com
Mon Aug 20 15:45:27 BST 2018


I'm not an expert on regular expressions, maybe there's a better and faster
approach than the one I used in the example.
I initially tried using re.sub, but works correctly only if you want to
match case, as the substitution string is fixed.
Anyway, it seems fast enough to me, as the viewport update() takes care of
repainting only visible elements.

Another (derivate) approach could be subclassing the model too (the data()
method), adding a custom user role for the html filtered text that can be
read by the delegate, maybe with some sort of caching in the model to speed
up reading. It may be slightly faster and more "elegant" (the model takes
care of the string match, not the delegate), and could be useful for
further implementation.

I forgot to say: my example obviously doesn't consider spacings, grid lines
pen width and icon decoration.

Maurizio

Il giorno lun 20 ago 2018 alle ore 16:01 Maziar Parsijani <
maziar.parsijani at gmail.com> ha scritto:

> Really thanks to Maurizio
> I will try this.I agree with you and was thinking if someone had a
> solution with re library and regix could be better for me .
>
>
> On Mon, Aug 20, 2018 at 6:09 PM, Maurizio Berti <maurizio.berti at gmail.com>
> wrote:
>
>> I know you already found a solution, but I decided to give it a try
>> anyway, just out of curiosity.
>> I didn't like the idea of using another QWidget, which might involve
>> QStyle issues, then I found out that it's possible to use QTextDocument.
>> This is a simple implementation that just matches the text in all items
>> (no actual search in the model).
>>
>>
>> class MatchDelegate(QtWidgets.QStyledItemDelegate):
>>     regex = re.compile('')
>>     fakeIndex = QtCore.QModelIndex()
>>
>>     def paint(self, qp, option, index):
>>         self.initStyleOption(option, index)
>>         td = QtGui.QTextDocument()
>>         if self.regex.pattern:
>>             splitted = self.regex.split(option.text)
>>             matches = iter(self.regex.findall(option.text))
>>             text = ''
>>             for words in splitted[:-1]:
>>                 text += words + '<b>{}</b>'.format(matches.next())
>>             text += splitted[-1]
>>         else:
>>             text = option.text
>>         td.setHtml(text)
>>         option.text = ''
>>         # Using an invalid index avoids painting of the text
>>         QtWidgets.QStyledItemDelegate.paint(self, qp, option,
>> self.fakeIndex)
>>         qp.save()
>>         qp.translate(option.rect.topLeft())
>>         td.drawContents(qp, QtCore.QRectF(0, 0, option.rect.width(),
>> option.rect.height()))
>>         qp.restore()
>>
>>
>> class Widget(QtWidgets.QWidget):
>>     def __init__(self):
>>         [...]
>>         self.delegate = MatchDelegate()
>>         self.table.setItemDelegate(self.delegate)
>>         self.search = QtWidgets.QLineEdit()
>>         self.search.textChanged.connect(self.findText)
>>         [...]
>>
>>     def findText(self, text):
>>         self.delegate.regex = re.compile(text, re.I)
>>         self.table.viewport().update()
>>
>>
>> Of course it doesn't take the text size change into account whenever bold
>> characters are in place, so the sizeHint is not perfect. Also, it might be
>> possible to implement QFontMetrics' elidedText, again with some small
>> issues about font size changes.
>>
>> Maurizio
>>
>>
>> Il giorno lun 20 ago 2018 alle ore 11:31 Maziar Parsijani <
>> maziar.parsijani at gmail.com> ha scritto:
>>
>>> Hi Denis Rouzaud
>>>
>>> This question was for 19days ago.But you are correct the best method is
>>> html delegate and I did it but I couldn't fix that with my table and the
>>> table was changed but it worked nice.
>>>
>>> On Mon, Aug 20, 2018 at 12:28 PM, Denis Rouzaud <denis.rouzaud at gmail.com
>>> > wrote:
>>>
>>>> This is not easily done.
>>>> You'd have to create a custom delegate using a QLabbel and use html in
>>>> there.
>>>>
>>>> I have been creating a search tool for tables and ending up
>>>> highlighting the whole cell.
>>>> The effort and the risk of bad results is just not worth the effort
>>>> IMHO.
>>>>
>>>> Denis
>>>>
>>>> Le mar. 31 juil. 2018 à 23:05, Maziar Parsijani <
>>>> maziar.parsijani at gmail.com> a écrit :
>>>>
>>>>> I use method1 to find some text in qtablewidget rows.
>>>>>
>>>>> method1 :
>>>>>
>>>>> def FindItem(self):
>>>>>     items = self.SuraBRS.findItems(
>>>>>         self.SearchTbox.text(), QtCore.Qt.MatchContains)
>>>>>     if items:
>>>>>         results = '\n'.join(
>>>>>             'row %d column %d' % (item.row() + 1, item.column() + 1)
>>>>>             for item in items)
>>>>>     else:
>>>>>         results = 'Found Nothing'
>>>>>     print(results)
>>>>>
>>>>> Now I want to know how to highlight results or change their color.*I
>>>>> want to select and highlight that text or character not all of the row or
>>>>> column*.
>>>>> _______________________________________________
>>>>> PyQt mailing list    PyQt at riverbankcomputing.com
>>>>> https://www.riverbankcomputing.com/mailman/listinfo/pyqt
>>>>
>>>> --
>>>>
>>>> Denis Rouzaud
>>>> denis at opengis.ch  <denis at opengis.ch>
>>>> +41 76 370 21 22
>>>>
>>>>
>>>>
>>> _______________________________________________
>>> PyQt mailing list    PyQt at riverbankcomputing.com
>>> https://www.riverbankcomputing.com/mailman/listinfo/pyqt
>>
>>
>>
>> --
>> È difficile avere una convinzione precisa quando si parla delle ragioni
>> del cuore. - "Sostiene Pereira", Antonio Tabucchi
>> http://www.jidesk.net
>>
>
>

-- 
È difficile avere una convinzione precisa quando si parla delle ragioni del
cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20180820/b3145ea5/attachment-0001.html>


More information about the PyQt mailing list