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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Перерисовка окон в момент работы долгих функций.  (Прочитано 6430 раз)
shchors
Гость
« : Март 25, 2007, 18:36 »

Хотелось бы сделать следующую вещь (если это возможно, конечно). Периодически в программе вызываются функции, которые могут отрабатывать от 10 секунд до пары минут. Хотелось написать пару функций, одну из них вызывать перед такой продолжительной функцией, другую - после. Первая должна вывести на экран окошко с надписью "Подождите...", вторая - убрать. Такое уже сделано.

Теперь самое интересное: окошко с надписью "Подождите" не перерисовывается, если его чем-то перекрыли. Понятно даже почему: потому что основной цикл QT никто не вызывает. Возможности вызвать processEvents() из долго работающей функции нет, поскольку эта функция из сторонней библиотеки, к исходникам которой нет доступа.

Вопрос такой: можно ли как-то сделать, чтобы окошко все-же перерисовывалось (например, с помощью потоков, или же вызовом дочернего приложения)? Я пробовал запускать это окошко в другом потоке - QT говорит, что нельзя (или не рекомендуется, не помню точно) этого делать.

Есть какие-нибудь идеи?
Записан
SABROG
Гость
« Ответ #1 : Март 25, 2007, 20:43 »

QProgressDialog не подойдет он и автозакрытие и модализм имеет ?

добавлено спустя:

 Если хочешь использовать свои диалоги, то посмотри пример из на основе QThread \network\blockingfortuneclient

Смысл в том, чтобы создать сигнал, который посылает нить через emit в главный поток и прилепить этот сигнал к слоту/методу класса главного окна, откуда и вызывать свои диалоги, я думаю можно сделать и второй сигнал, который вызовет метод главного окна на закрытие диалога, если такой имеется, а также завершит выполнение нити.
Записан
shchors
Гость
« Ответ #2 : Март 25, 2007, 21:46 »

Цитировать

QProgressDialog не подойдет он и автозакрытие и модализм имеет ?


QProgressDialog подошел бы идеально с бесконечным прогрессбаром. Вопрос в том, будет ли он отрисовывать бегущий прогресс, если приложение занято вызывом левой функции и основной цикл QT не работает.

Цитировать

Если хочешь использовать свои диалоги, то посмотри пример из на основе QThread \network\blockingfortuneclient


Спасибо за вектор. Если QProgressDialog не подойдет, буду копать в этом направлении.
Записан
SABROG
Гость
« Ответ #3 : Март 25, 2007, 22:44 »

Цитата: "shchors"
Вопрос в том, будет ли он отрисовывать бегущий прогресс, если приложение занято вызывом левой функции и основной цикл QT не работает.


Есть пример dialogs\findfiles
Кусок оттуда:
Код:

QStringList Window::findFiles(const QDir &directory, const QStringList &files,
                              const QString &text)
{
    QProgressDialog progressDialog(this);
    progressDialog.setCancelButtonText(tr("&Cancel"));
    progressDialog.setRange(0, files.size());
    progressDialog.setWindowTitle(tr("Find Files"));

    QStringList foundFiles;

    for (int i = 0; i < files.size(); ++i) {
        progressDialog.setValue(i);
        progressDialog.setLabelText(tr("Searching file number %1 of %2...")
                                    .arg(i).arg(files.size()));
        qApp->processEvents();

        if (progressDialog.wasCanceled())
            break;

        QFile file(directory.absoluteFilePath(files[i]));

        if (file.open(QIODevice::ReadOnly)) {
            QString line;
            QTextStream in(&file);
            while (!in.atEnd()) {
                if (progressDialog.wasCanceled())
                    break;
                line = in.readLine();
                if (line.contains(text)) {
                    foundFiles << files[i];
                    break;
                }
            }
        }
    }
    return foundFiles;
}


Т.е. можно сказать, что в главном потоке между инструкциями, которые грузят процесс и вешают программу вызывается processEvents() для отрисовки обработки окон, паралельно идет проверка на нажатие клавиши отмена. Этот способ может быть плох тем, что во время очень загруженных операций интерфейс диалога будет замораживаться и не обрабатывать нажатия клавиш, пока не достигнет processEvents(), это плохо как-раз в случаях работы с сокетами, файлами, внешними источниками данных или методами (API, dllки третих сторон) внутри которых невозможно вставить ProcessEvents() например Sleep или искуственная задержка.
Поэтому хоть нити и сложнее реализовывать, но они не имеют подобных недостатков.
Записан
shchors
Гость
« Ответ #4 : Март 25, 2007, 22:55 »

Вот поэтому мне QProgressDialog и не подходит. Я не могу вызвать processEvents() из сторонней функции.

Буду копать в сторону QThread \network\blockingfortuneclient.
Записан
Hordi
Гость
« Ответ #5 : Март 26, 2007, 15:52 »

Я делал так, упрощенно:
в потоке вызывал на долгоиграющую функцию. функция после окончания работы устанавливает флаг об окончании.В основном коде после запуска этой функции на исполнение запускаю QWidget->show() или что-либо со статусом и после показа в цикле проверяю флаг окончания работы функции + precessEvents()
Записан
zabivator
Гость
« Ответ #6 : Март 26, 2007, 17:07 »

http://doc.trolltech.com/4.2/threads.html
Per-Thread Event Loop

Наследуемся от QThread, переопределяем run(), в нем QThread::exec()
Потом your_object->moveToThread( thread );;
И все слоты данного объекта, дергаемые по сигналу вызываются в другом потоке. Основной гуевый поток свободен все время.
Записан
SABROG
Гость
« Ответ #7 : Март 26, 2007, 17:37 »

Если честно, то ничего не понятно, даже после того, что я прочитал в ассистанте. Что такое your_object ? Почему moveToThread "not thread-safe" ?
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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