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将内存释放,而不是给它设置一个一键释放的属性。所以我又开始了自己琢磨。释放内存可以通过dialog的delete 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);
}
&spm=1001.2101.3001.5002&articleId=115065717&d=1&t=3&u=379492d2e2ca48b68f8792f9cb3de37e)
351

被折叠的 条评论
为什么被折叠?



