Qt - 在 QTableWidget 中添加一行时出现奇怪的访问冲突

Qt - Strange access violation while adding a row in QTableWidget

我完全是 Qt 的新手,但我需要确定我是否可以使用这个 IDE 来创建专业项目。出于这个原因,我使用 Visual Studio 2019 创建了一个演示项目,并使用提供的 Qt Designer 来设计我的用户界面。

我的演示包含我使用 QTableWidget 对象创建的网格视图,在设计器中配置了 7 列,我可以通过单击 (+) 和 (-) 按钮在其中动态添加和删除单元格。

这是添加和删除单元格的代码:

void MainForm::OnAddClicked()
{
    const int row    = (m_CellCount / 7);
    const int column = (m_CellCount % 7);

    // add a new line if required
    m_UI.twGridView->setRowCount(row + 1);

    QString                 text;
    QFont                   font("Segoe UI", 14);
    QFontMetrics            metrics(font);
    std::unique_ptr<QLabel> pImage(new QLabel());

    switch (m_CellCount % 3)
    {
        case 0:
        {
            text = metrics.elidedText("This is a very very long device name", Qt::ElideRight, m_UI.twGridView->columnWidth(column) - 10);
            pImage->setStyleSheet("image: url(resources/images/Device.png) center center;");
            break;
        }

        case 1:
            text = metrics.elidedText("iPod Shuffle Robbie", Qt::ElideRight, m_UI.twGridView->columnWidth(column) - 10);
            pImage->setStyleSheet("image: url(resources/images/Shuffle.png) center center;");
            break;

        case 2:
            text = metrics.elidedText("iPad Robbie", Qt::ElideRight, m_UI.twGridView->columnWidth(column) - 10);
            pImage->setStyleSheet("image: url(resources/images/iPad.png) center center;");
            break;
    }

    std::unique_ptr<QLabel> pLabel(new QLabel(text));
    pLabel->setFixedHeight(20);
    pLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
    pLabel->setFont(font);
    pLabel->setStyleSheet("color: rgb(243, 243, 243);");

    std::unique_ptr<QWidget>     pWidget(new QWidget());
    std::unique_ptr<QVBoxLayout> pLayout(new QVBoxLayout(pWidget.get()));
    pLayout->addSpacing(10);
    pLayout->addWidget(pImage.get());
    pLayout->addSpacing(10);
    pLayout->addWidget(pLabel.get());
    pWidget->setLayout(pLayout.get());
    pWidget->setStyleSheet("background: none;");
    pImage.release();
    pLabel.release();
    pLayout.release();

    m_UI.twGridView->setCellWidget(row, column, pWidget.get());
    pWidget.release();

    ++m_CellCount;
}

void MainForm::OnDelClicked()
{
    if (m_CellCount)
    {
        --m_CellCount;

        const int row    = (m_CellCount / 7);
        const int column = (m_CellCount % 7);

        delete m_UI.twGridView->cellWidget(row, column);
        m_UI.twGridView->setRowCount(!column ? row : row + 1);
    }
    else
    {
        if (m_UI.twGridView->rowCount())
            delete m_UI.twGridView->cellWidget(0, 0);

        m_UI.twGridView->setRowCount(0);
    }
}

此代码在全球范围内运行良好,并且可以完成工作。但是,由于我无法弄清楚的原因,在执行以下行时,我有时会遇到奇怪的访问冲突:

// add a new line if required
m_UI.twGridView->setRowCount(row + 1);

例如,如果我添加 9 个单元格以显示第二行,然后我删除 3 个单元格以删除之前创建的第二行,然后我再次添加 2 个单元格,我在上述行中遇到访问冲突, 而第二行又被添加了。

任何人都可以向我解释我做错了什么吗?

正如@Adversus 上面所说,删除单元格不是一个好主意。将删除行替换为:

m_UI.twGridView->setCellWidget(row, column, NULL);

为我解决了这个问题。

这是更正后的代码:

void MainForm::OnAddClicked()
{
    const int row    = (m_CellCount / 7);
    const int column = (m_CellCount % 7);

    // add a new line if required
    m_UI.twGridView->setRowCount(row + 1);

    QString                 text;
    QFont                   font("Segoe UI", 14);
    QFontMetrics            metrics(font);
    std::unique_ptr<QLabel> pImage(new QLabel());

    switch (m_CellCount % 3)
    {
        case 0:
        {
            text = metrics.elidedText("This is a very very long device name", Qt::ElideRight, m_UI.twGridView->columnWidth(column) - 10);
            pImage->setStyleSheet("image: url(resources/images/Device.png) center center;");
            break;
        }

        case 1:
            text = metrics.elidedText("iPod Shuffle Robbie", Qt::ElideRight, m_UI.twGridView->columnWidth(column) - 10);
            pImage->setStyleSheet("image: url(resources/images/Shuffle.png) center center;");
            break;

        case 2:
            text = metrics.elidedText("iPad Robbie", Qt::ElideRight, m_UI.twGridView->columnWidth(column) - 10);
            pImage->setStyleSheet("image: url(resources/images/iPad.png) center center;");
            break;
    }

    std::unique_ptr<QLabel> pLabel(new QLabel(text));
    pLabel->setFixedHeight(20);
    pLabel->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
    pLabel->setFont(font);
    pLabel->setStyleSheet("color: rgb(243, 243, 243);");

    std::unique_ptr<QWidget>     pWidget(new QWidget());
    std::unique_ptr<QVBoxLayout> pLayout(new QVBoxLayout(pWidget.get()));
    pLayout->addSpacing(10);
    pLayout->addWidget(pImage.get());
    pLayout->addSpacing(10);
    pLayout->addWidget(pLabel.get());
    pWidget->setLayout(pLayout.get());
    pWidget->setStyleSheet("background: none;");
    pImage.release();
    pLabel.release();
    pLayout.release();

    m_UI.twGridView->setCellWidget(row, column, pWidget.get());
    pWidget.release();

    ++m_CellCount;
}

void MainForm::OnDelClicked()
{
    if (m_CellCount)
    {
        --m_CellCount;

        const int row    = (m_CellCount / 7);
        const int column = (m_CellCount % 7);

        //delete m_UI.twGridView->cellWidget(row, column);
        m_UI.twGridView->setCellWidget(row, column, NULL);

        m_UI.twGridView->setRowCount(!column ? row : row + 1);
    }
    else
        m_UI.twGridView->clearContents();
}

非常感谢 Adversus。