Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Termit от Июль 31, 2011, 20:51



Название: QDialog и затенение окна
Отправлено: Termit от Июль 31, 2011, 20:51
Добрый день.

Хочу реализовать затенение главного окна приложения при открытии модального диалога. Не получается ничего нормального.
То ничего не происходит, то работает крайне медленно :-(

Хотелось бы чтобы работало без лишнего наследования виджетов.

Поиск по google и по форуму понимания ситуации не добавил.

Делал так. Вроде на форуме было...
Код
C++ (Qt)
QPixmap px = QPixmap::grabWidget( this );
QPainter p( &px );
p.setBrush( QColor( 0, 0, 0, 100 ) ); // highligh a bit
p.setPen( Qt::NoPen );
p.drawRect( px.rect() );
p.end();
 
Ничего не происходит...

Делал свой QGraphicsEffect
в методе draw
Код
C++ (Qt)
painter->fillRect(boundingRect(), QColor( 0, 0, 0, 100 ));
 
Тормозит со страшной силой. И похоже, что вызывается для каждого объекта на форме

Есть ли у кого решение? В какую сторону копать?


Название: Re: QDialog и затенение окна
Отправлено: SimpleSunny от Июль 31, 2011, 21:20
Может попробовать так

Код
C++ (Qt)
setEnabled(false);
//по желанию qApp->processEvents();
dlg.exec();
setEnabled(true);


Название: Re: QDialog и затенение окна
Отправлено: Termit от Июль 31, 2011, 21:23
Может попробовать так

Код
C++ (Qt)
setEnabled(false);
//по желанию qApp->processEvents();
dlg.exec();
setEnabled(true);

Нет, ну это же не затемнение...


Название: Re: QDialog и затенение окна
Отправлено: Termit от Август 01, 2011, 00:12
После того как добавил строку
Код
C++ (Qt)
painter->setRenderHint(QPainter::Antialiasing);
painter->fillRect(boundingRect(), QColor( 0, 0, 0, 100 ));
 
вдруг стало быстро работать...


Название: Re: QDialog и затенение окна
Отправлено: climber от Август 01, 2011, 11:09
Решал подобную задачу. Необходимо было в момент длительного обращения к базе блокировать курвер для отрисовки графиков, с показом прогреса.

Вот как реализовано у меня
Код:

class Glass : public QDialog
{
    Q_OBJECT

public:
  Glass(QWidget *parent = 0);
  ~Glass();
  QBrush *mask;
  QLabel *informationText;
  QLabel *glass;
  QLabel *animationContainer;
  QLabel *progress;
  QMovie *defaultMovie;
  int install; // 1 - положить стекло 0 - убрать
  void installGlass(QWidget *w);
public slots:
  void removeGlass();
  void setProgress(double p);
};

Glass::Glass(QWidget *parent):
    QDialog(parent)
{

    install = 0;
    QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect(parent);
    const QColor& color = QColor(111, 111, 100);

    mask = new QBrush();
    mask->setColor(color);
    mask->setStyle(Qt::SolidPattern);
    qreal opacity = 0.7;

    opacityEffect->setOpacityMask(*mask);
    opacityEffect->setOpacity(opacity);

    glass = new QLabel(parent);
    glass->setGraphicsEffect(opacityEffect);
    glass->setVisible(false);

    informationText = new QLabel(parent);
    informationText->setVisible(false);
    informationText->setText(trUtf8("Подождите\n Выполняется отбор данных..."));
    QFont font;
    font.setPointSize(12);
    font.setWeight(QFont::Bold);
    informationText->setFont(font);
    informationText->setAlignment(Qt::AlignHCenter);

    QPalette pal(informationText->palette());
    pal.setColor(QPalette::Foreground, QColor("white"));

    informationText->setPalette(pal);

    animationContainer = new QLabel(parent);
    animationContainer->setVisible(false);
    defaultMovie = new QMovie("/pictures/loading51.gif", QByteArray(), animationContainer);
    animationContainer->setMovie(defaultMovie);
    defaultMovie->start();

    progress = new QLabel(parent);
    progress->setVisible(false);
    progress->setPalette(pal);
    progress->setAlignment(Qt::AlignHCenter);

}

Glass::~Glass()
{
  delete progress;
  delete defaultMovie;
  delete animationContainer;
  delete informationText;
  delete glass;
  delete mask;
}

void Glass::installGlass(QWidget *w)
{
  install = 1;
  glass->setVisible(true);
  informationText->setVisible(true);
  animationContainer->setVisible(true);
  progress->setVisible(true);

  progress->setGeometry(w->size().width()/2 - 17,w->size().height()/2 - 80,30,15);
  animationContainer->setGeometry(w->size().width()/2 - 65,w->size().height()/2 - 150,300,150);
  informationText->setGeometry(w->size().width()/2 - 150,w->size().height()/2,300,150);
  glass->setGeometry(0,0,w->size().width(),w->size().height());
}

void Glass::removeGlass()
{
  install = 0;
  glass->setVisible(false);
  informationText->setVisible(false);
  animationContainer->setVisible(false);
  progress->setVisible(false);
}

void Glass::setProgress(double p)
{
  QString str_persent;
  str_persent.setNum((int)p);

  progress->setText(str_persent);
}

Работает шустро.


Название: Re: QDialog и затенение окна
Отправлено: Termit от Август 01, 2011, 17:51
Решал подобную задачу. Необходимо было в момент длительного обращения к базе блокировать курвер для отрисовки графиков, с показом прогреса.

Спасибо, как вернусь из командировки помедитирую.
По результатам отпишусь.


Название: Re: QDialog и затенение окна
Отправлено: trot от Август 01, 2011, 20:32
Создаешь QWidget, распахиваешь его на все свое окно, устанавливаешь прозрачность, а потом вызываешь свой модальный диалог. После закрытия диалога, уничтожаешь виджет. Вот и все.


Название: Re: QDialog и затенение окна
Отправлено: Termit от Август 03, 2011, 18:52
Вот как реализовано у меня

Спасибо, получилось то, что хотел...

to All:

Проясните такую ситуацию:
для простоты изложения вложил маленький проект, который на коленке собрал из QGraphicsEffect и решения climber.

Так вот, если применить напрямую (key 1) эффект на форму где что-то изменяется, то эффект применяется много раз. В коде есть закомментированный костыль.

Собственно почему так происходит?


Название: Re: QDialog и затенение окна
Отправлено: climber от Август 04, 2011, 10:56
Как мне видится это происходит вот почему:
1. В классе GraphicsDarkensEffect переопределена виртуальная функция draw, которая вызывается всякий раз, когда источник перерисовывается.
Цитировать
This pure virtual function draws the effect and is called whenever the source needs to be drawn.
2. В Вашем случае источником является объект класса Gf, который меняется по таймеру. Соответственно и функция draw получается что вызывается по таймеру.

P.S. А зачем понадобилось писать класс наследованный от QGraphicsEffect, если как Вы уже сами попробовали, мой способ проще? =)


Название: Re: QDialog и затенение окна
Отправлено: Termit от Август 04, 2011, 18:33
Как мне видится это происходит вот почему:
1. В классе GraphicsDarkensEffect переопределена виртуальная функция draw, которая вызывается всякий раз, когда источник перерисовывается.
Цитировать
This pure virtual function draws the effect and is called whenever the source needs to be drawn.
Все так и есть. Но ожидалось, что перерисовываться будет каждый раз  так сказать "с нуля", а не уже с наложенным эффектом.

2. В Вашем случае источником является объект класса Gf, который меняется по таймеру. Соответственно и функция draw получается что вызывается по таймеру.
P.S. А зачем понадобилось писать класс наследованный от QGraphicsEffect, если как Вы уже сами попробовали, мой способ проще? =)

Этот класс я писал еще до того как Вы выложили свое решение. Ну а по большому счету, лично для меня кажется более правильным подход с созданием эффекта ;-)

PS. В некоторых случаях в Ваше решение тоже затемняется по много раз - если на форме есть QLabel который по таймеру обновляется.