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


Автор: becks 26.10.2012, 15:59
Добрый день, коллеги! Вопрос такой, хочу в программе в моменты длительных вычислений накрывать некоторый виджет другим виджетом с красивыми эффектами, дабы запретить редактирование. В качестве виджета родителя может выступать практически любой виджет от главной формы до закладок в табвиджете. 

И вот главная проблема, что при ресайзе родителя, от него остается скролл на старом месте. Предок (покрывало) ресайзится нормально. 

Покрывалу назначил eventFilter:

Код

bool Glass::eventFilter(QObject *object, QEvent* event)
{
    if(object != this && object != m_parent)
        return false;

    if(event->type() == QEvent::Resize)
    {
        QWidget *w = qobject_cast<QWidget *>(object);
        m_glass->resize(m_glass->parentWidget()->size());
        w->repaint();
        m_glass->move(0, 0);
        positioning();
        return true;
    }
    m_glass->setFocus();
    return false;
}


для родителя делаю:
Код

ui->documentTabs->currentWidget()->installEventFilter(glass);


Если свернуть и развернуть приложение, то скролл встает на правильное место.

Автор: hawk3500 28.10.2012, 19:03
А может просто сделать hide для родительского виджета?

Автор: becks 29.10.2012, 10:15
Цитата

А может просто сделать hide для родительского виджета? 


Чтобы было нагляднее вот картинка:

http://s2.ipicture.ru/uploads/20121029/muRVd3z7.bmp


Тут одна вкладочка закрыта от редактирования пока идет какой-то процесс, остальные пользователь может редактировать и в том числе и изменять размер мэйнвиндоуса. Я полагаю hide() тут не поможет.

Автор: becks 5.11.2012, 14:08
Собственно, все еще не могу понять почему не перерисовывается скролл, задачу не решил. Прошу помощи.

Автор: loneybibi 8.11.2012, 17:44
Цитата(becks @ 26.10.2012,  14:59)
Добрый день, коллеги! Вопрос такой, хочу в программе в моменты длительных вычислений накрывать некоторый виджет другим виджетом с красивыми эффектами, дабы запретить редактирование. В качестве виджета родителя может выступать практически любой виджет от главной формы до закладок в табвиджете. 

И вот главная проблема, что при ресайзе родителя, от него остается скролл на старом месте. Предок (покрывало) ресайзится нормально. 

Покрывалу назначил eventFilter:

Код

bool Glass::eventFilter(QObject *object, QEvent* event)
{
    if(object != this && object != m_parent)
        return false;

    if(event->type() == QEvent::Resize)
    {
        QWidget *w = qobject_cast<QWidget *>(object);
        m_glass->resize(m_glass->parentWidget()->size());
        w->repaint();
        m_glass->move(0, 0);
        positioning();
        return true;
    }
    m_glass->setFocus();
    return false;
}


для родителя делаю:
Код

ui->documentTabs->currentWidget()->installEventFilter(glass);


Если свернуть и развернуть приложение, то скролл встает на правильное место.

Я так понял что positioning() это и есть длительная операция.
Так как она выполняется внутри виджета то естественно он подвиснет и отрисовка GUI тоже будет тупить.
Попробуйте вместо метода repaint() вызвать метод update() и не до а после метода move(), насколько я помню он сам вызовет метод repaint() как надо.

Вообще обычно всегда при длительных операция GUI подвисает.

Такие объемные функции надо выносить в отдельный поток, почитайте про QThread.

Конечно есть другой вариант! Сделать псевдо-поток но у этого способа есть некоторые нюансы!
Хотя я думаю вам может подойди. Почитайте эту статью:
http://www.opennet.ru/docs/RUS/qt3_prog/x4064.html
Как это делается показал в коде, но опять же повторюсь что лучше использовать QThread, так и GUI подвисать не будет и отрисовка будет нормальной.

Код

bool Glass::eventFilter(QObject *object, QEvent* event)
{
    if(object != this && object != m_parent)
        return false;
    if(event->type() == QEvent::Resize)
    {
        QWidget *w = qobject_cast<QWidget *>(object);
        m_glass->resize(m_glass->parentWidget()->size());
        m_glass->move(0, 0);

        w->update(); //<<<<<<<<<<<

        qApp->processEvents(); // <<<<<<< Псевдо-поток

        positioning();

        return true;
    }
    m_glass->setFocus();
    return false;
}

Автор: becks 8.11.2012, 22:06
Видимо плохо всё объяснил, сейчас попытаюсь более детально.

Есть некоторое приложение, по внешнему виду очень напоминающее Notepad++, т.е. существует центральный QTabWidget, и в нем несколько вкладок, каждая такая вкладка представляет собой QGraphicsView на нем я рисую граф и изначально у него есть скролл. Вот, и так как некоторые задачи обработки графа занимают продолжительное время, вкладку на которой расположен граф я хочу на это время накрывать объектом-покрывалом Glass. Другие вкладки в это время должны быть потенциально доступны (в принципе так оно сейчас и есть).

Сейчас я пока не делаю никаких нагруженных задач, а просто по нажатию на некоторую кнопку в MainWindow  накрываю объектом-покрывалом Glass открытую вкладку:

Код

void MainWindow::changeWorkingMode()
{

    ....
    Glass *glass = new Glass("Производится сохранение настроек базовых объектов!\n"
                             "Данная операция может занять некоторое время.\n");
    ui->documentTabs->currentWidget()->installEventFilter(glass);
    glass->setAnimationDuration(200);
    glass->init(ui->documentTabs->currentWidget());
}


В этом коде вроде должно быть все понятно. 

Хотя теперь у меня возникают сомнения о правильности вызова installEventFilter?

Вот определение класса Glass:

Код

class Glass : public QObject
{
    Q_OBJECT
public:
    explicit Glass(QString message = "", int stepCount = 0);
    virtual ~Glass();
...
    void setAnimationDuration(int duration);
    void init(QWidget *parent); // виджет-родитель, который накрываем
    void hideAndDelete();

protected:

    bool eventFilter(QObject* object, QEvent* event);

private:
    QLabel* m_glass;
    QLabel* m_infoText;
    QProgressBar *m_progressBar;

    QWidget *m_parent;
};


QLabel* m_glass - растягивается по родительскому виджету.


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