我在Qt中构建了一个应用程序,它包含两个按钮:一个退出按钮和一个导入按钮。当按下导入按钮时,屏幕上的scrollarea会显示一个按钮列表(文件loggers.csv包含数据1、2、3、4、5;)。
这一切都很好,但当我按下退出按钮(当然应该关闭一切),应用程序没有正确停止( Qt的停止按钮仍然是活动的,而play按钮没有)。当我运行调试器并按退出按钮时,它会出现一个错误:指定给RtlFreeHeap的无效地址(0ADF 0000,0028FE40 )。有人能帮我吗?
主
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.showFullScreen();
return a.exec();
}Mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtGui>
#include "logger.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QPushButton exit_btn;
QPushButton import_btn;
private slots:
void createMenus();
void exit();
void import();
private:
int window_width;
int window_height;
int numLoggers;
int numSelected;
QVector<Logger*> loggers;
QScrollArea * scroll_area;
QVBoxLayout scrollLayout;
QWidget viewport;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_HMainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QtGui"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
window_width = QApplication::desktop()->width();
window_height = QApplication::desktop()->height();
createMenus();
connect(&exit_btn,SIGNAL(clicked()),this,SLOT(exit()));
connect(&import_btn,SIGNAL(clicked()),this,SLOT(import()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::createMenus()
{
import_btn.setParent(ui->centralWidget);
import_btn.setGeometry(400,300,100,100);
import_btn.setText("IMPORT");
exit_btn.setText("EXIT");
exit_btn.setParent(ui->centralWidget);
exit_btn.setGeometry(window_width-50,12,32,32);
viewport.setLayout(&scrollLayout);
viewport.resize(0,0);
scroll_area = new QScrollArea(ui->centralWidget);
scroll_area->setGeometry(0,66,317,window_height-116);
scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scroll_area->setWidget(&viewport);
scroll_area->setGeometry(0,97,317,window_height-228);
scrollLayout.setMargin(0);
scrollLayout.setSpacing(0);
}
void MainWindow::exit()
{
close();
qApp->quit();
}
void MainWindow::import()
{
numSelected=0;
QFile f("Loggers3.csv");
if (f.open(QIODevice::ReadOnly))
{
numLoggers=0;
QString data;
data = f.readAll();
QStringList vals = data.split(';');
while(vals.size()>=1)
{
Logger * logger = new Logger;
logger->setNumber(vals[0].toInt());
vals.removeAt(0);
loggers<<logger;
numLoggers++;
}
f.close();
for(int i=0; i<numLoggers;i++)
{
loggers[i]->createButtons();
scrollLayout.addWidget(loggers[i]->button);
}
viewport.resize(367,numLoggers*60);
}
}logger.h
#ifndef LOGGER_H
#define LOGGER_H
#include <QtGui>
class Logger : public QWidget
{
Q_OBJECT
public:
explicit Logger(QWidget *parent = 0);
~Logger();
int number;
QLabel num;
QToolButton * button;
bool checked;
signals:
public slots:
void setNumber(int number);
void createButtons();
};
#endif // LOGGER_Hlogger.cpp
#include "logger.h"
#include <QtGui>
Logger::Logger(QWidget *parent) :
QWidget(parent)
{
button = new QToolButton;
button->setCheckable(true);
button->setMinimumSize(317,60);
button->setStyleSheet("QToolButton{background-image: url(images/btn_bg); border:none}");
}
Logger::~Logger()
{
}
void Logger::setNumber(int logNumber)
{
number=logNumber;
}
void Logger::createButtons()
{
QLayout * layout = new QHBoxLayout;
QSpacerItem *spacer = new QSpacerItem(120, 31, QSizePolicy::Maximum, SizePolicy::Maximum);
num.setStyleSheet("color: white; font: bold 16px");
num.setText(QString::number(number));
layout->addWidget(&num);
layout->addItem(spacer);
button->setLayout(layout);
}发布于 2012-10-01 18:40:01
我不太确定你想要实现什么.但你的问题在于这两条线:
viewport.setLayout(&scrollLayout);
viewport.resize(0,0);在QWidget类的文档中,它声明:
如果这个小部件上已经安装了一个布局管理器,QWidget将不允许您安装另一个。在使用新布局调用setLayout()之前,必须先删除现有的布局管理器(由layout ()返回)。
这就是你的问题所在。别相信我,在这两行代码之前加上这张支票。
if(layout()){
qDebug() << "Another layout exists";
}来源:QVBoxLayout类引用
QVBoxLayout类垂直排列小部件。
此类用于构造垂直框布局对象。详情请参见QBoxLayout。
这个类最简单的用法如下:
QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QPushButton *button4 = new QPushButton("Four");
QPushButton *button5 = new QPushButton("Five");
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);
window->setLayout(layout);
window->show();首先,我们在布局中创建我们想要的小部件。然后,我们创建QVBoxLayout对象并将小部件添加到布局中。最后,我们调用QWidget::setLayout()将QVBoxLayout对象安装到小部件上。此时,布局中的小部件被修改为将窗口作为其父窗口。
项目中的关键错误来源:
应该在堆上构造小部件,因为当它们的父部件被删除时,它们将被自动删除。,您有一个自定义小部件类,可以在堆上实例化它们。成员也应该在堆上。此外,您应该考虑在GUI代码中使用父/child层次结构,以确保正确的内存管理和正确的删除。
发布于 2012-10-02 10:24:54
根据我的经验,如果您的程序停止在RtlFreeHeap中,这是内存损坏的好迹象。
打电话时
import_btn.setParent(ui->centralWidget);centralWidget拥有import_btn的所有权。这意味着,当centralWidget被删除时(在MainWindow的析构函数中作为delete ui;的一部分发生),它将对成员变量调用delete!
这将导致报告的内存损坏。
您需要动态地分配您的QPushButton,而不是作为普通的成员变量。所以让它们成为QPushButton*。
发布于 2014-03-14 09:35:32
这是我是如何从mainwindow.cpp做到这一点的,感谢和这个问题:如何在qt中创建正确的退出按钮
QPushButton * quit_btn = new QPushButton(this);
quit_btn->setGeometry(540,440,93,27);
quit_btn->setText("Exit");
QObject::connect(quit_btn,SIGNAL(clicked()),qApp,SLOT(quit()));作品完美无缺:D
https://stackoverflow.com/questions/12674984
复制相似问题