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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Новый класс на основе QDialog и память  (Прочитано 4762 раз)
Orfus
Гость
« : Февраль 10, 2011, 13:17 »

Доброго времени суток.
Собственно встала следующая проблема. Необходимо вывести окошко (блокирующее все остальные виджеты приложения) и получить с него результат. Окно по типу: "вы уверены ...? Да-Нет". За родителя нового класса был выбран QDialog, по причине существования в нём такой вещи как exec(). Такое окно будет появлятся одновременно 1 на всё приложение  (с разными текстом в различных случаях), но вызываться может десятки раз и поэтому чтобы не долбаться с потерей памяти я сделал его глобальным для всего приложения и получил следующую проблему.
При первом вызове всё происходит гладко и красиво. При втором вызове, непонятно откуда происходит отрисовка окна, а уже после этого смена текста. Всё конечно работает, но косяк с таким мерцанием текста напрягает.

header
Код:
class MesBoxYesNo: public QDialog
{
    Q_OBJECT

public:
    explicit MesBoxYesNo();
    ~MesBoxYesNo();

    topBar      *tbar;// окно делается с 0. это полоска наверху с заголовком и кнопкой закрыть.
    QLabel      *Label_text;//1 строка текста
    QLabel      *Label_textunder;//2 строка текста
    QPushButton *But_yes;//кнопка Да
    QPushButton *But_no;//кнопка нет

    QHBoxLayout *ButLayout;
    QVBoxLayout *MainLayout;
    int answer;//переменная которую будет возвращать окошко
    int winWidth,winHeight;//размеры окна
protected:
    void paintEvent(QPaintEvent *event);
public slots:
    void close();

    //ниже слот вызова окна. проблема в нём. Его отработка запаздывает, наверно...
    int Question(QString question,QString question2,QString topbar_label,int width,int height);

    void yes();
    void no();
};

