2009-05-28 87 views
8

我在写第一个适当的有用软件。其中的一部分将涉及用户查看图像,并选择接受或拒绝它。这样做会导致图像被保存到接受或拒绝的文件夹中,并可能旋转和/或调整大小。在Qt中运行单独的进程或线程

目前,我的旋转/调整大小/保存操作暂停执行我的程序,但我希望它发生在后台,以便下一个图像即时显示。

是唯一的方式来做到这一点在Qt中处理图像在一个单独的线程,或者有另一种方式?我仍然把我的脑袋围绕C++和Qt,所以我不想通过潜入一个新领域来迷惑自己!

+8

一个字的警告。您不能在GUI线程之外使用QPixmaps。最近我被这个类似的线程图像渲染类型应用程序所咬。改为使用QImage。如果你真的需要一个QPixmap(我做过),你必须从线程返回一个QImage,然后在主GUI线程中进行转换(这非常昂贵)。 – 2009-05-29 13:21:46

回答

14

Qt有线程支持。您可能会发现this example application有趣,因为它与您所描述的有些相似。

另外,here is the full Qt thread documentation

+0

那么你会建议只是潜入并学习基础知识? – Skilldrick 2009-05-28 22:32:56

+4

线程是正确的答案,Qt的线程支持非常好。如果是我,我只是通过示例来学习。链接的应用程序类似于它在后台执行任务,并允许您在完成时收到通知。举一个有趣或适用于你的例子,并自己尝试一下。查看文档中您不了解的内容,直到整个过程更加清晰。通常这会让你到你需要去的地方。 – Naaff 2009-05-28 22:51:36

3

这些类型的任务非常适合线程。仍然,你应该首先做一个“正常”的功能,当它工作时,添加一个读取队列并调用相同处理函数的线程。

Qt有很多工具可以帮助你解决这个问题,主要是大部分容器都是线程安全的,还有一些线程算法(比如map-reduce)。仍然,首先尝试它同步。

2

编辑

对不起球员,我有一个非常艰难的时间链接“队列自定义类型示例”的要求。

据我所知道的问题,一旦用户接受或拒绝图像,它必须是可选的旋转和/或缩放,并始终保存到一个特定的目录,并继续下一个图像。 ( - >不再与用户进行交互)
即使用户离开当前对话框,图像仍然需要保存。

“排队的自定义类型示例”只处理一个图像,始终链接到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); 
1

可以创建一个单独的线程与QThread或线程池工作线程使用带有QRunnable或看看高水平QtConcurrent类。Here是一个图像缩放的例子。

1

最简单的方法是使用QtConcurrent :: run

相关问题