Issue
How to arrange the filtered QListwidget items in the following order,
- List item starting with the search term.
- List item containing anywhere in the search term and finally.
- List item ends in the search item.
For example, In My Program, my search term is "I", I want to arrange item starts with "I" ("India", "Iceland", "Iran"), then item containing anywhere ("America", "China", "Fiji","Russia"), finally items end with search term "I" ("Brunei", "Mali")
import sys
from PyQt5.QtWidgets import QApplication,QWidget,QListWidget,QLineEdit,QVBoxLayout
from PyQt5.QtCore import Qt,QEvent
items = ["America","canada","Mali","India","Russia", "Fiji","Nepal","Iran","China","Japan","IceLand","Brunei"]
class Listwidget(QWidget):
def __init__(self):
super(). __init__()
self.setWindowTitle("List Box Samples")
self.le = QLineEdit()
self.le.textChanged.connect(self.func_textchanged)
self.lb_master = QListWidget()
self.lb_search = QListWidget()
vbox = QVBoxLayout(self)
vbox.addWidget(self.le)
vbox.addWidget(self.lb_search)
self.lb_master.addItems(items)
self.lb_search.addItems(items)
self.le.setFocus()
self.le.installEventFilter(self)
def eventFilter(self, source,event):
if event.type() == QEvent.KeyPress and source is self.le:
if event.key() == Qt.Key_Backspace:
if len(self.le.text()) == 0:
self.fun_normal()
return super(Listwidget,self).eventFilter(source,event)
def fun_normal(self):
self.lb_search.clear()
if normal_count > 0:
for item in item_normal:
self.lb_search.addItem(item.text())
def func_search(self):
self.lb_search.clear()
if search_count > 0:
for item in item_anywhere:
self.lb_search.addItem(item.text())
def func_textchanged(self):
global item_normal,item_anywhere,search_count,normal_count
item_normal = self.lb_master.findItems("*",Qt.MatchWildcard)
item_anywhere = self.lb_master.findItems(self.le.text(), Qt.MatchContains)
normal_count = len(item_normal)
search_count = len(item_anywhere)
self.func_search()
if __name__ == "__main__":
app = QApplication(sys.argv)
win = Listwidget()
win.show()
sys.exit(app.exec_())
Solution
There are few ways to do go about what you are trying to acheive. One is to sort the list based on a key.
In your case, it could be
item_anywhere.sort(key=lambda item: item.text().lower().find(self.le.text()))
Output:
['India', 'Iran', 'IceLand', 'Fiji', 'China', 'Mali', 'America', 'Russia', 'Brunei']
As you can see there is a small problem with this approach, that is, "Mali" is in the middle of the list and not towards the end.
The only approach I could think of right now is to use filter
function.
Below are the steps I followed:
- use the
find
method to find the strings (you have already done this part). - Now use that list and filter it based on words starting with
I
or whatever the search text is. - filter the list based on words that contain the search letter between them, then use sort as shown above on this list.
- filter the list based on words ending with
I
. - concatenate the list
def func_textchanged(self):
search_text = self.le.text().lower()
item_anywhere = self.lb_master.findItems(search_text, Qt.MatchContains)
start_list = list(filter(lambda item: item.text().lower().startswith(search_text), item_anywhere))
start_text = [x.text().lower() for x in start_list]
def bw_filter(item):
# checks if the letter is between the start and end letter, then checks if it already exists in start_list
item_text = item.text().lower()
return search_text in item_text[1:-1] and item_text not in start_text
bw_lst = list(filter(bw_filter, item_anywhere))
bw_lst.sort(key=lambda item: item.text().lower().find(search_text)) # sort it based on index
bw_text = [x.text().lower() for x in bw_lst]
def end_filter(item):
# checks if the string ends with search string, then checks if it already exists in
# start_list and between list
item_text = item.text().lower()
return item_text.endswith(search_text) and item_text.lower() not in start_text and item_text not in bw_text
end_lst = list(filter(end_filter, item_anywhere))
self.lb_search.clear()
for item in start_list + bw_lst + end_lst: # concatenate list
self.lb_search.addItem(item.text())
Answered By - Art
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.