当我运行我的工具并双击项目时,它会将名称输出到控制台,在这种情况下,它会打印“注释”。但是,如果我在搜索栏中输入,过滤掉列表,然后再次双击该图像,则会返回错误的名称。我不知道我在哪里错了。以下是整个应用程序的代码。
要测试只是将代码末尾的文件夹路径更改为包含某些jpg的计算机上的本地文件夹。我发现这是一个非常简单的应用程序,在listview上只有一个搜索过滤器。我很困惑为什么它会返回错误的项目。我猜它与我如何检索选择有关。
在我的QAbstractListModel上,我有一个传递选择的方法
def getSelectedItems(self, selection):
objs = []
for i, index in enumerate(selection):
item = self.getItem(index)
objs.append(item)
return objs
完整代码
import sys
import os
from PySide import QtGui, QtCore
from PySide import QtGui as QtWidgets
class AssetItem(object):
def __init__(self, filepath):
self._name = ''
self._filepath = ''
self.filepath = filepath
@property
def filepath(self):
return self._filepath
@filepath.setter
def filepath(self, value):
self._filepath = value
self._name, self._extension = os.path.splitext(os.path.basename(self.filepath))
@property
def name(self):
return self._name
class AssetModel(QtCore.QAbstractListModel):
NameRole = QtCore.Qt.UserRole + 1
def __init__(self, *args, **kwargs):
QtCore.QAbstractListModel.__init__(self, *args, **kwargs)
self._items = []
def rowCount(self, index=QtCore.QModelIndex()):
return len(self._items)
def addItem(self, assetItem):
self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
self._items.append(assetItem)
self.endInsertRows()
def getItem(self, index):
row = index.row()
if index.isValid() and 0 <= row < self.rowCount():
return self._items[row]
def getSelectedItems(self, selection):
objs = []
for i, index in enumerate(selection):
item = self.getItem(index)
objs.append(item)
return objs
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return None
if 0 <= index.row() < self.rowCount():
item = self._items[index.row()]
if role == AssetModel.NameRole:
return item.name
elif role == QtCore.Qt.TextAlignmentRole:
return QtCore.Qt.AlignCenter
elif role == QtCore.Qt.ToolTipRole:
return item.name
elif role == QtCore.Qt.DisplayRole:
return item.name
class SortedModel(QtGui.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
super(SortedModel, self).__init__(*args, **kwargs)
self._patterns = {}
def set_pattern(self, role, value):
self._patterns[role] = value
def filterAcceptsRow(self, sourceRow, sourceParent):
sm = self.sourceModel()
ix = sm.index(sourceRow)
if ix.isValid():
val = True
for role, fvalue in self._patterns.items():
value = ix.data(role)
val = val and self.filter(value, fvalue, role)
return val
return False
@staticmethod
def filter(value, fvalue, role):
'''
fvalue: search value
value: properties value being tested
'''
if role == AssetModel.NameRole:
if fvalue == []:
return True
else:
# change all to any for expanded search
return all(any(x in y for y in value) for x in fvalue)
else:
return False
class ShopWidget(QtWidgets.QWidget):
def __init__(self,parent=None, path=None):
super(ShopWidget, self).__init__(parent)
self.TITLE = 'Shop'
self.VERSION = '1.0.0' # MAJOR.MINOR.PATCH
self.setWindowTitle(self.TITLE + ' | ' + self.VERSION)
self.resize(1000,700)
# properties
self.path = path
# controls
self.ui_search_bar = QtWidgets.QLineEdit()
self.ui_search_bar.setPlaceholderText('Search...')
self.ui_asset_list = QtWidgets.QListView()
self.ui_asset_list.setViewMode(QtWidgets.QListView.IconMode)
self.ui_asset_list.setResizeMode(QtWidgets.QListView.Adjust)
self.ui_asset_list.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.ui_asset_list.setIconSize(QtCore.QSize(256, 256))
self.ui_asset_list.setMovement(QtWidgets.QListView.Static)
self.ui_asset_list.setSpacing(10)
self.ui_asset_list.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.ui_asset_selection_model = self.ui_asset_list.selectionModel()
self.ui_asset_list.setIconSize(QtCore.QSize(128,128))
self.sorted_model = SortedModel()
self.sorted_model.setSourceModel(AssetModel())
self.ui_asset_list.setModel(self.sorted_model)
# layout
search_layout = QtWidgets.QHBoxLayout()
search_layout.addWidget(self.ui_search_bar)
main_layout = QtWidgets.QVBoxLayout()
main_layout.addLayout(search_layout)
main_layout.addWidget(self.ui_asset_list)
self.setLayout(main_layout)
# connections
self.ui_search_bar.textChanged.connect(self.search_value_changed)
self.ui_search_bar.keyPressEvent = self.search_bar_key_event
self.ui_asset_list.doubleClicked.connect(self.on_item_double_clicked)
# constructor
self.path = path
self.populate_asset_list()
# methods
def populate_asset_list(self):
extensions = ['.jpg']
directory = self.path
if not os.path.isdir(directory):
return
for root, subdirs, files in os.walk(directory):
for f in files:
filepath = os.path.join(root, f)
if not os.path.isfile(filepath):
continue
if not os.path.splitext(filepath)[-1] in extensions:
continue
self.ui_asset_list.model().sourceModel().addItem(AssetItem(filepath))
def search_bar_key_event(self, event):
if event.key() == QtCore.Qt.Key_Escape:
self.ui_search_bar.clear()
QtWidgets.QLineEdit.keyPressEvent(self.ui_search_bar, event)
def search_value_changed(self, text):
filters = filter(None, text.lower().split(' '))
model = self.ui_asset_list.model()
model.set_pattern(AssetModel.NameRole, filters)
model.invalidateFilter()
def import_assets(self):
selection = self.ui_asset_list.selectionModel().selectedRows()
assets = self.ui_asset_list.model().sourceModel().getSelectedItems(selection)
for x in assets:
print x.name
# actions
def on_item_double_clicked(self, index):
self.import_assets()
# Main
# -----------------------------------------------------------------------------
def main():
app = QtWidgets.QApplication(sys.argv)
ex = ShopWidget(path='C:/Users/jmartini/Desktop/Temp/images')
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
答案 0 :(得分:1)
当使用方法selectionModel().selectedRows()
选择QModelIndex时,这将返回关于为视图建立的模型的索引,在您的情况下为SortedModel
,但如果您想获取项目,必须有QModelIndex
属于AssetModel
,即属于源模型,为此您必须使用代理模型的mapToSource
:
def import_assets(self):
selection = self.ui_asset_list.selectionModel().selectedRows()
selection_x = [self.ui_asset_list.model().mapToSource(index) for index in selection]
assets = self.ui_asset_list.model().sourceModel().getSelectedItems(selection_x)
for x in assets:
print(x.name)