简体   繁体   English

实例化 QStyledItemDelegate 的子类两次时出现“Python 已停止工作”错误

[英]"Python has stopped working" error when instantiating subclass of QStyledItemDelegate twice

I have the following code to align text of QTableWidget's column.我有以下代码来对齐 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_())

If I execute the above code with python QTableWidgetAlignRight.py 1 it sort of works as it should as shown below with col2 aligned to the right but apparently to the top also :如果我使用python QTableWidgetAlignRight.py 1执行上面的代码,它的工作原理如下所示, col2向右对齐,但显然也向顶部对齐:

作品

However when I execute the same code with python QTableWidgetAlignRight.py 2 where I try to align 2 columns to the right, I ran into Python has stopped working error .但是,当我使用python QTableWidgetAlignRight.py 2执行相同的代码时,我尝试将 2 列向右对齐,我遇到了Python has stopped working error The following screenshot is actually on my Japanese Windows OS (Win 10 Pro 20H2 (OS Build 19402.1165))下面的截图其实是在我的日文 Windows OS (Win 10 Pro 20H2 (OS Build 19402.1165))

不起作用(日语错误消息)

However I searched the.net for the same error message in English and I found a screenshot albeit not due to my code above (burrowed from this page: Python has stopped working ).但是,我在 .net 上搜索了相同的英文错误消息,并找到了一个屏幕截图,尽管不是我上面的代码造成的(从此页面挖出: Python 已停止工作)。

同样的英文错误信息

So what is the correct way of aligning 2 columns of my QTableWidget (without an error and without aligning to the top vertically)?那么对齐我的 QTableWidget 的 2 列的正确方法是什么(没有错误并且没有垂直对齐到顶部)? Also is this a bug in PyQt5?这也是 PyQt5 中的错误吗?

For your information, I am using the following: Python 3.7.6 , conda 4.8.2 , pyqt 5.9.2 py37h6538335_2 .供您参考,我正在使用以下内容: Python 3.7.6conda 4.8.2 pyqt 5.9.2 py37h6538335_2 For column alignment, I looked at this for reference: How to align all items in a column to center in QTableWidget对于列 alignment,我查看了这个以供参考: How to align all items in a column to center in QTableWidget

Due to the way python and PyQt keep references to objects, only one unparented and unreferenced delegate can theoretically be set for each view.由于 python 和 PyQt 保持对对象的引用的方式,理论上每个视图只能设置一个无父级和无引用的委托。

But, while it is possible to set one delegate like this, it should not be done: delegates should always have a persistent reference or valid parent since the view does not take ownership of the delegate (see the docs for all setItemDelegate* functions).但是,虽然可以像这样设置一个委托,但不应该这样做:委托应始终具有持久引用或有效父级,因为视图拥有委托的所有权(请参阅所有setItemDelegate*函数的文档)。

Also, considering that you are using the same delegate for multiple columns, there's no point in creating more than one.此外,考虑到您对多个列使用相同的委托,创建多个列没有意义。

    self.alignDelegate = AlignRightDelegate(self)
    for colIndex in range(1, 1 + alignColumns):
        print("Align Column [", colIndex, "]", sep="")
        self.setItemDelegateForColumn(colIndex, self.alignDelegate)

Note that you could either use the parent argument ( self ) or create an instance attribute:请注意,您可以使用父参数 ( self )创建实例属性:

self.alignDelegate = AlignRightDelegate()
# or
alignDelegate = AlignRightDelegate(self)

Using both, though, is not an issue, and specifying the parent is a good choice anyway when dealing with Qt objects.但是,同时使用两者不是问题,并且在处理 Qt 对象时无论如何指定父对象是一个不错的选择。
In any case, at least one of the methods above should always be used.在任何情况下,至少应始终使用上述方法之一。

You get a wrong alignment because you only set the horizontal alignment: use option.displayAlignment = Qt.AlignRight | Qt.AlignVCenter你得到一个错误的 alignment 因为你只设置了水平alignment: use option.displayAlignment = Qt.AlignRight | Qt.AlignVCenter option.displayAlignment = Qt.AlignRight | Qt.AlignVCenter . option.displayAlignment = Qt.AlignRight | Qt.AlignVCenter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM