首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >运行时间循环中从QChart中从QLineSeries中更新QLineSeries

运行时间循环中从QChart中从QLineSeries中更新QLineSeries
EN

Stack Overflow用户
提问于 2018-06-22 22:04:33
回答 2查看 2.7K关注 0票数 1

每当将点添加到附加到QChart的QLineSeries对象时,我希望使它动态更新,但似乎只有在我运行的while循环完成之后才会进行此更新。我在interface.cpp中使用said which循环,它调用一个函数updatePlot(),该函数将数据点添加到行系列中,但这只会在while循环完全完成之后更新图表。这里正在发生的事情的伪代码:

qtwindow.cpp

代码语言:javascript
复制
// Constructor that initializes the series which will be passed into the interface
AlgoWindow::AlgoWindow( ..., TradingInterface* interface, ... ) {

    ...

    QLineSeries* series = new QLineSeries();
    QLineSeries* benchmark = new QLineSeries();

    QChart* chart = new QChart();
    chart->addSeries(series);
    chart->addSeries(benchmark);

    // Also creates custom axes which are attached to each series
    ...
}

// Slot connected to a button signal
void AlgoWindow::buttonClicked() {

    // Runs the backtest 
    interface->runbacktest(..., series, benchmark, ...);
}

interface.cpp

代码语言:javascript
复制
void TradingInterface::runbacktest(..., QtCharts::QLineSeries* algoplot, QtCharts::QLineSeries* benchplot) {

    // Runs a huge while loop that continuously checks for events
    while (continue_backtest) {
        if (!eventsqueue.isEmpty()) {
             // Handle each event for the bar
        } else {
             // All events have been handled for the day, so plot
             updatePlot(algoplot, benchplot);
        }
    }
}

void TradingInterface::updatePlot(QtCharts::QLineSeries *algoseries,
    QtCharts::QLineSeries *benchseries) {

    // Get the date and the information to put in each point
    long date = portfolio.bars->latestDates.back();
    double equitycurve = portfolio.all_holdings.rbegin().operator*().second["equitycurve"];
    double benchcurve = benchmarkportfolio.all_holdings.rbegin().operator*.second["equitycurve"];

    // Append the new points to their respective QLineSeries
    algoseries->append(date * 1000, equitycurve*100);
    benchseries->append(date * 1000, benchcurve*100);
}

这使我没有错误,while循环也完成了,但是只有在runbacktest()退出后才绘制行。然后,它正确地绘制所有数据,但都是一次性的。

我需要做的是,每次添加行时,QChart都会更新,我的猜测是使用某种形式的自定义信号插槽监听器,但我不知道如何做到这一点。如果图形在函数完成后才会更新,那么在QChart框架内是否可能更新呢?

此外,我已经尝试过QChart::update()和QChartView::repaint()。两者产生的结果与没有的结果相同。

编辑:我尝试设置一个新线程,每当数据完成时,它会向主线程发出一个信号,但是它似乎什么也没有改变。在输入所有数据之前,QChart仍然不会更新。我添加了几行来帮助调试,似乎发出信号的函数运行得很好,但是接收信号的插槽函数只在线程完成后才运行。不仅如此,随着睡眠而减慢信号的速度并不会使它缓慢地发生(就像我想的那样),因为QChart仍然拒绝更新,直到addData()的最后更新之后。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-22 22:30:55

要么删除while循环,然后使用计时器一步一步地执行工作。

或者在另一个线程中运行您的runbacktest函数,并在数据准备就绪时发送一个信号来更新UI线程中的QChart

无论哪种方式,您都需要将控制权还给事件循环,以便重新绘制图表。

票数 1
EN

Stack Overflow用户

发布于 2018-06-25 14:24:02

用于运行“连续”操作的Qt成语是使用零持续时间“计时器”。这不是真正的计时器,但Qt称它为计时器。

你可以用大约1毫秒的块来做这个操作。为此,反转控制流。Qt没有为它提供太多的语法糖,但它很容易补救。

转换此代码,它维护一个循环:

代码语言:javascript
复制
for (int i = 0; i < 1000; ++i) {
  doSomething(i);
}

进入此lambda,由事件循环调用:

代码语言:javascript
复制
m_tasks.addTask([this](i = 0) mutable {
  doSomething(i);
  ++i;
  return i < 1000;
});

假设:

代码语言:javascript
复制
class Controller : public QObject {
  Tasks m_tasks;
  ...
};

其中,Tasks类维护要由事件循环执行的任务列表:

代码语言:javascript
复制
class Tasks : public QObject {
  Q_OBJECT
  QBasicTimer timer;
  std::list<std::function<bool()>> tasks;
protected:
  void timerEvent(QTimerEvent *ev) override {
    if (ev->timerId() != timer.timerId())
      return;
    for (auto it = tasks.begin(); it != tasks.end(); ) {
      bool keep = (*it)();
      if (!keep)
        it = tasks.erase(it);
      else
        ++it;
    }
    if (tasks.empty())
      timer.stop();
  }
public:
  using QObject :: QObject;
  template <typename F> void addTask(F &&fun) {
    tasks.emplace_back(std::forward(fun));
    if (!timer.isActive())
      timer.start(0, this);
  }
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50996127

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档