Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: shchors от Март 25, 2007, 18:36



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

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

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

Есть какие-нибудь идеи?


Название: Перерисовка окон в момент работы долгих функций.
Отправлено: SABROG от Март 25, 2007, 20:43
QProgressDialog не подойдет он и автозакрытие и модализм имеет ?

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

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

Смысл в том, чтобы создать сигнал, который посылает нить через emit в главный поток и прилепить этот сигнал к слоту/методу класса главного окна, откуда и вызывать свои диалоги, я думаю можно сделать и второй сигнал, который вызовет метод главного окна на закрытие диалога, если такой имеется, а также завершит выполнение нити.


Название: Перерисовка окон в момент работы долгих функций.
Отправлено: shchors от Март 25, 2007, 21:46
Цитировать

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


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

Цитировать

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


Спасибо за вектор. Если QProgressDialog не подойдет, буду копать в этом направлении.


Название: Перерисовка окон в момент работы долгих функций.
Отправлено: SABROG от Март 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 от Март 25, 2007, 22:55
Вот поэтому мне QProgressDialog и не подходит. Я не могу вызвать processEvents() из сторонней функции.

Буду копать в сторону QThread \network\blockingfortuneclient.


Название: Перерисовка окон в момент работы долгих функций.
Отправлено: Hordi от Март 26, 2007, 15:52
Я делал так, упрощенно:
в потоке вызывал на долгоиграющую функцию. функция после окончания работы устанавливает флаг об окончании.В основном коде после запуска этой функции на исполнение запускаю QWidget->show() или что-либо со статусом и после показа в цикле проверяю флаг окончания работы функции + precessEvents()


Название: Перерисовка окон в момент работы долгих функций.
Отправлено: zabivator от Март 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 от Март 26, 2007, 17:37
Если честно, то ничего не понятно, даже после того, что я прочитал в ассистанте. Что такое your_object ? Почему moveToThread "not thread-safe" ?