C++ Qt (释放界面类内存,让控件一直处于变化状态)

1、关闭时界面类时,自动释放内存:

通过以下代码,点击按钮调起界面类。运行结果是:界面类显示,200ms后隐藏,200ms后显示。

void MainWindow::on_pushButton_clicked()
{
    Dialog  *dialog1 = new Dialog(this);
    dialog1->show();
    _sleep(200);
    dialog1->close();
    _sleep(200);
    dialog1->show();
}

出现这种现象,是由于close()并不能释放界面类,实际上还在内存中。通过查阅资料发现,close()函数会发送一个close()的信号,然后再执行hide(),所以其本质还是hide。由于指定了它的父类为this,作为child,它会伴随着this存在整个程序运行周期。只有当this被移除时,它才会被跟着移除。

只有一两个界面类的时候还不影响,但是当程序调起的界面类变得很多时,占用的内存也变多,我不想这样,我在它们close时就把它们释放掉。在网上搜索了一下,发现要么是告诉你指定parent就会跟着父控件一起释放。要么就是告诉你设置setAttribute(Qt::WA_DeleteOnClose)来让它close时自动释放内存,虽然这样也可以,但是这我之前就知道了。

这些都不是我想要的,我想自己写一个delete将内存释放,而不是给它设置一个一键释放的属性。所以我又开始了自己琢磨。释放内存可以通过dialogdelete this来释放自身。也可以使用信号的机制来让主界面类来delete,在close的时候发送一个信号,这个信号可以是close()触发的close信号,也可以是我自己定义的信号。主界面类收到信号后,将这个子界面delete掉,也许WA_DeleteOnClose也是这样实现的吧。

(1)close时释放自身内存:

dialog的关闭按钮上添加释放自身内存:

this->close();
delete this;

要注意的是,添加这句后,需要确保dialog都是new实例化出来的,否则会出现delete不存在的内存导致报错。

(2)在dialog的close事件中释放:
#include <QCloseEvent>

protected:
    void closeEvent(QCloseEvent *event);


void QDialog::closeEvent(QCloseEvent *event)
{
    this->deleteLater();
}
(3)使用信号来让主界面来释放:

界面类dialog.h中创建关闭按钮和close的信号:

private slots:
    void on_pushButton_clicked();    //关闭按钮
signals:
    void closeWindowSignal();      //关闭信号

dialog.cpp中:

void Dialog::on_pushButton_clicked()
{
    this->close();
    emit(closeWindowSignal());    //发送close信号
}

//或
void QDialog::closeEvent(QCloseEvent *event)
{
    emit(closeWindowSignal());
}

mainwindow.cpp中:

void MainWindow::on_pushButton_clicked()   //点击 pushButton 显示界面,并绑定释放内存按钮
{
    Dialog  *dialog1 = new Dialog(this);
    dialog1->show();
    //点击 pushbutton_2 释放 dialog1
    connect(pushbutton_2,&QPushButton::clicked, this, [=](){dialog1->deleteLater();dialog1=NULL;});
    }

为了测试,可以在dialog1释放后添加dialog1->show(),发现已经无法显示了,因为内存已经被释放了。

对于有些界面类需要储存上一次用户输入的数据,那一部分的界面类就不需要delete了,也不需要一直初始化,直接放在栈中就可以了。

2、关于一直处于变化状态的控件:

以前写一些脚本,遇到需要反复执行的,比如使用opencv读取相机,怕麻烦的话,可能就直接while(1)循环读取了。但是如果在有UI界面的程序或是有其他触发式功能的程序中,使用while(1)会使程序界面卡死。

比如让界面中的一个label持续下落,肯定不能使用while(1)来让它一直向下移动。参照相机的回调读取图像机制,实现这样的功能的方法需要是回调触发式,而非循环式。

从常用的方法角度来看,三种方法是可取的:

  • 定时器定时任务,每隔一段时间,label向下移动一点。
  • 事件触发式,但这个事件必须是能持续触发的,而非断断续续的。如paint事件,鼠标悬浮事件。
  • 让线程来执行while(1)或定时器,由于无法直接操控主界面,所以可以每隔100毫秒左右发送一个信号,主界面每次接收到一个信号,将label向下移动一点。

基本都离不开线程和信号。

定时器

QTimer *pTimer = new QTimer(this);
connect(pTimer,SIGNAL(timeout()),this,SLOT(moveLabel()));
pTimer->start( 20 );

void MainWindow::moveLabel()
{
    ui->label->move(ui->label->x(),ui->label->y()+10);
}

paint事件
对于 paint 事件,由于触发速度过快,一瞬间 label 就下落的没边了。

void MainWindow::paintEvent(QPaintEvent *event)
{
    ui->label->move(ui->label->x(),ui->label->y()+1);
}

线程触发
注意一定要添加msleep(),否则太过频繁的信号也会使主界面卡死,还有记得关闭线程。

//线程
void Thread1::run()
{
    while(1){
            emit moveLabel1();
            msleep(100);
}}

//mainwindow 
Thread1 *thread1 = new Thread1();
thread1->setParent(this);
thread1->start();
connect(thread1,SIGNAL(moveLabel1()),this,SLOT(moveLabel()));


void MainWindow::moveLabel(){
    ui->label->move(ui->label->x(),ui->label->y()+10);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值