我在 Python 3.9.6 上使用 PyQt6 6.1.0,我想获取 QTreeWidgetItem 的父 QTreeWidgetItems 的父 QTreeWidget 的父 QMainWindow,因为我需要从 QTreeWidgetItem 中修改窗口。
完整的代码很长,超过 1800 行,大小超过 60 KiB,当我将它放在一个文件中时,它可以正常工作,但是当放在一个文件中时,它的可读性非常低,并且当拆分为文件时,全局变量可以是很难从类中访问。
基本上我的想法是重复调用.parent()
,直到对象的类名是'MainWindow'。
def getWindow(obj):
window = obj.parent()
while True:
if type(window).__name__ == 'MainWindow':
break
window = window.parent()
return window
我没有直接使用该类,因为该类是在主文件中定义的。
以下是在名为 的文件中定义的两个类groupA.py
:
class TreeNode(QTreeWidgetItem):
def __init__(self, texts):
super().__init__()
self.isSongNode = False
self.setFlags(
FLAG.ItemIsAutoTristate
| FLAG.ItemIsEnabled
| FLAG.ItemIsSelectable
| FLAG.ItemIsUserCheckable
)
self.setCheckState(0, Qt.CheckState.Unchecked)
self.data = dict(zip(fields, texts))
self.song = None
for i in ("title", "album", "artist"):
if i in self.data:
if i == "title":
self.setTextAlignment(0, Qt.AlignmentFlag.AlignLeft)
self.setText(0, self.data["title"])
self.setToolTip(0, self.data["title"])
self.setText(1, self.data["duration"])
self.setText(2, self.data["instrumental"])
self.setText(3, self.data["downloaded"])
self.setText(4, ",".join(self.data["language"]))
self.setText(5, self.data["artistgender"])
for j in range(1, 6):
self.setTextAlignment(j, Qt.AlignmentFlag.AlignCenter)
self.song = song(*[self.data[i] for i in cells])
self.isSongNode = True
else:
self.setText(0, self.data[i])
self.setToolTip(0, self.data[i])
break
def detail(self):
print(self)
print(self.parent())
print(self.parent().parent())
print(self.parent().parent().parent())
window = getWindow(self)
if self.childCount() != 0:
for i in range(self.childCount()):
self.child(i).detail()
else:
if self.song not in detailed_items and self.isSongNode:
widget = SongPage(self.data)
window.detailArea.scrollArea.Layout.addWidget(widget)
widget.autoResize()
detailed_items.append(self.song)
class Tree(QTreeWidget):
def __init__(self):
super().__init__()
self.init()
def init(self):
self.setColumnCount(len(HEADERS))
self.setHeaderLabels(HEADERS)
font = Font(9)
self.setFont(font)
self.header().setFont(font)
self.setColumnWidth(0, 900)
fontRuler = QFontMetrics(font)
for i in range(1, len(HEADERS)):
Width = fontRuler.size(0, HEADERS[i]).width() + 16
self.setColumnWidth(i, Width)
self.setAutoScroll(True)
self.setIndentation(32)
self.setAlternatingRowColors(True)
self.setUniformRowHeights(True)
self.itemClicked.connect(self.onItemClicked)
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
@pyqtSlot(QTreeWidgetItem)
def onItemClicked(self, item):
window = getWindow(self)
nodes = self.findItems(
"", Qt.MatchFlag.MatchContains | Qt.MatchFlag.MatchRecursive
)
for node in nodes:
if (
node.checkState(0) == Qt.CheckState.Unchecked
and node.song in detailed_items
):
i = detailed_items.index(node.song)
detailed_items.remove(node.song)
layoutitem = window.detailArea.scrollArea.Layout.itemAt(i)
widget = layoutitem.widget()
window.detailArea.scrollArea.Layout.removeItem(layoutitem)
window.detailArea.scrollArea.Layout.removeWidget(widget)
elif (
node.childCount() == 0
and node.checkState(0) == Qt.CheckState.Checked
and node.isSongNode
):
node.detail()
if item.childCount() == 0 and item.isSongNode:
if item.song not in detailed_items:
item.detail()
index = detailed_items.index(item.song)
dim_others(window, index)
widget = window.detailArea.scrollArea.Layout.itemAt(index).widget()
QTimer.singleShot(
25, lambda: window.detailArea.scrollArea.ensureWidgetVisible(
widget)
)
widget.highlight()
setButtonsStatus(window)
树是这样填充的:
def add_nodes(tree, cls, data):
indexes.clear()
for artist, albums in data.items():
artist_node = cls([artist])
indexes.add([artist])
for album, songs in albums.items():
album_node = cls([artist, album])
indexes.add([artist, album])
for song in songs:
song_node = cls([artist, album, *song])
indexes.add([artist, album, song[0]])
album_node.addChild(song_node)
artist_node.addChild(album_node)
tree.addTopLevelItem(artist_node)
这是代码执行的开始:
if __name__ == '__main__':
mysql80 = psutil.win_service_get("MySQL80").as_dict()
if mysql80["status"] != "running":
os.system("net start MySQL80")
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(u'Asceteria')
songs = fetchdata()
entries = treefy(songs)
app = QApplication(sys.argv)
app.setStyle("Fusion")
tree = Tree()
add_nodes(tree, TreeNode, entries)
filterArea = FilterArea()
Window = MainWindow()
print(tree)
print(tree.parent())
print(tree.parent().parent())
Window.showMaximized()
app.setWindowIcon(QIcon(ICON))
app.exec()
当我检查任何 QTreeWidgetItem 时,程序崩溃,因为顶级 QTreeWidgetItems 没有父母:
<groupA.Tree object at 0x0000022ABCFE9430>
<PyQt6.QtWidgets.QWidget object at 0x0000022AC10DBAF0>
<__main__.MainWindow object at 0x0000022AC10DBA60>
<groupA.TreeNode object at 0x0000022ABE087EE0>
<groupA.TreeNode object at 0x0000022ABE087E50>
<groupA.TreeNode object at 0x0000022ABE087DC0>
None
Traceback (most recent call last):
File "D:\Asceteria\groupA.py", line 148, in onItemClicked
node.detail()
File "D:\Asceteria\groupA.py", line 90, in detail
window = getWindow(self)
File "D:\Asceteria\functions.py", line 112, in getWindow
window = window.parent()
AttributeError: 'NoneType' object has no attribute 'parent'
我怎样才能解决这个问题?