How to catch window close events?

Hi all,

I discovered VTK recently and I am trying to get used to it for now. Currently I am trying to plot some 2D curves that represents the evolution of the sin and cos functions through time at a given rate. To update both curves I had to write a custom rendering loop in which data are updated, the window is rendered and events are processed. All of this works as expected, however, since I am no longer using vtkRenderWIndowInteractor::Start(), the application no longer terminates when I click on the window close button or when I press Alt+f4. I don’t know how to catch these events to close the application without relying on vtkRenderWIndowInteractor::Start().

Here is the source code (based on the vtkChartXY example)

#include <chrono>

#include <vtkAxis.h>
#include <vtkChartXY.h>
#include <vtkContextScene.h>
#include <vtkContextView.h>
#include <vtkFloatArray.h>
#include <vtkPen.h>
#include <vtkPlot.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkTable.h>


int
  main()
{
  // Create a table with some points in it.
  vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();

  vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
  arrX->SetName("X Axis");
  table->AddColumn(arrX);

  vtkSmartPointer<vtkFloatArray> arrC = vtkSmartPointer<vtkFloatArray>::New();
  arrC->SetName("Cosine");
  table->AddColumn(arrC);

  vtkSmartPointer<vtkFloatArray> arrS = vtkSmartPointer<vtkFloatArray>::New();
  arrS->SetName("Sine");
  table->AddColumn(arrS);

  // Set up the view.
  vtkSmartPointer<vtkContextView> view = vtkSmartPointer<vtkContextView>::New();
  view->GetRenderer()->SetBackground(1.0, 1.0, 1.0);

  // Add multiple line plots, setting the colors etc.
  vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
  view->GetScene()->AddItem(chart);
  vtkPlot* line = chart->AddPlot(vtkChart::LINE);
  line->SetInputData(table, 0, 1);
  line->SetColor(0, 255, 0, 255);
  line->SetWidth(1.0);
  line = chart->AddPlot(vtkChart::LINE);
  line->SetInputData(table, 0, 2);
  line->SetColor(255, 0, 0, 255);
  line->SetWidth(5.0);

  // Save a time origin.
  auto t0 = std::chrono::steady_clock::now();

  // Start the rendering/event loop.
  while (true)
  {
    // Compute the elapsed time since the start of the loop.
    auto t1 = std::chrono::steady_clock::now();
    auto dt
      = std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count()
        / 1e9f;

    // Update data in the table according to the elapsed time.
    int   num_points = 100;
    float time_step = 0.1;
    float rad_per_s = 3.14;
    table->SetNumberOfRows(num_points);
    for (int i = 0; i < num_points; ++i)
    {
      float t = dt + (i * time_step);
      table->SetValue(i, 0, t);
      table->SetValue(i, 1, cos(t * rad_per_s));
      table->SetValue(i, 2, sin(t * rad_per_s));
    }
    table->Modified();

    // Update the X axis.
    auto  axis = chart->GetAxis(vtkAxis::BOTTOM);
    float t_min = dt;
    float t_max = dt + (num_points * time_step);
    axis->SetRange(t_min, t_max);
    axis->Modified();

    // Render and process events.
    view->GetRenderWindow()->Render();
    view->GetInteractor()->ProcessEvents();
  }

  return EXIT_SUCCESS;
}

If you want to process events from the windowing system then you need to pump the application’s event queue. On Windows, you can process pending events (without blocking execution forever) by executing these few lines of code somewhere in your infinite loop: