Запуск отдельного процесса или потока в Qt
Я пишу свой первый правильный полезный кусок программного обеспечения. Часть его будет включать в себя просмотр пользователем изображения и выбор принять или отклонить его. Это приведет к тому, что изображение будет сохранено в принятой или отклоненной папке и, возможно, повернуто и/или изменено.
на данный момент моя операция поворота/изменения размера/сохранения приостанавливает выполнение моей программы, но я бы хотел, чтобы это произошло в фоновом режиме, чтобы следующее изображение отображалось мгновенно.
- Это единственный способ сделать это в Qt для обработки изображения в отдельном потоке, или есть другой способ? Я все еще думаю о C++ и Qt, поэтому я не хочу запутывать себя, погружаясь в новое поле!
5 ответов
Qt имеет поддержку потоков. Вы можете найти этот пример приложения интересно, так как это несколько похоже на то, что вы описываете.
такие задачи идеально подходят для потоков. тем не менее, сначала вы должны сделать "нормальную" функцию, которая это делает, и когда она работает, добавьте поток, который читает очередь и вызывает ту же функцию обработки.
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 высокого уровня. здесь является примером масштабирования изображений.