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

现象

在这里插入图片描述

结论

  1. clearContents() 会清除表格中的所有单元格内容,包括释放之前创建的QTableWidgetItem和通过 setCellWidget() 设置的 QWidget 对象,但是不指向nullptr并且是延时释放QWidget 的而QTableWidgetItem 立即释放;

  2. 使用 setItem 方法将一个 QTableWidgetItem 对象设置为表格中的一个单元格后,该对象的位置(即所在行的索引)不会改变。这意味着,如果之后将该对象设置为其他单元格,它的位置将保持不变;

原因:QTableWidgetItem 对象是动态地与表格的行和列关联的。当使用 setItem 方法将一个 QTableWidgetItem 对象设置为某个单元格时,该对象的位置将保持不变,因为它是与该单元格关联的

  1. 而使用 setCellWidget 方法将一个QWidget对象设置为表格中的一个单元格时,该对象的位置可能会改变;

原因: QWidget 对象不是直接与表格的行和列关联的,而是与 QTableWidget 对象本身关联的。

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

代码验证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);
}

断点情况

clearContents()清空再执行添加

验证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);
}
### PyQt QTableWidget UI 设计 示例教程 #### 1. QTableWidget 基本概念 `QTableWidget` 是 PyQt 提供的一个用于展示表格数据的组件,它允许开发者通过编程方式创建具有交互性的表格界面。该控件支持多种自定义操作,比如设置单元格内容、嵌入其他控件以及动态调整布局等[^1]。 以下是 `QTableWidget` 的基本属性和方法概述: - **列数与行数管理**: 使用 `setRowCount()` 和 `setColumnCount()` 方法来设定表格的行列数量。 - **单元格内容填充**: 可以通过 `setItem(row, column, QTableWidgetItem)` 来向指定位置插入文本型单元格项。 - **嵌套控件**: 支持在特定单元格中放置按钮、下拉框或其他复杂的小部件,这可以通过 `setCellWidget(row, column, widget)` 完成。 #### 2. 创建基础 QTableWidget 表格 下面是一段简单的代码示例,演示如何初始化一个带有固定行列结构的基础表格: ```python from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidget, QTableWidgetItem class MainWindow(QMainWindow): def __init__(self): super().__init__() self.table = QTableWidget(4, 3) # 设置初始行为4,列为3 self.setCentralWidget(self.table) # 添加一些示例行数据到表单里 for row in range(4): for col in range(3): item = QTableWidgetItem(f"Item {row},{col}") self.table.setItem(row, col, item) app = QApplication([]) window = MainWindow() window.show() app.exec_() ``` 这段程序展示了如何构建并填充一个小型静态表格,其中每一单元都被赋予了一个字符串形式的内容标记其坐标位置。 #### 3. 高级特性——嵌入额外控件至单元格 除了纯文字外,在某些场景下我们还希望能在表格内部加入更多互动性强的小工具,例如复选框或者组合列表。这里给出一段示范代码说明这一过程: ```python from PyQt5.QtWidgets import QPushButton, QLineEdit, QVBoxLayout, QWidget def add_widgets_to_cells(): button_widget = QPushButton('Click Me') line_edit_widget = QLineEdit() table.setCellWidget(0, 0, button_widget) table.setCellWidget(1, 1, line_edit_widget) add_widgets_to_cells() ``` 上述片段实现了将按钮和输入框分别置入不同单元的操作。值得注意的是当采用这种方式时需注意大小适配问题以免破坏整体视觉效果。 #### 4. 大量数据处理下的分页解决方案 对于包含大量条目的情况来说,一次性加载全部记录可能会造成性能瓶颈甚至崩溃风险;因此引入分页机制变得尤为重要。具体做法如下所示: ```python class PaginatedTable(QWidget): def __init__(self, data_list): super().__init__() layout = QVBoxLayout() self.setLayout(layout) self.data = data_list self.page_size = 10 self.current_page = 0 self.total_pages = (len(data_list)-1)//self.page_size +1 self.table = QTableWidget(self.page_size, len(data_list[0])) layout.addWidget(self.table) prev_button = QPushButton("Previous") next_button = QPushButton("Next") buttons_layout = QHBoxLayout() buttons_layout.addWidget(prev_button) buttons_layout.addWidget(next_button) layout.addLayout(buttons_layout) prev_button.clicked.connect(lambda:self.changePage(-1)) next_button.clicked.connect(lambda:self.changePage(+1)) self.update_table_content() def changePage(self,direction): new_page=self.current_page+direction if(new_page>=0 and new_page<self.total_pages): self.current_page=new_page self.update_table_content() def update_table_content(self): start_index= self.current_page * self.page_size end_index=min((start_index+self.page_size),len(self.data)) rows=[list(item.values())for item in self.data[start_index:end_index]] self.table.clearContents() for i,row_data in enumerate(rows): for j,value in enumerate(row_data): cell_item=QTableWidgetItem(str(value)) self.table.setItem(i,j,cell_item) data=[ {"Name":"Alice","Age":28,"City":"New York"}, {"Name":"Bob", "Age":22,"City":"Los Angeles"} ] app = QApplication([]) widget = PaginatedTable(data*100) # Simulate large dataset by repeating small one. widget.resize(640,480) widget.show() app.exec_() ``` 此部分提供了完整的分页逻辑实现方案,包括前后翻页控制及对应的数据更新函数[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值