Вызов из другого cpp. Инициализация происходит в main.cpp. Сама же ссылка на переменную хранится в файле глобальных переменных, хедер которого я использую во многих местах.
Код:
 switch(MesBoxYN->Question(tr("Вы действительно хотите удалить?"), //1ая строка
                            tr(""),//2ая строка
                            tr("Удаление ")+this->tree_model->itemFromIndex(index)->text(),//текст в заголовке
                            250,//переменные размеров
                            100))
        {
        case 1:
            {
            //some actions
            break;
            }
        case 0:
            {
            //some actions
            break;
            }


конструктор и слоты cpp
Код:
MesBoxYesNo::MesBoxYesNo()
    :QDialog()
{
    tbar            =new topBar(this);
    Label_text      =new QLabel(this);
    Label_textunder =new QLabel(this);
    But_yes = new QPushButton(tr("Ok"),this);
    But_no = new QPushButton(tr("Отмена"),this);

    MainLayout  = new QVBoxLayout(this);
    ButLayout   = new QHBoxLayout();
    ButLayout->setMargin(0);
    MainLayout->setMargin(0);


    ButLayout->addWidget(But_yes,0,Qt::AlignLeft);
    ButLayout->addWidget(But_no,0,Qt::AlignRight);

    But_yes->setObjectName("But_Standart");
    But_no->setObjectName("But_Standart");

    MainLayout->addWidget(tbar,0,Qt::AlignTop);
    MainLayout->addWidget(Label_text,0,Qt::AlignJustify);
    MainLayout->addWidget(Label_textunder,0,Qt::AlignJustify);
    MainLayout->addLayout(ButLayout);

    connect(But_yes,SIGNAL(clicked()),this,SLOT(yes()));
    connect(But_no,SIGNAL(clicked()),this,SLOT(no()));
    connect(tbar->closeBut,SIGNAL(clicked()),this,SLOT(no()));
    this->setObjectName("MesBoxYesNo");
    answer=0;

    winWidth= 150;
    winHeight= 100;


    this->setLayout(MainLayout);

    this->setWindowFlags(Qt::FramelessWindowHint);
    this->setAttribute(Qt::WA_TranslucentBackground);
    this->setWindowModality (Qt::ApplicationModal);
    //this->setAttribute(Qt::WA_DeleteOnClose);//тут у меня были попытки уничтожать окно по закрытию.
    // но тогда правильный int возвращался через раз
    this->setStyleSheet(styles);//Глобальная переменная со стилями.
    this->hide();
    qWarning()<<"MesBoxYesNo::MesBoxYesNo()";
}
void MesBoxYesNo::paintEvent(QPaintEvent *event)
{
       //вызов исходного метода
       QDialog::paintEvent( event );
       //произвольные команды
       QStyleOption opt;
       opt.init(this);
       QPainter p(this);
       style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
       qWarning()<<"MesBoxYesNo::paintEvent()";
}
int MesBoxYesNo::Question(QString question,QString question2,QString tbar_label,int width=0,int height=0)
{

    qWarning()<<"MesBoxYesNo::Question() 01";
    answer=0;
    tbar->TopLabel->setText(tbar_label);
    Label_text->setText(question);
    Label_textunder->setText(question2);

    qWarning()<<"MesBoxYesNo::Question() 02";
    if(width!=0)
    {winWidth=width;}
    if(height!=0)
    {winHeight=height;}

    QDesktopWidget *d=QApplication::desktop();
    int x=d->width(),y=d->height();
    this->setGeometry((x-winWidth)/2,(y-winHeight)/2,winWidth,winHeight);
    qWarning()<<"MesBoxYesNo::Question() 03";

//    qWarning()<<"answer first = "<<answer;
//    this->show();
    setVisible( true );
    //exec();
    qWarning()<<"answer final = "<<answer;
    return answer;
}
//смена переменной на 1 и закрытие окна
void MesBoxYesNo::yes()
{
    answer = 1;
    close();
}
//смена переменной на 0 и закрытие окна
void MesBoxYesNo::no()
{
    answer=0;
    close();
}
//хоть close тут и стоит и даже отрабатывается, но обнуления не происходит вообще...
void MesBoxYesNo::close()
{
   qWarning()<<"MesBoxYesNo::close() 01";

   tbar->TopLabel->setText("");
   Label_text->setText("");
   Label_textunder->setText("");

   tbar->TopLabel->clear();
   Label_text->clear();
   Label_textunder->clear();
   qWarning()<<"MesBoxYesNo::close() 02";
   QDialog::close();
}
MesBoxYesNo::~MesBoxYesNo()
{
    if(tbar){tbar=0;delete tbar;}
    if(Label_text){Label_text=0;delete Label_text;}
    if(Label_textunder){Label_textunder=0;delete Label_textunder;}
    if(But_no){But_no=0;delete But_no;}
    if(But_yes){But_yes=0;delete But_yes;}
    if(ButLayout){ButLayout=0;delete ButLayout;}
    if(MainLayout){MainLayout=0;delete MainLayout;}

}

Вопрос в том как избавится от мерцания и почему оно вообще рисуется до exec()? Без exec() оно либо не рисуется вообще, либо закрывается моментально и я не успеваю его заметить.

Альтернативный способ борьбы на мой взгляд:
1) Долбаться с локальными переменными окна и делать delete в конце метода с ним.
Я честно говоря мало понимаю в распределении памяти. Насколько мне было известно в конце метода переменные инициализированные в данном методе пропадают, но память выделенная под них остаётся замусоренной. Вопрос ещё в том правильно ли я это понял)

2) Отказаться от QDialog и ковырять в другом направлении (QWidget сигнал-слотовая структура)
У меня были изначально попытки разобраться с setEnabled(false) для блокирования остальной части приложения, но я предпочёл перейти к QDialog.
Записан
UVV
Гость
« Ответ #1 : Февраль 10, 2011, 13:24 »

Почему бы просто не воспользоваться QMessageBox?
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #2 : Февраль 10, 2011, 13:26 »

