探索QTableWidget对单元格(QWidget/QTableWidgetItem)的内存管理[clearContents()]

简介: 1.clearContents() 会清除表格中的所有单元格内容,包括释放之前创建的QTableWidgetItem和通过 setCellWidget() 设置的 QWidget 对象,但是不指向nullptr并且是延时释放QWidget 的而QTableWidgetItem 立即释放;2.使用 setItem 方法将一个 QTableWidgetItem 对象设置为表格中的一个单元格后,该对象的位置(即所在行的索引)不会改变。这意味着,如果之后将该对象设置为其他单元格,它的位置将保持不变;3.而使用 setCellWidget 方法将一个QWidget对象设置单元格时,位置可能会改变

现象

memory.gif

结论

  1. clearContents() 会清除表格中的所有单元格内容,包括释放之前创建的 QTableWidgetItem 和通过 setCellWidget() 设置的 QWidget 对象,但是不指向nullptr并且是延时释放QWidget 的而QTableWidgetItem 立即释放;
  2. 使用 setItem 方法将一个 QTableWidgetItem 对象设置为表格中的一个单元格后,该对象的位置(即所在行的索引)不会改变。这意味着,如果之后将该对象设置为其他单元格,它的位置将保持不变;
原因:QTableWidgetItem 对象是动态地与表格的行和列关联的。当使用 setItem 方法将一个 QTableWidgetItem 对象设置为某个单元格时,该对象的位置将保持不变,因为它是与该单元格关联的
  1. 而使用 setCellWidget 方法将一个 QWidget 对象设置为表格中的一个单元格时,该对象的位置可能会改变;
原因: QWidget 对象不是直接与表格的行和列关联的,而是与 QTableWidget 对象本身关联的。
  • 总的来说:

QTableWidgetItem 对象与表格的行和列关联,而 QWidget 对象与整个表格本身关联。因此,当更改单元格中的 QTableWidgetItem 对象时,该对象的位置将保持不变;而当更改单元格中的 QWidget 对象时,该对象的位置将根据设置的单元格位置而改变。

  • 官方开发文档

image.png

代码验证clearContents() 会释放QTableWidgetItem 和QWidget 对象,但是不指向nullptr

memorytable.h


#ifndef MEMORYTABLE_H
#define MEMORYTABLE_H

#include <QWidget>
#include <QCheckBox>
#include <QTableWidgetItem>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class MemoryTable; }
QT_END_NAMESPACE

class MemoryTable : public QWidget

{
    Q_OBJECT

public:
    MemoryTable(QWidget *parent = nullptr);
    ~MemoryTable();

private slots:
    void on_btnAdd_clicked();

    void on_btnClear_clicked();

private:
    Ui::MemoryTable *ui;
    QCheckBox*m_pQCheckBox=nullptr;
    QTableWidgetItem *m_pItem=nullptr;
};

#endif // MEMORYTABLE_H

memorytable.cpp


#include "memorytable.h"
#include "ui_memorytable.h"
#pragma execution_character_set("utf-8")

MemoryTable::MemoryTable(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MemoryTable)
{
    ui->setupUi(this);
    this->setWindowFlag(Qt::WindowStaysOnTopHint);
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(
        QHeaderView::Stretch);

}

MemoryTable::~MemoryTable()
{
    delete ui;
}



void MemoryTable::on_btnAdd_clicked()
{
    if(m_pQCheckBox==nullptr){
        m_pQCheckBox=new QCheckBox();
        m_pQCheckBox->setCheckState(Qt::Checked);
    }
    if(m_pItem==nullptr){
        m_pItem=new QTableWidgetItem();
        m_pItem->setText("QTableWidgetItem 不为空");
    }

    auto state =m_pQCheckBox->checkState();

    QString text =m_pItem->text();

    int rowCount=ui->tableWidget->rowCount();
    ui->tableWidget->insertRow(rowCount);

    ui->tableWidget->setCellWidget(rowCount,0,m_pQCheckBox);
    ui->tableWidget->setItem(rowCount,1,m_pItem);

    int curRow =m_pItem->row();  //curRow 一直
}


void MemoryTable::on_btnClear_clicked()
{
    ui->tableWidget->clearContents();

    //ui->tableWidget->setRowCount(0);
}

断点情况

image.png

验证clearContents()是延时释放QWidget 的而QTableWidgetItem 立即释放

  • 直接在clearContents() 后加上delete m_pQCheckBox不报错(重复删除(delete)同一个指针是不允许的)
  • 而 delete m_pItem或者访问m_pItem就会崩溃;(打断点/qDebug()就知道崩溃点了)
void MemoryTable::on_btnClear_clicked()
{
    ui->tableWidget->clearContents();
    
    auto state =m_pQCheckBox->checkState();    //不会崩溃
    qDebug()<<"state"<<state;
    delete m_pQCheckBox;                    //不会崩溃
    m_pQCheckBox = nullptr;
    
    QString text =m_pItem->text();            //会崩溃
    //ui->tableWidget->setRowCount(0);
}
相关文章
|
JavaScript
Qt视频播放器[QMediaPlayer+QVideowidget]
本代码在Window10下运行,利用qMediaPlayer和qvideowidget实现视频文件mp4的播放,并且提供进度显示,还可以通过拖动进度条来变换播放位置
1766 0
|
编解码 Linux 编译器
使用 C++ 方式实现 GBK 到 UTF-8 转码 (win / linux)
使用 C++ 的方式处理在 Windows 平台和 Linux 平台,编码字符集从 GBK 到 UTF-8 转码,C++ 存在多种方式实现
4943 1
Qt提升控件类为自定义类
Qt提升控件类为自定义类
733 0
|
关系型数据库 MySQL Linux
Qt连接Mysql出现问题(一):“Driver not loaded Driver not loaded“
第一眼看见这张图我也觉得很奇怪,显示有QMYSQL但是又说没有,这不自相矛盾吗!
3553 4
|
Linux 开发者 iOS开发
QT:基于QMediaPlayer制作的视频播放器(最下方有整合包,可直接运行)
QMediaPlayer是Qt多媒体模块中的一个核心类,它提供了播放音频和视频内容的功能。这个类的设计旨在简化跨平台的媒体播放,使得开发者能够在多种操作系统(如Linux、Windows、macOS及移动平台)上轻松集成多媒体播放能力到他们的应用中,而无需关心底层实现细节。以下是关于QMediaPlayer的一些关键点:
2144 1
|
数据库 数据库管理
qt对sqlite数据库多线程的操作
本文总结了在Qt中进行SQLite数据库多线程操作时应注意的四个关键问题,包括数据库驱动加载、加锁、数据库的打开与关闭,以及QsqlQuery变量的使用。
1196 1
【Qt 学习笔记】Qt常用控件 | 布局管理器 | 水平布局Horizontal Layout
【Qt 学习笔记】Qt常用控件 | 布局管理器 | 水平布局Horizontal Layout
1456 2
(5)Qt中的日期和时间
本文介绍了Qt中处理日期和时间的类QDate、QTime和QDateTime,包括它们的格式化选项、构造函数、公共成员函数以及如何进行日期和时间的增减、比较,同时提到了QElapsedTimer作为QTime的替代品用于计时。
1288 0
|
机器学习/深度学习 人工智能 语音技术
QT界面中实现视频帧显示的多种方法及应用(三)
QT界面中实现视频帧显示的多种方法及应用
1591 0
【Qt 学习笔记】Qt窗口 | 标准对话框 | 文件对话框QFileDialog
【Qt 学习笔记】Qt窗口 | 标准对话框 | 文件对话框QFileDialog
4310 4