Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt4] ошибка при закрытии тестовой программки


Автор: anatox91 12.3.2008, 14:27
при первой же моей попытке поэкпериментировать с Qt, наткнулся на ошибку - при нажатии на кнопку Quit вылезает ошибка Windows (типа приложение будет закрыто из-за ошибки, просим извинения за неудобства), а если закрываю обычным красным крестиком то окошко исчезает, но в процессах остается висеть... помогите пожалуйста разобраться, вот код:
Код

#include <QLabel>
#include <QApplication>
#include <QPushButton>
#include <QSpinBox>
#include <QWidget>
#include <QSlider>
#include <QHBoxLayout>
#include <QVBoxLayout>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget window;
    window.setWindowTitle("Age");
    window.setWindowFlags(Qt::Tool);
    QLabel label("Change your age: ");
    QPushButton button("Quit");
    QObject::connect(&button, SIGNAL(clicked()), &app, SLOT(quit()));
    QSpinBox spinbox;
    spinbox.setRange(0, 130);
    QSlider slider(Qt::Horizontal);
    slider.setRange(0, 130);
    QObject::connect(&spinbox, SIGNAL(valueChanged(int)), &slider, SLOT(setValue(int)));
    QObject::connect(&slider, SIGNAL(valueChanged(int)), &spinbox, SLOT(setValue(int)));
    spinbox.setValue(35);
    QHBoxLayout spinbox_slider;
    spinbox_slider.addWidget(&spinbox);
    spinbox_slider.addWidget(&slider);
    QVBoxLayout main;
    main.addWidget(&label);
    main.addLayout(&spinbox_slider);
    main.addWidget(&button);
    window.setLayout(&main);
    window.show();
    return app.exec();
}

Автор: SABROG 12.3.2008, 14:52
А этот пример из Qt нормально работает ?

Код

#include <QApplication>
#include <QFont>
#include <QPushButton>

 int main(int argc, char *argv[])
 {
     QApplication app(argc, argv);

     QPushButton quit("Quit");
     quit.resize(75, 30);
     quit.setFont(QFont("Times", 18, QFont::Bold));

     QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));

     quit.show();
     return app.exec();
 } 


Используй отладчик.

Автор: anatox91 12.3.2008, 14:59
SABROG, твой пример абсолютно нормально работает, а вот мой - нет... хотя вроде коннект тот же... 

Автор: SABROG 12.3.2008, 15:16
Ну глянь в отладчике.

Автор: anatox91 12.3.2008, 15:23
жаль, но я никогда не работал с отладчиком и вообще не умею им пользоваться... smile  smile 

Автор: anatox91 12.3.2008, 15:40
а есть какие-нибудь книги по нему?

сорри за два поста

Автор: SABROG 12.3.2008, 15:48
Цитата(anatox91 @ 12.3.2008,  15:40)
а есть какие-нибудь книги по нему?

сорри за два поста

На попытке освободить память под какой-то gui'шный объект его выбивает в ntdll:

Код

Invalid Address specified to RtlFreeHeap( 3ee0000, 22fef0 )

Автор: anatox91 12.3.2008, 15:56
и как можно этого избежать? во всех других примерах с такой же кнопкой работает нормально, а тут на тебе...

Автор: SABROG 12.3.2008, 17:43
Косяков здесь 2. Первый это попытка Qt удалить самой указатели на дочернией QObject'ы, ей это успешно удается, поэтому при покидании основного блока программы ОС пытается вызвать деструктор еще раз, ибо Qtшные классы создавались в стеке, а не через new. Второй косяк в том, что ты меняешь флаг окна на Tool, похоже Qt считает, что для этого окна родителем является рабочий стол и выход не происходит по quitOnLastWindowClosed (т.е. когда последнее окно приложения закрывается). Эта проблема где-то обсуждалась уже, но решение я не помню. А так вот рабочая версия:

Код

