如何修复 QTableWidget setText/setCellWidget 在加载 QSettings 时导致崩溃

Posted

技术标签:

【中文标题】如何修复 QTableWidget setText/setCellWidget 在加载 QSettings 时导致崩溃【英文标题】:How to fix QTableWidget setText/setCellWidget causing crash when loading QSettings 【发布时间】:2019-02-06 23:52:17 【问题描述】:

您好,我使用的是QTableWidget,并且基本上有这样的代码,第一列将允许表格动态增长/收缩。最后填充的行的第一个单元格将有一个加号按钮以添加一个可以编辑的新行,减号按钮将删除其相应按钮的行。例如,如果我单击加号按钮 5 次,它将位于第 6 行,而前 5 行都将有一个减号按钮来删除它们的行。如果单元格的行上有一个减号按钮,则该行隐含可编辑,否则不可编辑。但是,我允许表具有默认的行数,例如,即使它在技术上是“空的”,它在视觉上永远不会缩小到 5 以下。要编辑行,您需要点击加号按钮,该按钮将检查我们是否需要插入新行,例如,如果我们有 5 行并且基本行大小为 5,那么我们需要一个新行并填充新行的每一列的索引。

这个表的主要原因是读取和写入表的信息到QSettings,并且能够将过去导出的信息导入到相同的单元格中,并且基本上恢复了表最后出现的状态。但是,当从QSettings 读取数据时,表格将在所有单元格都正确填充信息后崩溃,我可以告诉它们已正确填充,因为调试器将冻结 GUI,我可以直观地看到 qDebug() 到多远QSettings 数组的循环我在 seg-faulting 之前得到的。

现在,当我手动执行所有操作(例如单击加号按钮)时,一切正常,程序按预期执行。

//newRowCount is assumed to be the amount of rows with Minus Buttons currently, only creates a new row if the table needs to expand
void TableTest::enableNewRow()
    newRowCount++;
    if(newRowCount > table->rowCount())
        table->insertRow(table->rowCount());
        for(int i = 0; i < table->columnSize(); ++i)
            QTableWidgetItem* item = new QTableWidgetItem;
            item->setFlags(item->flags() ^ Qt::ItemisEditable);
            table->setItem(newRowCount, i, item);
            //Code to set the previous column's item (newRowCount--) to have an Qt::ItemisEditable flag set to true
            ...
        
    
        //Some button setup to make Plus button and create a new Minus button connect and do their jobs and move the Plus button down into the newly inserted row
        ...

void MainWindow::importFile()
    int settingRows = settings->beginReadArray("Groups");
    for(int i = 0; i < settingRows; ++i)
        settings->setArrayIndex(i);
        //Will only add a new row if needed, check inside above function and all row items will be allocated if made
        table->enableRow();
        for(int j = 1; j < table->columnCount(); ++j)
            table->item(i, j)->setText("testing");
        
    


And the program crashes with the following stack trace:
1  QWidget::show()
2  QAbstractItemView::updateEditorGeometries()
3  QAbstractItemView::updateGeometries()
4  QTableView::updateGeometries()
5  QTableView::timerEvent(QTimerEvent *)
6  QObject::event(QEvent *)
7  QWidget::event(QEvent *)
8  QFrame::event(QEvent* )
9  QAbstractScrollArea::event(QEvent* )
10 QAbstractItemView::event(QEvent* )
11-21 ... Not useful information about any of the code
22 QCoreApplication::exec()
23 main

但是,这都是字节码,我实际上无法使用调试器检查哪一行导致任何跟踪中的代码崩溃。我不明白的是,手动单击加号按钮的相同过程正在完成(我将加号按钮的单击事件连接到enableRow() 函数)以及当我以编程方式从QSettings 调用enableRow() 时在importFile() 中循环,它会在遍历所有项目后崩溃。

注意事项:将表格的基本大小设置为我正在读取的 QSettings 数组的大小(即,如果我想要 10 行,只需在设置项目文本之前设置 10 行即可正常工作) ,但是,我希望创建时表的基本大小类似于 5。似乎一旦循环超出了我从构造函数中指定的行数,程序就会崩溃,但不是说索引 6,而是只有在它完全循环通过表之后。它不会在QTableWidgetItem::setTextQTableWidget::setCellWidget() 等任何行上崩溃。我有点困惑,想知道对于堆栈跟踪第 5 行上的 QTableWidget::timerEvent,表格是否填充得太快。我在循环中所做的一切都与我在正常操作表格时所做的有任何不同。

【问题讨论】:

【参考方案1】:

事实证明,错误在于我将QTableWIdgetItem 设置得比我应该设置的早一排。我不确定为什么该表能够在崩溃之前迭代直到 QSettings 循环结束,但这本质上是错误。我不太清楚为什么堆栈跟踪如此神秘。

在我的 enableRow() 函数中,我实际上在上面从内存中发布了正确的逻辑,这在我的代码逻辑中与之前行值的 1 个索引不同。为什么代码在正常使用其插槽调用与import() 相同功能的按钮时没有崩溃,这让我感到困惑,也许是未定义行为的情况。

【讨论】:

以上是关于如何修复 QTableWidget setText/setCellWidget 在加载 QSettings 时导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如何修复翻译无法使用TextView.setText()?

Qt与Qtablewidget中headeritem的Python大小

如何更改水平标题的高度(QTableWidget)

我如何获得 QTableWidget 的委托?

如何将数据发送到 QTableView/QTableWidget (PyQt)

如何让 QTableWidget 的列占据最大空间?