简体   繁体   中英

Qt on Mac: app.exec() blocks terminal input, how to rewrite this minimal example?

I have been reading a lot about this, but I don't fully get how to go about it (eg see How to avoid Qt app.exec() blocking main thread ).

The following code is a very naievely written minimal example of what I'm trying to achieve. For the sake of this example: there is a terminal in which you put exam grades for the same subject for one student. Concretely: how a student did for his/her English course over the whole year. Every time you put in the grade of a student, a Qt chart updates and shows the progression.

This is the code I wrote:

#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;
}

Now, there are many issues here from a software engineering perspective (eg not sanitizing input, and so on), but what I can't wrap my head around is how to rewrite app.exec(); . I know it shouldn't be there, since it's blocking, and I know Qt isn't meant to be written this way.

So I'm wondering: how would you rewrite this example in order to make app.exec(); non-blocking and allow the program to receive user input on the terminal at all times?

This is how I put it into its own thread while still being able to handle CLI input. A lot of things are still wrong with this code from a code review perspective, but the basic functionality (putting it into a different thread) works.

#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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM