您好我正在为有孩子的对象创建一个对话框,一个带有QlineEdit的QTreeview用于过滤。当对话框最初出现时,它看起来像(1号)
代码如下所示。我只用重要的位来总结它
#These are global so can be referenced from any function. and all set
#when i initialise my diaglog.
model=QtGui.QStandardItemModel()
treeview=QtGui.QTreeview()
proxymodel=QtGui.QSortFilterProxyModel(treeview)
treeview.setmodel(proxymodel)
proxymodel.setSourceModel(model)
def initialise_treeview(self):
#This builds the treeview with a list of root nodes only
root_nodes=["Apple","Ardvark","Ankle","Bee","Bark","Bar","Carrot"]# a list of root nodes
for objects in root_nodes:
item=QtGui.QStandardItem(objects)
model.appendRow(item)
No.2显示当用户键入LineEdit文本框
时要过滤的树视图#When a user types into the search field the Treeview gets filtered via the proxymodel
QtCore.QObject.connect(LineEdit,QtCore.Signal("TextChanged(QString)")),update_filter)
def update_filter(self,text):
#filter the model based on the text in the qlineedit
proxymodel.setFilterRegExp(LineEdit.text());
用户选择树视图中的项目(3号,选择了栏)。代码应该获取所有选定项目子项,将它们添加到模型中,最后展开所选节点以显示所有子项目(No.4)
#update_treeview function is called to add children to the selected item
QtCore.QObject.connect(treeview.selectionModel(),QtCore.Signal("currentChanged(QModelIndex,QmodelIndex)")),update_treeview)
def update_treeview(self,currentindex,previousindex):
sourcemodel_index=proxymodel.mapToSource(currentindex)
parent_item=QtGui.QStandardItem()
#get the item from the source model
parent_item=model.itemFromIndex(sourcemodel_index)
for childitem in list_of_children:
file_item=QtGui.QStandardItem(str(childitem))
model.appendRow(file_item)
treeview.expand(currentindex) #this doesn't work when proxymodel has been filtered
到目前为止,我的大部分工作都在进行中。实际上所有这一切。除了树视图的扩展,当有一些过滤时。
我在没有应用过滤器的情况下工作了,但是一旦树形视图的列表被过滤,它就会被击中并失败,即树视图并不总是在右边节点展开。
如何确保树视图在正确的索引处展开,以便在筛选文件夹列表并将文件添加到筛选列表时。如何确保将树视图扩展到正确的位置。我在Windows上使用python 2.7,Qt 4.8。
答案 0 :(得分:2)
问题不是它没有扩展,而是它受QSortProxyModel过滤器的影响,过滤器应该只应用于topLevels。我已经使用了一个新角色,如果你已经拥有它们,就不会添加更多的孩子,我也认为点击的信号最适合这种情况。
from PyQt4.QtCore import *
from PyQt4.QtGui import *
HaveChildrenRole = Qt.UserRole
class SortFilterProxyModel(QSortFilterProxyModel):
def filterAcceptsRow(self, source_row, source_parent):
ix = self.sourceModel().index(source_row, 0, source_parent)
if not ix.parent().isValid(): # check if the item has no parent
return QSortFilterProxyModel.filterAcceptsRow(self, source_row, source_parent)
else: # as it has a parent, the filter does not apply
return True
class Widget(QWidget):
def __init__(self, *args, **kwargs):
QWidget.__init__(self, *args, **kwargs)
self.setLayout(QVBoxLayout())
self.treeView = QTreeView(self)
self.le = QLineEdit(self)
self.layout().addWidget(self.treeView)
self.layout().addWidget(self.le)
self.model = QStandardItemModel(self)
self.proxy = SortFilterProxyModel(self)
self.proxy.setSourceModel(self.model)
self.treeView.setModel(self.proxy)
self.initialise_treeview()
self.le.textChanged.connect(self.update_filter)
self.treeView.clicked.connect(self.onClicked)
def initialise_treeview(self):
root_nodes = ["Apple", "Ardvark", "Ankle", "Bee", "Bark", "Bar", "Carrot"] # a list of root nodes
for obj in root_nodes:
item = QStandardItem(obj)
item.setData(False, HaveChildrenRole)
self.model.appendRow(item)
def update_filter(self, text):
self.proxy.setFilterRegExp(text)
def onClicked(self, ix):
s_ix = self.proxy.mapToSource(ix)
it = self.model.itemFromIndex(s_ix)
if not it.data(HaveChildrenRole) and it.parent() is None:
for children in ["A", "B", "C", "D"]:
it.appendRow(QStandardItem(children))
it.setData(True, HaveChildrenRole)
self.treeView.expand(ix)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
<强>解释强>
filterAcceptsRow
方法决定是否显示该行,在您的情况下,应该对topLevel做出决定&#34; Apple&#34;,&#34; Bee&#34;,所以首先要确定那些项目,主要特征是它们没有父项,所以我们访问parent()
如果它是有效的,它有一个父项,如果它不是topLevel,那么方法必须通过过滤器,然后我们返回True,以便它们可见。