PyQt5 QTableWidget多列对齐触发Python has stopped working报错
问题根因
- 文本垂直靠上:你覆写
initStyleOption时直接将displayAlignment赋值为Qt.AlignRight,直接覆盖了原有属性里的垂直对齐配置,默认的垂直居中属性丢失,所以只有水平右对齐生效,垂直方向变为默认的顶部对齐。 - 程序崩溃:属于PyQt对象生命周期管理的常见问题,你在循环中创建的
AlignRightDelegate是临时对象,没有被Python层持有引用,执行完setItemDelegateForColumn后会被Python垃圾回收,Qt层面仍持有已销毁对象的指针,后续访问触发野指针崩溃。单列时未触发属于巧合,多列创建多个临时对象时GC触发概率大幅提升,所以必现崩溃,不属于PyQt的Bug。
修正方案
修改两处代码即可:
- 对齐属性设置时保留垂直居中,或者显式指定垂直对齐
- 将创建的delegate实例存到表格的实例属性中,避免被GC回收
修正后完整代码
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 = (option.displayAlignment & ~Qt.AlignHorizontal_Mask) | Qt.AlignRight | Qt.AlignVCenter class Table(QTableWidget): def __init__(self, data, alignColumns = 1, *args): QTableWidget.__init__(self, *args) self.setRowCount(len(data)) self.setColumnCount(3) # 新增列表持有delegate实例,避免被GC回收 self.align_delegates = [] self.setData(data) self.resizeColumnsToContents() for colIndex in range(1, 1 + alignColumns): print("Align Column [", colIndex, "]", sep="") delegate = AlignRightDelegate() self.align_delegates.append(delegate) self.setItemDelegateForColumn(colIndex, delegate) 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_())
替代方案(无需自定义Delegate)
如果不需要统一控制整列的后续动态新增内容,可以直接在创建QTableWidgetItem时指定对齐属性,写法更简单,也不会有生命周期问题:
# 修改setData方法里的item创建逻辑 item = QTableWidgetItem(cellContent) item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) self.setItem(m - 1, n, item)
内容的提问来源于stack exchange,提问作者mak
相关产品推荐
相关产品推荐