Какой кошмар. Улыбающийся
Советую попробовать начать сначала и все обдумать. Подмигивающий
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Orfus
Гость
« Ответ #3 : Февраль 10, 2011, 13:43 »

Почему бы просто не воспользоваться QMessageBox?
Стандартная отрисовка выбивается из стиля. Тем более он тоже от диалога наследуется и боюсь проблемы будут те же. В замешательстве


Какой кошмар. Улыбающийся
Советую попробовать начать сначала и все обдумать. Подмигивающий
Что большего всего ужаснуло? Веселый


Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #4 : Февраль 10, 2011, 13:44 »

Orfus, подход к решению задачи, так как код не парсил, "многабукф".

Как уже посоветовали, используй QMessageBox.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Orfus
Гость
« Ответ #5 : Февраль 11, 2011, 14:30 »

Собственно говоря проблема как оказалось даже не в QDialog. Данный косяк проявляется во всём приложении....  Обеспокоенный

Например в дереве: первой строкой каждого метода я разместил  qWarning() с названием метода.
Ну примерно так:
Код
C++ (Qt)
void SelectGroupWindow::show()
{
   qWarning()<<"SelectGroupWindow::show()";
   QWidget::show();
}
 
void SelectGroupWindow::Show()
{
   qWarning()<<"SelectGroupWindow::Show()";
   tree->tree_model->clear();
 
   currentNode=new QStandardItem(QDir::toNativeSeparators(Dir_Groups));
   currentNode->setEditable(false);
 
   tree->tree_model->appendRow(currentNode);
   tree->RefreshNode(currentNode->index());
   tree->expand(currentNode->index());
 
   this->show();
}
 
 

Получил следующий список:

Код:
SelectGroupWindow::SelectGroupWindow() //конструктор
SelectGroupWindow::Hide() //очистка и затем hide окна

//далее я вызываю окно в первый раз по нажатию на некую кнопку
SelectGroupWindow::Show() //Смена некоторых значений и show() в конце
SelectGroupWindow::ButtonsEnD() // Disable/enable некоторых кнопок
SelectGroupWindow::show() //отображение окна
SelectGroupWindow::ButtonsEnD() // Disable/enable некоторых кнопок

//далее окно прячется по нажатию на кнопку
SelectGroupWindow::Hide()          //очистка и затем hide окна

//вот тут проблема :(
SelectGroupWindow::Show() //Смена некоторых значений и show() в конце
SelectGroupWindow::ButtonsEnD() // Disable/enable некоторых кнопок
SelectGroupWindow::ButtonsEnD() // Disable/enable некоторых кнопок
SelectGroupWindow::show() //собственно показ окна
В первый раз после инициализации всё происходит замечательно. Но в каждый следующий сначала окно показывается, а только после этого очищает некоторые старые значения и строит новые и в то же время я вижу в дебаггере что метод Show() производящий очистку вызывается раньше чем show() производящий показ. Ума не приложу чем может быть вызвано.  Непонимающий
Записан
Etud
Гость
« Ответ #6 : Февраль 11, 2011, 19:41 »

Надо начать с НУЛЯ

и все переписать...

А память тут при чем ?
Записан
Orfus
Гость
« Ответ #7 : Февраль 14, 2011, 11:22 »

Надо начать с НУЛЯ

и все переписать...

А память тут при чем ?

Не особо радует писать всё с 0.. но видимо придётся.

Я слабо понимаю как используется память, но предполагаю что единожды созданное окно в котором меняют некотрые значения, работает быстрее (отрисовывается) и занимает меньше памяти чем постоянно создаваемые с 0. Собственно говоря даже если объёмы памяти останутся теми же и не будет никаких утечек, процесс создания окна с 0 займёт больше времени чем смены значений пары QLabel. Или я не прав?

А касательно мерцания, дело то было в parent. Если я создавал новый виджет без parent он сначала показывал себя старого, а потом перерисовывался. Если же ему делать родителем главное окно то он сразу всё верно отображал.
« Последнее редактирование: Февраль 14, 2011, 12:23 от Orfus » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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