Russian Qt Forum
Май 05, 2024, 19:42 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Не удаляется окно с виджетом если в него загружен текст в разметке html  (Прочитано 9133 раз)
Silentium
Гость
« : Сентябрь 28, 2011, 09:43 »

Добрый день. Не нашел подобной темы потому решил написать вопрос.
И так, у меня много оконное приложение. существует класс "привратник" потомок QObject, который запускает все окна по определенному алгоритму. Проблема возникла с окнами, которые он загружает. Предполагалось, что это диалоговые окна на базе QWidget. В них загружается текст в формате html (ничего сложного только теги <p> и <font>). Загружается все прекрасно, а вот, когда окно надо закрыть(отдельной кнопкой) - окно как бы повисает, но реагирует на кнопку закрытия окна. При этом если сразу после этого запускаю следующие окно все нормально. уничтожение происходит так: по сигналу выполняется слот, в котором уничтожаются все виджиты, а потом посылается сигнал close. Если загружать обычный текст то все происходит прекрасно, окно уничтожается. Побывал создавать как модальный диалог -тот же эффект.
Прошу помочь советом.
« Последнее редактирование: Сентябрь 28, 2011, 09:46 от Silentium » Записан
Bepec
Гость
« Ответ #1 : Сентябрь 28, 2011, 10:23 »

А указать всем виджетам родителя (то окно виджет), и в слоте закрытия просто вызвать close() Непонимающий
Попытаюсь сча смоделировать ситуацию.
Записан
Silentium
Гость
« Ответ #2 : Сентябрь 28, 2011, 10:49 »

не вышло
вот как выглядит слот
Код:
delete ok_label;
    delete ok_button;
    delete cancel_label;
    delete cancel_button;
    delete warning_label;
    delete button_layout;
    delete central_layout;
    emit bye();//посылает сигнал на выключение основному приложению
    close();
а так выглядит инициализация виджитов
Код:
ok_button       =   new QPushButton;
    cancel_button   =   new QPushButton;
    ok_label        =   new QLabel(ok_button);
    cancel_label    =   new QLabel(cancel_button);
    warning_label   =   new QLabel;
    central_layout  =   new QVBoxLayout;
    button_layout   =   new QHBoxLayout;
а дальше группировка и внесение информации из файла.
Код:
central_layout->addWidget(warning_label,Qt::AlignAbsolute);
    central_layout->addStretch();
    central_layout->addLayout(button_layout,Qt::AlignAbsolute);
    button_layout->addWidget(ok_button,Qt::AlignAbsolute);
    button_layout->addStretch();
    button_layout->addWidget(cancel_button,Qt::AlignAbsolute);
    setLayout(central_layout);
и отдельной функцие загрузка данных из файла
Код:
QFile file;
    QTextStream stream(&file);
    file.setFileName("config/object_text_content/age_warning");
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)) return;
    warning_label->setText(stream.readAll());
    stream.flush();
    file.close();
    file.setFileName("config/object_text_content/age_warning_button");
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)) return;
    ok_label->setText(stream.readLine());
    cancel_label->setText(stream.readLine());
    stream.flush();
    file.close();
Единственное что не стандартно, я накладываю на кнопки лайблы, чтоб можно было вставить html текст, напрямую у меня не вышло
« Последнее редактирование: Сентябрь 28, 2011, 10:54 от Silentium » Записан
Bepec
Гость
« Ответ #3 : Сентябрь 28, 2011, 13:08 »

Мб конечно я не понимаю вашего стремления, но зачем все создавать динамически?

