Simple Window using C++
The sample metavision_simple_window.cpp
shows the basic usage of the Metavision::Window
and Metavision::MTWindow
classes.
The source code of this sample can be found in <install-prefix>/share/metavision/sdk/ui/cpp_samples/simple_window
when installing Metavision SDK from installer or packages. For other deployment methods, check the page
Path of Samples.
Principle of the Window Management Implementation
The Window Management System implemented in the UI module relies on the use of GFLW and OpenGL which allows rendering multiple windows in different threads.
Two kinds of window are available:
a
Metavision::Window
that will be updated on demanda
Metavision::MTWindow
that owns an internal rendering thread allowing a fixed frequency display (synchronized with the screen’s refresh rate)
Note
Both kinds of window can be used from any thread.
The principle works like this: input events from the system are polled from the main thread and then sent
to their corresponding windows using the Metavision::EventLoop::poll_and_dispatch()
function.
Events are automatically polled, and the callbacks associated with them are called, when a window is updated (using
either the Metavision::Window::show()
or Metavision::MTWindow::show_async()
methods).
Events can also be explicitly polled from a window by calling the Metavision::BaseWindow::poll_events()
method.
Warning
To ensure the compatibility across the different platforms, certain operations should exclusively occur within the main thread. These operations are:
window creation and destruction, and
polling the system input events via the
Metavision::EventLoop::poll_and_dispatch()
function
Expected Output
Two resizable windows the user can interact with.
How to start
First, compile the sample as described in this tutorial.
To start the sample, run:
Linux
./metavision_simple_window
Windows
metavision_simple_window.exe
Code Overview
Window Creation
In this sample two windows are created:
a
Metavision::Window
that will render images in GRAY modea
Metavision::MTWindow
that will render images in BGR mode
Metavision::Window w1("Window GRAY", img.cols, img.rows, Metavision::Window::RenderMode::GRAY);
Metavision::MTWindow w2("MTWindow BGR", img.cols, img.rows, Metavision::Window::RenderMode::BGR);
Note
The windows can be resized after creation.
System Events Subscription
The windows can respond to three types of system input events, to which users can subscribe:
the key events, when the user presses a key on the keyboard while the window has the focus
the mouse events, when the user clicks on a mouse’s button while the mouse’s cursor is in the window’s area
the cursor events, when the user moves the mouse’s cursor in the window’s area
In this sample we subscribe to the key and mouse events of the first window:
// An example of a Key callback. It will be called only when a key is pressed while the window 1 has the focus.
w1.set_keyboard_callback([&w1](Metavision::UIKeyEvent key, int scancode, Metavision::UIAction action, int mods) {
if (action == Metavision::UIAction::RELEASE) {
const auto it = key_to_names.find(key);
if (it != key_to_names.end())
MV_LOG_INFO("[KEYBOARD EVENT]") << " " << it->second;
if (key == Metavision::UIKeyEvent::KEY_ESCAPE)
w1.set_close_flag();
}
});
w1.set_mouse_callback([](Metavision::UIMouseButton button, Metavision::UIAction action, int mods) {
if (action == Metavision::UIAction::RELEASE) {
const auto it = button_to_names.find(button);
if (it != button_to_names.cend())
MV_LOG_INFO("[MOUSE EVENT]") << " " << it->second;
}
});
and to the key and cursor events of the second window:
// An example of a mouse cursor callback. It will be called whenever the mouse's cursor is on top of the window 2.
w2.set_cursor_pos_callback(
[](double x, double y) { MV_LOG_INFO("[MOUSE CURSOR EVENT]") << " x:" << x << "y:" << y; });
// Another Key callback called when a key is pressed while the window 2 has the focus.
w2.set_keyboard_callback([&w2](Metavision::UIKeyEvent key, int scancode, Metavision::UIAction action, int mods) {
if (action == Metavision::UIAction::RELEASE && key == Metavision::UIKeyEvent::KEY_ESCAPE)
w2.set_close_flag();
});
The application stops when the ‘ESCAPE’ key is pressed while one of the two windows has the focus.
Using the Windows from any thread
Once instantiated from the main thread, the windows can be used from any thread. In this sample we create a rendering loop in a separate thread for the first window to illustrate that:
// The window 1 will be rendered in a separate thread
auto rendering_thread_w1 = std::thread([&]() {
// Continue until one of the two windows is asked to close
while (!w1.should_close() && !w2.should_close()) {
// This call will:
// - Poll and process the events received by the window 1. The attached callbacks are processed here in this
// thread.
// - Immediately update the displayed image.
w1.show(img1);
// Here we make the window 1 have a 40Hz refresh rate
std::this_thread::sleep_for(std::chrono::milliseconds(25));
}
});
While the second window, which has its own internal rendering thread, is asynchronously updated from the main thread (but it could have been done from any thread as well):
// The window 2 will be updated asynchronously from the main thread (i.e. the image will be updated in the internal
// rendering thread).
// Continue until one of the two windows is asked to close
while (!w1.should_close() && !w2.should_close()) {
// Poll all the events from the system and send them to the corresponding windows' internal queues.
Metavision::EventLoop::poll_and_dispatch();
auto img2 = img.clone();
// This call will:
// - Poll and process the events received by the window 2. The attached callbacks are processed here in the main
// thread.
// - Asynchronously update the displayed image.
w2.show_async(img2);
}
However, as opposed to using the windows from any thread, it is very important for the
Metavision::EventLoop::poll_and_dispatch()
function to be called from the main thread.