#include <QLabel>
#include <QApplication>
#include <QPushButton>
#include <QSpinBox>
#include <QWidget>
#include <QSlider>
#include <QHBoxLayout>
#include <QVBoxLayout>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget window;
    window.setWindowTitle("Age");
    //window.setWindowFlags(Qt::Tool);
    QLabel *label = new QLabel("Change your age: ");
    QPushButton *button = new QPushButton("Quit");
    QObject::connect(button, SIGNAL(clicked()), &app, SLOT(quit()));
    QSpinBox *spinbox = new QSpinBox;
    spinbox->setRange(0, 130);
    QSlider *slider = new QSlider(Qt::Horizontal);
    slider->setRange(0, 130);
    QObject::connect(spinbox, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
    QObject::connect(slider, SIGNAL(valueChanged(int)), spinbox, SLOT(setValue(int)));
    spinbox->setValue(35);
    QHBoxLayout *spinbox_slider = new QHBoxLayout;
    spinbox_slider->addWidget(spinbox);
    spinbox_slider->addWidget(slider);
    QVBoxLayout *main = new QVBoxLayout;
    main->addWidget(label);
    main->addLayout(spinbox_slider);
    main->addWidget(button);
    window.setLayout(main);
    window.show();
    return app.exec();
}

Автор: just_geek 12.3.2008, 17:51
создавай виджеты динамически и указывай у виджетов родителя, иначе непонятно в каком порядке они будут уничтожатся...

Код

#include <QLabel>
#include <QApplication>
#include <QPushButton>
#include <QSpinBox>
#include <QWidget>
#include <QSlider>
#include <QHBoxLayout>
#include <QVBoxLayout>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget window;
    window.setWindowTitle("Age");
    window.setWindowFlags(Qt::Tool);
    QLabel *label = new QLabel("Change your age: ", &window);
    QPushButton *button = new QPushButton("Quit", &window);
    QObject::connect(button, SIGNAL(clicked()), &app, SLOT(quit()));
    QSpinBox *spinbox = new QSpinBox(&window);
    spinbox->setRange(0, 130);
    QSlider *slider = new QSlider(Qt::Horizontal, &window);
    slider->setRange(0, 130);
    QObject::connect(spinbox, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
    QObject::connect(slider, SIGNAL(valueChanged(int)), spinbox, SLOT(setValue(int)));
    spinbox->setValue(35);
    QHBoxLayout *spinbox_slider = new QHBoxLayout(&window);
    spinbox_slider->addWidget(spinbox);
    spinbox_slider->addWidget(slider);
    QVBoxLayout *main = new QVBoxLayout(&window);
    main->addWidget(label);
    main->addLayout(spinbox_slider);
    main->addWidget(button);
    window.setLayout(main);
    window.show();
    return app.exec();
}


вот так все замечательно работает...

Автор: SABROG 12.3.2008, 18:05
Цитата(just_geek @  12.3.2008,  17:51 Найти цитируемый пост)
создавай виджеты динамически и указывай у виджетов родителя, иначе непонятно в каком порядке они будут уничтожатся...


Чет ты нашаманил

user posted image

Автор: anatox91 12.3.2008, 22:35
SABROG, большое тебе спасибо, разобрался наконец-то, вот конечный код
Код

#include <QtGui>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget *window = new QWidget;
    window->setWindowTitle("Age");
    window->setWindowFlags(Qt::WindowMinimizeButtonHint);
    QLabel *label = new QLabel("Change your age: ");
    QPushButton *button = new QPushButton("Quit");
    QObject::connect(button, SIGNAL(clicked()), &app, SLOT(quit()));
    QSpinBox *spinbox = new QSpinBox;
    spinbox->setRange(0, 130);
    QSlider *slider = new QSlider(Qt::Horizontal);
    slider->setRange(0, 130);
    QObject::connect(spinbox, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
    QObject::connect(slider, SIGNAL(valueChanged(int)), spinbox, SLOT(setValue(int)));
    spinbox->setValue(35);
    QHBoxLayout *spinbox_slider = new QHBoxLayout;
    spinbox_slider->addWidget(spinbox);
    spinbox_slider->addWidget(slider);
    QVBoxLayout *mainl = new QVBoxLayout;
    mainl->addWidget(label);
    mainl->addLayout(spinbox_slider);
    mainl->addWidget(button);
    window->setLayout(mainl);
    window->show();
    return app.exec();
}

Автор: just_geek 13.3.2008, 10:18
SABROG,  smile главное заработало

Автор: anatox91 13.3.2008, 18:24
Цитата(SABROG)

Чет ты нашаманил

эт из-за того что под все виджеты память динамически выделяется, а под главный QWidget (window) - нет...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)