Issue
How to select this element in Qtreewidget using the path to an element?
The path is written as an example string: parent/parent/parent/parent/element
It is important to search for elements along the entire path and not only by the name of this element, because there may be many elements in the tree with the same name, but each one will certainly have a different path.
I tried to solve it in ten ways:
def find_and_select_item(self):
path = self.comboBox_Scene.currentText()
path_elements = path.split('/')
current_item = self.treeWidget.invisibleRootItem()
for element in path_elements:
items = self.treeWidget.findItems(element, Qt.MatchFlag, 0)
if items:
current_item = items[0]
else:
# Element not found in the current level of the tree
return None
# Select the found item
current_item.setSelected(True)
return current_item
Unfortunately, this function returns an error::
TypeError: findItems(self, text: str, flags: Qt.MatchFlag, column: int = 0): argument 2 has unexpected type 'EnumType'
Solution
This is most easily implemented using recursion, which can provide a more general solution that is capable of finding multiple matching pathways in the tree (if necessary).
Below is a basic working demo that shows how to achieve this. Since the question states that each element has a different path, this demo only looks for the first matching item. However, the searchByPath
method returns a generator that can iterate over all matches if necessary (and it can also start searching from any point in the tree).
from PyQt6 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.button = QtWidgets.QPushButton('Test')
self.button.clicked.connect(self.handleButton)
self.edit = QtWidgets.QLineEdit()
self.tree = QtWidgets.QTreeWidget()
self.tree.setHeaderHidden(True)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.tree)
layout.addWidget(self.edit)
layout.addWidget(self.button)
for text in ('Red', 'Blue', 'Green'):
level0 = QtWidgets.QTreeWidgetItem(self.tree, [text])
for text in ('Cyan', 'Violet', 'Yellow'):
level1 = QtWidgets.QTreeWidgetItem(level0, [text])
for text in ('Orange', 'Brown', 'Purple'):
level2 = QtWidgets.QTreeWidgetItem(level1, [text])
for text in ('Gold', 'Silver', 'Bronze'):
level3 = QtWidgets.QTreeWidgetItem(level2, [text])
self.edit.setText('Green/Violet/Orange/Bronze')
def handleButton(self):
self.tree.clearSelection()
self.tree.collapseAll()
path = self.edit.text()
if path:
item = next(self.searchByPath(path), None)
if item is not None:
self.tree.scrollToItem(item)
item.setSelected(True)
def searchByPath(self, path, root=None):
if root is None:
root = self.tree.invisibleRootItem()
elements = list(map(str.strip, path.split('/')))
last = len(elements) - 1
def search(parent, level=0):
if level <= last:
target = elements[level]
for index in range(parent.childCount()):
child = parent.child(index)
if child.text(0) != target:
continue
if level == last:
yield child
else:
yield from search(child, level + 1)
return search(root)
if __name__ == '__main__':
app = QtWidgets.QApplication(['Test'])
window = Window()
window.setGeometry(600, 100, 300, 300)
window.show()
app.exec()
Answered By - ekhumoro
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.