Qt多循环同时循环和qApp-> processEvents();

问题描述:

我想要做一个项目是用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

的解决方案是反转控制流。 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; 
}