2017-06-02 60 views
0

我想要做一個項目是用Qt GUI C++ 5.6.2在窗口上創建一些圖形。 我有兩個名爲'createVerticalSpeedIndicator'和'createAirSpeedIndicator'的方法。這些方法需要用while(1)循環創建一些圖形並使用qApp-> processEvents();在窗口上,當他們中的一個人工作時另一個人處於非活動狀態時他們正在完美地完成工作。但是我需要同時運行它們並始終運行它們。Qt多循環同時循環和qApp-> processEvents();

我該怎麼做才能同時運行它們並始終如一。

謝謝你這麼多

+0

您目前正在努力使這兩個指標在同while循環,還是兩個?您是使用OpenGL小部件還是內置小部件?你使用單獨的線程嗎?一些僞代碼的例子會很好。鑑於此描述,有太多可能會出錯的事情。 – rationalcoder

+0

我使用了線程,但是我看到了一些粘連,我正在創建圖形,所以我想如果在同一個循環中顯示,我可能會失去smotth。因爲我會將這15張圖片分開。我正在使用內置小工具 –

+0

您遇到過什麼樣的「粘連」?您正在使用哪個內置小工具? 15究竟是什麼?請發佈一些您的代碼和圖片。 – rationalcoder

回答

0

的解決方案是反轉控制流。 while() { ... processEvents() ... }是異步代碼中的反模式,因爲它假定您擁有控制軌跡,而您確實沒有。你很幸運,因爲processEvents可能會重新輸入createXxx方法,所以你沒有用完堆棧。

這裏有一個轉變的一個完整的例子:

// Input 
void Class::createVerticalSpeedIndicator() { 
    for (int i = 0; i < 100; i ++) { 
    doStep(i); 
    QCoreApplication::processEvents(); 
    } 
} 
// Step 1 - factor out state 
void Class::createVerticalSpeedIndicator() { 
    int i = 0; 
    while (i < 100) { 
    doStep(i); 
    QCoreApplication::processEvents(); 
    i++; 
    } 
}; 
// Step 2 - convert to continuation form 
void Class::createVerticalSpeedIndicator() { 
    int i = 0; 
    auto continuation = [=]() mutable { 
    if (!(i < 100)) 
     return false; 
    doStep(i); 
    QCoreApplication::processEvents(); 
    i++; 
    return true; 
    }; 
    while (continuation()); 
}; 
// Step 3 - execute the continuation asynchronously 
auto Class::createVerticalSpeedIndicator() { 
    int i = 0; 
    return async(this, [=]() mutable { 
    if (!(i < 100)) 
     return false; 
    doStep(i); 
    i++; // note the removal of processEvents here 
    return true; 
    }); 
}; 

template <typename F> void async(QObject * parent, F && continuation) { 
    auto timer = new QTimer(parent); 
    timer->start(0); 
    connect(timer, &QTimer::timeout, [timer, c = std::move(continuation)]{ 
    if (!c()) 
     timer->deleteLater(); 
    }); 
} 

在這一點上,你可以使用同樣的改造createAirSpeedIndicator,並在啓動它們你班的構造函數:

Class::Class(QWidget * parent) : QWidget(parent) { 
    ... 
    createVerticalSpeedIndicator(); 
    createAirSpeedIndicator(); 
} 

這兩個任務將在主線程內異步並僞同時運行,即每個任務將交替執行一個單獨的步驟。

假設我們想鏈接任務,即只有在前一個任務完成後纔開始任務。在用戶代碼的修改可以很簡單:

Class::Class(QWidget * parent) : QWidget(parent) { 
    ... 
    createVerticalSpeedIndicator() 
    >> createAirSpeedIndicator() 
    >> someOtherTask(); 
} 

async函數現在必須返回一個類,允許進行這樣的連接:

struct TaskTimer { 
    QTimer * timer; 
    TaskTimer & operator>>(const TaskTimer & next) { 
    next.timer->stop(); 
    connect(timer, &QObject::destroyed, next.timer, [timer = next.timer]{ 
     timer->start(0); 
    }); 
    timer = next.timer; 
    return *this; 
    } 
}; 

template <typename F> TaskTimer async(QObject * parent, F && continuation) { 
    TaskTimer task{new QTimer(parent)}; 
    task.timer->start(0); 
    connect(task.timer, &QTimer::timeout, 
      [timer = task.timer, c = std::move(continuation)]{ 
      if (!c()) 
       timer->deleteLater(); 
    }); 
    return task; 
}