Можно просто создать форму (в Designer'e), навтыкать лейблов, кнопок, и нестандартно воткнуть лейблы на кнопки (не видел реализацию, не скажу как и что)

И в последующем весь твой слот будет выглядеть просто -
Код:
// удаление нестандартных лейблов
delete nestandartLabel;
emit bye();
close();

Конечно желательно посмотреть весь твой проект.

Еще как вариант: создавай кнопки и прочее не new, а в виде private: переменных. И опять-таки у них будет виджет родителем и при его закрытии они сами уничтожатся.

PS твоих целей незнаю, потому мои советы могут быть некстати.

 
Записан
Silentium
Гость
« Ответ #4 : Сентябрь 28, 2011, 13:16 »

Спасибо буду думать. Мне, честно, не нравится дезигнер предпочитаю все создавать ручками - мне так понятнее. Странно просто то ,что такой казус возникает только, когда загружен текст в штмл, если загружу обычный текст все будет хорошо (кстати первый раз запускается нормально, на 3 перезапуск начинает виснуть). В конце концов обойдусь без html пусть это и будет более хлопотно! Спасибо за беспокойство
Записан
andrew.k
Гость
« Ответ #5 : Сентябрь 28, 2011, 13:22 »

хочешь ручками, делай ручками, но зачем писать лишний код?
присваивай родителя и он сам удалится в деструкторе. И ошибок меньше будет.

button = new QPushButton (this);

Такой батон удалять не надо.
Записан
Silentium
Гость
« Ответ #6 : Сентябрь 28, 2011, 13:41 »

Да если this не написать он тоже поймет кто родитель этого "батона" и прекрасно его удалит. Проблема в другом, что если загружен html текст, то если верить gdb он даже не попадает в слот просто вешается. А вот при принудительном уничтожение главного виджета (клавиша закрытия окна) он уничтожается, но приложение то повисает, а когда нет html нет.
Записан
Bepec
Гость
« Ответ #7 : Сентябрь 28, 2011, 13:44 »

to Silentium: объект удалится, но память не освободится и появится утечка памяти. Что в дальнейшем фатально.
Можешь скинуть свой проект? Просто видимо у тебя там с сигналами что то. (если конечно проект не закрытый и платный Улыбающийся )

to andrew.k: спасибо за наводку - ток сейчас осознал что:
 только Qtшные объекты удалятся, если у них будет родитель, и он будет прибит.
Думал раньше на Сишный лад.

« Последнее редактирование: Сентябрь 28, 2011, 13:53 от Bepec » Записан
Silentium
Гость
« Ответ #8 : Сентябрь 28, 2011, 13:46 »

ща накропаю тестовое приложение в одно окно без сценариста попробую так. Еще есть вероятность что конфликт идет с операционкой - но это врядли.
Записан
andrew.k
Гость
« Ответ #9 : Сентябрь 28, 2011, 14:19 »

Да если this не написать он тоже поймет кто родитель этого "батона" и прекрасно его удалит. Проблема в другом, что если загружен html текст, то если верить gdb он даже не попадает в слот просто вешается. А вот при принудительном уничтожение главного виджета (клавиша закрытия окна) он уничтожается, но приложение то повисает, а когда нет html нет.

Интересно как это он поймет? Если this не передать в конструктор, то автоматически он не удалится.
И его нужно удалить самостоятельно.
Записан
Silentium
Гость
« Ответ #10 : Сентябрь 28, 2011, 14:27 »

Видимо тему закрываю,. По крайней мере тестовый пример работает. значит как говорил старый анекдот ошибка в рибонуклеиновой кислоте. Действительно не показатель указание родителя. Ошибка видимо идет на уровне класса привратника а значит буду думать. Выложу рабочий тестовый пример
widget.cpp
Код:
#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    html_label  =   new QLabel(this);
    exit_button =   new QPushButton(this);
    main_layout =   new QVBoxLayout(this);
    main_layout->addWidget(html_label);
    main_layout->addStretch();
    main_layout->addWidget(exit_button);
    setLayout(main_layout);
    exit_button->setText("goodbye");
    html_label->setText("<p><img src=img/1.JPG  width=1024 height=768 alt=test><p>test img</p></p><p>THIS IS TEST</p>");
    connect(exit_button,SIGNAL(clicked()),SLOT(goodbye()));
}

Widget::~Widget()
{

}
void Widget::goodbye(){
    delete html_label;//теоретически это избыточно и если верить Шелле все само за сабой чиститься, но всеже
    delete exit_button;
    delete main_layout;
    emit bye();
    close();
}
widget.h
Код:
#ifndef WIDGET_H
#define WIDGET_H

#include <QtGui/QWidget>
#include <QPushButton>
#include <QLabel>
#include <QVBoxLayout>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
    QLabel      *html_label;
    QPushButton *exit_button;
    QVBoxLayout *main_layout;
private slots:
    void goodbye();
signals:
    void bye();
};

#endif // WIDGET_H
main.cpp
Код:
#include <QtGui/QApplication>
#include "widget.h"

int main(int argc, char *argv[])
{
    QApplication *a=new QApplication(argc, argv);
    Widget *w=new Widget;
    w->show();
    QObject::connect(w,SIGNAL(bye()),a,SLOT(quit()));

    return a->exec();
}
Записан
Bepec
Гость
« Ответ #11 : Сентябрь 28, 2011, 14:38 »

