首页 > 解决方案 > Mac 上的 Qt:app.exec() 阻止终端输入,如何重写这个最小示例?

问题描述

我已经阅读了很多关于此的内容,但我不完全了解如何去做(例如,请参阅如何避免 Qt app.exec() 阻塞主线程)。

下面的代码是我想要实现的一个非常简单的最小示例。对于这个例子:有一个终端,您可以在其中为一个学生输入同一科目的考试成绩。具体来说:学生全年的英语课程表现如何。每次输入学生的成绩时,Qt 图表都会更新并显示进度。

这是我写的代码:

#include <iostream>
#include <vector>

#include <QApplication>
#include <QMainWindow>
#include <QChartView>
#include <QLineSeries>

int main(int argc, char **argv)
{
  QApplication app(argc, argv);

  std::vector<int> examScores;
  int totalExams = 5;

  QtCharts::QLineSeries *series = new QtCharts::QLineSeries();
  QtCharts::QChart *chart = new QtCharts::QChart();
  chart->legend()->hide();
  chart->createDefaultAxes();
  QtCharts::QChartView *chartView = new QtCharts::QChartView(chart);
  chartView->setRenderHint(QPainter::Antialiasing);
  QMainWindow window;
  window.setCentralWidget(chartView);
  window.resize(400, 300);

  for (int i = 1; i <= totalExams; i++)
  {
    std::cout << "Enter score of exam " << i << " ";
    std::string userInput;
    getline(std::cin, userInput);
    int score = std::stoi(userInput);
    examScores.push_back(score);

    series->append(i, score);
    chart->addSeries(series);
    window.show();
    app.exec();
    chart->removeSeries(series);
  }

  return 0;
}

现在,从软件工程的角度来看,这里有很多问题(例如不清理输入等),但我无法解决的是如何重写app.exec();. 我知道它不应该存在,因为它是阻塞的,而且我知道 Qt 不应该以这种方式编写。

所以我想知道:您将如何重写此示例以实现app.exec();非阻塞并允许程序始终在终端上接收用户输入?

标签: c++macosqt

解决方案


这就是我如何将它放入自己的线程,同时仍然能够处理 CLI 输入。从代码审查的角度来看,这段代码仍然有很多问题,但基本功能(将其放入不同的线程)是有效的。

#include <iostream>
#include <vector>
#include <thread>

#include <QApplication>
#include <QMainWindow>
#include <QChartView>
#include <QLineSeries>

std::vector<int> examScores;

void pollForUserInput(QtCharts::QLineSeries *series, int totalExams)
{
  for (int i = 1; i <= totalExams; i++)
  {
    std::cout << "\nEnter score of exam " << i << " " << std::endl;
    std::string userInput;
    getline(std::cin, userInput);
    int score = std::stoi(userInput);
    examScores.push_back(score);
    series->append(i, score);
  }

  std::cout << "done" << std::endl;
}

int main(int argc, char **argv)
{
  QApplication app(argc, argv);

  QtCharts::QLineSeries *series = new QtCharts::QLineSeries();
  int totalExams = 5;
  std::thread t1(pollForUserInput, series, totalExams);

  QtCharts::QChart *chart = new QtCharts::QChart();
  chart->legend()->hide();
  chart->addSeries(series);
  chart->createDefaultAxes();
  chart->axisX()->setRange(1, totalExams); // see https://stackoverflow.com/questions/38804179/how-to-repaint-a-qchart
  chart->axisY()->setRange(1, 10);         // see https://stackoverflow.com/questions/38804179/how-to-repaint-a-qchart
  QtCharts::QChartView *chartView = new QtCharts::QChartView(chart);
  chartView->setRenderHint(QPainter::Antialiasing);
  QMainWindow window;
  window.setCentralWidget(chartView);
  window.resize(400, 300);
  window.show();
  return app.exec();
}

推荐阅读