两次实例化 QStyledItemDelegate 的子类时出现“Python 已停止工作”错误
Posted
技术标签:
【中文标题】两次实例化 QStyledItemDelegate 的子类时出现“Python 已停止工作”错误【英文标题】:"Python has stopped working" error when instantiating subclass of QStyledItemDelegate twice 【发布时间】:2021-09-24 13:26:36 【问题描述】:我有以下代码来对齐 QTableWidget 列的文本。
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QTableWidget, QTableWidgetItem, QStyledItemDelegate
class AlignRightDelegate(QStyledItemDelegate):
def initStyleOption(self, option, index):
super(AlignRightDelegate, self).initStyleOption(option, index)
option.displayAlignment = Qt.AlignRight
class Table(QTableWidget):
def __init__(self, data, alignColumns = 1, *args):
QTableWidget.__init__(self, *args)
self.setRowCount(len(data))
self.setColumnCount(3)
self.setData(data)
self.resizeColumnsToContents()
for colIndex in range(1, 1 + alignColumns):
print("Align Column [", colIndex, "]", sep="")
self.setItemDelegateForColumn(colIndex, AlignRightDelegate())
def setData(self, data):
horizontalHeaders = []
for m, rowContent in enumerate(data):
for n, cellContent in enumerate(data[m]):
if (m == 0):
horizontalHeaders.append(cellContent)
else:
self.setItem(m - 1, n, QTableWidgetItem(cellContent))
self.setHorizontalHeaderLabels(horizontalHeaders)
if __name__ == "__main__":
data = [["col1", "col2", "col3"],
[ "1", "1", "a"],
[ "-1", "2", "b"],
[ "0", "3", "c"]]
print("python QTableWidgetAlignRight.py[ <AlignColumnCount=1]")
app = QApplication(sys.argv)
table = Table(data, int(sys.argv[1])) if (len(sys.argv) > 1) else Table(data)
table.show()
sys.exit(app.exec_())
如果我使用python QTableWidgetAlignRight.py 1
执行上面的代码,它有点工作,它应该如下所示,col2 与右侧对齐但显然与也顶:
但是,当我使用 python QTableWidgetAlignRight.py 2
执行相同的代码时,我尝试将 2 列向右对齐,我遇到了 Python has stopped working error
。以下截图其实是在我的日文Windows OS(Win 10 Pro 20H2 (OS Build 19402.1165))
但是我在网上搜索了相同的英文错误消息,我发现了一个屏幕截图,尽管不是由于我上面的代码(从这个页面挖掘:Python has stopped working)。
那么对齐我的 QTableWidget 的 2 列的正确方法是什么(没有错误并且没有垂直对齐到顶部)?这也是 PyQt5 中的一个错误吗?
为了您的信息,我正在使用以下内容:Python 3.7.6
、conda 4.8.2
、pyqt 5.9.2 py37h6538335_2
。对于列对齐,我查看了这个以供参考:How to align all items in a column to center in QTableWidget
【问题讨论】:
【参考方案1】:由于 python 和 PyQt 保持对对象的引用的方式,只有 one unparented 和 unreferenced 委托可以理论上为每个视图设置。
但是,虽然可以像这样设置一个委托,但不应该这样做:委托应该始终具有持久引用或有效的父级,因为视图没有 获得委托的所有权(请参阅所有 setItemDelegate*
函数的文档)。
另外,考虑到您对多个列使用相同的委托,创建多个列是没有意义的。
self.alignDelegate = AlignRightDelegate(self)
for colIndex in range(1, 1 + alignColumns):
print("Align Column [", colIndex, "]", sep="")
self.setItemDelegateForColumn(colIndex, self.alignDelegate)
请注意,您可以使用父参数 (self
) 或创建实例属性:
self.alignDelegate = AlignRightDelegate()
# or
alignDelegate = AlignRightDelegate(self)
不过,同时使用这两个不是问题,并且在处理 Qt 对象时指定父对象是一个不错的选择。 在任何情况下,至少应始终使用上述方法之一。
你得到一个错误的对齐方式,因为你只设置了水平对齐方式:使用option.displayAlignment = Qt.AlignRight | Qt.AlignVCenter
。
【讨论】:
第一段有错别字吗?就目前而言,这似乎是矛盾的。 @ekhumoro 也许我应该换个说法:我的意思是在 PyQt 中可以使用未引用的委托实例,但只有一个:只要它试图为相同的创建另一个查看,程序将冻结。因此,虽然它在技术上有效,但不应该这样做。 所以它应该是“一个”而不是“一个”。但是,我仍然认为建议应该始终保持参考 - 特别是当文档声明 Qt 不拥有所有权时。说它“可以”在 PyQt 中完成表明它在某种意义上得到了明确的支持,而不仅仅是一个实现细节。 @ekhumoro 好点,再次。我已经更新了答案,我相信现在应该更清楚了。以上是关于两次实例化 QStyledItemDelegate 的子类时出现“Python 已停止工作”错误的主要内容,如果未能解决你的问题,请参考以下文章