Доброго времени суток.
Собственно встала следующая проблема. Необходимо вывести окошко (блокирующее все остальные виджеты приложения) и получить с него результат. Окно по типу: "вы уверены ...? Да-Нет". За родителя нового класса был выбран 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.