Запуск отдельного процесса или потока в Qt

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

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

- Это единственный способ сделать это в Qt для обработки изображения в отдельном потоке, или есть другой способ? Я все еще думаю о C++ и Qt, поэтому я не хочу запутывать себя, погружаясь в новое поле!

5 ответов


Qt имеет поддержку потоков. Вы можете найти этот пример приложения интересно, так как это несколько похоже на то, что вы описываете.

и вот полная документация Qt thread.


такие задачи идеально подходят для потоков. тем не менее, сначала вы должны сделать "нормальную" функцию, которая это делает, и когда она работает, добавьте поток, который читает очередь и вызывает ту же функцию обработки.

Qt имеет много инструментов, которые помогут вам в этом, в основном тот факт, что большинство контейнеров потокобезопасны, а также несколько алгоритмов потоковой обработки (например, map-reduce). тем не менее, сначала попробуйте синхронно.


редактировать

Извините, ребята, мне очень трудно связать "пример пользовательского типа в очереди" с требованиями.

насколько я могу судить по вопросу, как только пользователь принял или отклонил изображение, оно должно быть необязательно повернуто и/или масштабировано и всегда сохранено в определенном каталоге и перейти к следующему изображению. (- >больше нет взаимодействия с пользователем)
даже если пользователь покидает текущий диалог, изображение все равно должно быть сохраненный.

"Пример пользовательского типа в очереди" обрабатывает только один образ, всегда связан с gui, и когда пользователи выходят из диалога, операция потока останавливается.
Поэтому, если он запускает свою программу из примера в очереди, он, вероятно, начнет писать очередь защищенных изображений мьютекса, чтобы он мог добавлять новые изображения в список, если есть ожидающие операции сохранения. В противном случае пользователю все равно придется ждать отложенных операций.
Вторая проблема заключается в том, что он, вероятно, не хочет ожидание отложенных операций сохранения при закрытии диалогового окна.

То, что я сделал бы для удовлетворения требований, - это работа с пулом потоков. Передайте пулу потоков нужные операции сохранения и используйте шаблон декоратора на основе QRunnable, если его также необходимо повернуть/масштабировать. Все очереди правильно обрабатываются библиотекой, и отложенные операции выполняются, даже если пользователь покидает текущее диалоговое окно. В конце я бы, возможно, использовал пример кода Queued для загрузки новых изображений и дайте пользователю указание ожидания для операции загрузки.

мои runnables и декоратор, вероятно, будет выглядеть так ... (возможно, некоторые дополнительные конструкторы для замены функций набора), поэтому я могу очень легко добавить новую операцию, как это QThreadPool::globalInstance()->start(saver ); без использования объекта синхронизации низкого уровня.

class ImageDecorator : public QRunnable
{
    NextStep nextStep;
public:
    typedef boost::shared_ptr<QRunnable> NextStep;

    ImageDecorator(const NextStep& nextStep) : nextStep(nextStep) {
    }   

    ImageDecorator() : nextStep() {
    }

    // set/get image functions....

protected:
    void next() {
        if( nextStep )
            nextStep->run();
    }
};


class RotateImage : public ImageDecorator
{
public:
    typedef boost::shared_ptr<Image> Image;

    RotateImage(const NextStep& nextStep) : ImageDecorator( nextStep) {
    }   

    RotateImage() : ImageDecorator() {
    }
    // set angle functions....

private:
    void run()
    {
        // rotate the image
        // ...
        next();
    }
};

class ResizeImage : public ImageDecorator
{
public:
    typedef boost::shared_ptr<Image> Image;

    ResizeImage(const NextStep& nextStep) : ImageDecorator( nextStep) {
    }   

    ResizeImage() : ImageDecorator() {
    }
    // set size functions....

private:
    void run()
    {
        // resize the image
        next();
    }
};

class SaveImage : public ImageDecorator
{
public:
    typedef boost::shared_ptr<Image> Image;

    SaveImage(const NextStep& nextStep) : ImageDecorator(nextStep) {
    }   

    SaveImage() : ImageDecorator() {
    }
   // set fileName functions....

private:
    void run()
    {
        // save the image
        next();
    }
};

// save the image 
SaveImage *const saver( new SaveImage() );
saver->setImage( /*use shared pointer*/ );
saver->setFilename( ... );

QThreadPool::globalInstance()->start( saver );

// rotate and save the image 
const ImageDecorator::NextStep saver( new SaveImage() );
saver->setImage( /*use shared pointer*/ );
saver->setFilename( ... );
RotateImage *const rotateAndSave( new RotateImage( saver ) );
rotateAndSave->setImage( /*use shared pointer*/ );
rotateAndSave->setAngle( ... );

QThreadPool::globalInstance()->start( rotateAndSave );


// resize rotate  and  save the image 
const ImageDecorator::NextStep saver( new SaveImage() );
saver->setImage( /*use shared pointer*/ );
saver->setFilename( ... );
const ImageDecorator::NextStep rotateAndSave( new RotateImage( saver ) );
rotateAndSave->setImage(/*use shared pointer*/ );
rotateAndSave->setAngle( ... );
ResizeImage *const resizeRotateAndSave( new ResizeImage( rotateAndSave ) );
resizeRotateAndSave->setImage( /*use shared pointer*/ );
resizeRotateAndSave->setSize( ... );

QThreadPool::globalInstance()->start( resizeRotateAndSave );

либо создайте отдельный поток с QThread или используйте рабочие потоки threadpool с QRunnableили взгляните на класс QtConcurrent высокого уровня. здесь является примером масштабирования изображений.


самый простой способ сделать это-использовать QtConcurrent:: run