在 PyQt5 QListWidget 中排列项目?
Arrange Items in PyQt5 QListWidget?
如何按以下顺序排列过滤后的 QListwidget 项,
- 列表项从开始使用搜索词。
- 列表项 包含 在搜索词的任何位置,最后。
- 列表项在搜索项中结束。
例如,在我的程序中,我的搜索词是 "I",我想排列以 "I" 开头的项目 ("India", “冰岛”、“伊朗”),然后项目包含任何地方 (“美国”、“中国”、“斐济”、“俄罗斯”),最后项目以搜索字词 "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_())
实现您想要实现的目标的方法很少。一种是根据键对列表进行排序。
你的情况可能是
item_anywhere.sort(key=lambda item: item.text().lower().find(self.le.text()))
输出:
['India', 'Iran', 'IceLand', 'Fiji', 'China', 'Mali', 'America', 'Russia', 'Brunei']
如您所见,这种方法存在一个小问题,即“马里”在列表的中间,而不是最后。
我现在唯一能想到的方法是使用 filter
函数。
以下是我遵循的步骤:
- 使用
find
方法查找字符串(您已经完成了这部分)。
- 现在使用该列表并根据以
I
开头的单词或任何搜索文本对其进行过滤。
- 根据包含搜索字母的单词过滤列表,然后按上面所示对该列表进行排序。
- 根据以
I
结尾的单词过滤列表。
- 连接列表
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())
如何按以下顺序排列过滤后的 QListwidget 项,
- 列表项从开始使用搜索词。
- 列表项 包含 在搜索词的任何位置,最后。
- 列表项在搜索项中结束。
例如,在我的程序中,我的搜索词是 "I",我想排列以 "I" 开头的项目 ("India", “冰岛”、“伊朗”),然后项目包含任何地方 (“美国”、“中国”、“斐济”、“俄罗斯”),最后项目以搜索字词 "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_())
实现您想要实现的目标的方法很少。一种是根据键对列表进行排序。
你的情况可能是
item_anywhere.sort(key=lambda item: item.text().lower().find(self.le.text()))
输出:
['India', 'Iran', 'IceLand', 'Fiji', 'China', 'Mali', 'America', 'Russia', 'Brunei']
如您所见,这种方法存在一个小问题,即“马里”在列表的中间,而不是最后。
我现在唯一能想到的方法是使用 filter
函数。
以下是我遵循的步骤:
- 使用
find
方法查找字符串(您已经完成了这部分)。 - 现在使用该列表并根据以
I
开头的单词或任何搜索文本对其进行过滤。 - 根据包含搜索字母的单词过滤列表,然后按上面所示对该列表进行排序。
- 根据以
I
结尾的单词过滤列表。 - 连接列表
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())