Лучше б нерабочий выложил, так бы хоть разобрались где ошибка.

Спасибо создателю темы и andrew.k - с помощью нее уложил еще 1 кирпичик знаний у себя Улыбающийся
Записан
Silentium
Гость
« Ответ #12 : Сентябрь 28, 2011, 18:20 »

Ура ошибка найдена. Правда не понятно почему и империческим путем. Виной всему было наложение лайблов на кнопки если их не накладывать то проблем нет.То есть получается при уничтожение их происходит ошибка.
Приведу последний код рабочий
cpp
Код:
#include "age_enquirer.h"

age_enquirer::age_enquirer(QWidget *parent)
    : QWidget(parent)
{
    ok_button       =   new QPushButton(this);
    cancel_button   =   new QPushButton(this);
    warning_text    =   new QLabel(this);
    ok_label        =   new QLabel(ok_button);
    cancel_label    =   new QLabel(cancel_button);
    button_layout   =   new QHBoxLayout;
    main_layout     =   new QVBoxLayout(this);
    main_layout->addWidget(warning_text);
    main_layout->addStretch();
    main_layout->addLayout(button_layout);
    button_layout->addWidget(ok_button);
    button_layout->addStretch();
    button_layout->addWidget(cancel_button);
    setLayout(main_layout);
    setFixedSize(500,500);
    load_content();
    connect(cancel_button,SIGNAL(clicked()),SLOT(goodbye()));
}
age_enquirer::~age_enquirer(){

}
void age_enquirer::load_content(){
    QFile file;
    QTextStream stream(&file);
    file.setFileName("config/object_text_content/age_warning");
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)) return;
    warning_text->setText(stream.readAll());
    stream.flush();
    file.close();
    file.setFileName("config/object_text_content/age_warning_button");
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text)) return;
    //ok_label->setText(stream.readLine());
    //cancel_label->setText(stream.readLine());
    stream.flush();
    file.close();
}
void age_enquirer::goodbye(){
    delete ok_label;
    delete cancel_label;
    delete ok_button;
    delete cancel_button;
    delete button_layout;
    delete warning_text;
    delete main_layout;
    emit bye();
    close();
}
h
Код:
#ifndef AGE_ENQUIRER_H
#define AGE_ENQUIRER_H

#include <QtGui/QWidget>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFile>
#include <QTextStream>

class age_enquirer : public QWidget
{
    Q_OBJECT
public:
    age_enquirer(QWidget *parent = 0);
    ~age_enquirer();
    QLabel  *warning_text;
    QLabel  *ok_label;
    QLabel  *cancel_label;
    QPushButton *ok_button;
    QPushButton *cancel_button;
    QVBoxLayout *main_layout;
    QHBoxLayout *button_layout;
private:
    void load_content();
private slots:
    void goodbye();
signals:
    void bye();
};

#endif // AGE_ENQUIRER_H
main
Код:
#include <QtGui/QApplication>
#include <QTextCodec>
#include "age_enquirer.h"



int main(int argc, char *argv[])
{
    QApplication *a =   new QApplication(argc, argv);
    QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
    age_enquirer    *age=    new age_enquirer;
    age->show();
    QObject::connect(age,SIGNAL(bye()),a,SLOT(quit()));
    return a->exec();
}
Записан
Bepec
Гость
« Ответ #13 : Сентябрь 29, 2011, 09:25 »

Блин да оладушки - прошу же нерабочую версию Улыбающийся а ты меня рабочими кормишь Улыбающийся

Выложи нерабочую версию в архиве тут (ну или на файлообменнике каком нить), тогда и разберемся. ^^
Записан
Silentium
Гость
« Ответ #14 : Сентябрь 29, 2011, 09:44 »

я проблема оказалась банальна, когда понял в чем дело нашел подобную на форуме. Смысл такой приложение не может понять откого происходит событие cliked, а точнее оно считает что событие произошло не для кнопки, а для лайбла и ничего не делает. Когда нет ввода в лайбел html текста он имеет размер в пиксель и клик приходит правильно, когда же лайбел заполняет всю кнопку нажать на кнопку просто нельзя. А текст кстати именно тот, я просто нафиг выкинул класс привратник - он нафиг не нужен.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.049 секунд. Запросов: 20.