2009-05-28 142 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

相關問題