# Getting Started with CVB++, QML, CMake

**URL:** <https://forum.commonvisionblox.com/t/getting-started-with-cvb-qml-cmake/1662>\
**Category:** C++ API\
**Tags:** tutorial, cplusplus\
**Created:** [March 29, 2022, 1:59pm UTC](https://forum.commonvisionblox.com/t/getting-started-with-cvb-qml-cmake/1662 "2022-03-29T13:59:20Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![MarkusTC1](https://avatars.discourse-cdn.com/v4/letter/m/3e96dc/32.png) [@MarkusTC1](https://forum.commonvisionblox.com/u/MarkusTC1)\
**Post date:** [March 29, 2022, 1:59pm UTC](https://forum.commonvisionblox.com/t/getting-started-with-cvb-qml-cmake/1662/1 "2022-03-29T13:59:20Z")

</div>

A quick tutorial for getting started with CVB, QML and CMake. What will you learn from this tutorial? After completing this tutorial you will be able to load and display a camera stream in an application with a simple UI, using C++, QML and CMake.

Before we start with this tutorial make sure that you properly installed:

- the _C++ Desktop Development_ package of [Visual Studio](https://visualstudio.microsoft.com/de/)
- the C++ Microsoft Foundation Classes in Visual Studio
- the Qt Framework
- CMake

If you have never heared of Qt or CMake I strongly suggest reading the online [CVB Manual](https://help.commonvisionblox.com/NextGen/14.0/md_theory_of_operation_appnotes__c_v_b_tutorials.html), which includes a detailed instruction on how to install CMake and Qt.

Now we can finally create our first ever CMake Project. Go to Visual Studio and select _C++_ as language, now you have to search for the _CMake Project_ template and create a new one.

After creating a cmake project we can see an out folder, a cmake list, a cpp file and a header file. In this tutorial we don’t need the header file, thus we delete it.

![Screenshot 1 - Creating a cmake project](https://canada1.discourse-cdn.com/flex027/uploads/commonvisionblox/original/1X/28abff60b9fbf75f493127270865df01c32d5b22.png)

**CMake List**

Lets start out with the CMake list, CMake uses these scripts to generate build files for a specific enviroment. As you can see visual studio already added a minimum required version, the project with the name and an _add\_executable_. This _add\_executable_ is needed to be able to run or debug the program.

```auto
cmake_minimum_required (VERSION 3.8)

project ("Tutorial")

add_executable (Tutorial "Tutorial.cpp")

```

In there you can see the project name and the cpp file, that was already created, written between quotation marks there. To be able to run your program properly you have to make sure that, whenever you add a new cpp file or a header file, you write the name of the cpp or header file in the add\_executable. This should happen automatically when creating a new file, but when deleting a cpp or header it can cause trouble, because its not getting removed automatically.

You can also add _WIN32_ between the project name and the c++ files, this will hide the console and gives the finished application a more polished look. But while developing it can be very useful, because the console shows helpfull error messages.

> **Summary**
>
> ```auto
> cmake_minimum_required (VERSION 3.8)
> 
> project ("Tutorial")
> 
> add_executable (Tutorial WIN32 "Tutorial.cpp")
> 
> ```

Now we have to do three things:

1. Find CVB, so we can use it in our project

```auto
file(TO_CMAKE_PATH "$ENV{CVB}/cmake" CVB_MODULE_PATH)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CVB_MODULE_PATH}")
find_package(CVB REQUIRED COMPONENTS CvbQuick)

```

1. Find Qt, so we can design our UI with Qml

```auto
find_package(Qt5Qml REQUIRED)
find_package(Qt5Quick REQUIRED)

```

1. Link the wanted libraries so we make them usable in our code

```auto
target_link_libraries(${PROJECT_NAME}
  CVB::CvbDriver
  CVB::CvbUI
  Qt5::Qml
  Qt5::Quick
  )

```

That already wraps up our CMake list. Your CMake list should now look like this:

```auto
cmake_minimum_required (VERSION 3.8)

project ("Tutorial")

add_executable (Tutorial WIN32 "Tutorial.cpp")

file(TO_CMAKE_PATH "$ENV{CVB}/cmake" CVB_MODULE_PATH)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CVB_MODULE_PATH}")
find_package(CVB REQUIRED COMPONENTS CvbQuick)

find_package(Qt5OpenGL REQUIRED)
find_package(Qt5Quick REQUIRED)

target_link_libraries(${PROJECT_NAME}
  CVB::CvbDriver
  CVB::CvbUI
  Qt5::Qml
  Qt5::Quick
  )

```

**QML Design**

We continue with the UI design. Right click your project folder on the top right and add a new file. Let´s name this file _mainUI.qml_, as you can see the icon of the file change and its now a qml file.  
Before we can acutally design our UI we need to import two things, QtQuick and CvbQuick.

```auto
import QtQuick 2.3
import CvbQuick 1.0 as CvbQuick

```

Now we can design our UI without any problems, but don´t worry our UI will be very simple. For our UI we only need a CvbQuick ImageView, so lets create it. We start out by giving the ImageView an id, in this case I named it _imageView_.  
After that we name the image property _mainImage_, this is the displayed image, we will later bind to this image from the c++ code.  
Then the anchors.fill is set to _parent_, this means this control is set to the full size of its parent, which will be our main window. So this image view will be displayed full screen inside the application.  
Last but not least we set the uploadmode to CvbQuick.UploadMode.Image, the image mode copies the complete image data, which also includes unvisible parts of the image. This can be very helpful in other, more complex projects.

At the end your UI should look like this:

```auto
import QtQuick 2.3
import CvbQuick 1.0 as CvbQuick

CvbQuick.ImageView
{
   id: imageView
   image : mainImage
   anchors.fill: parent
   uploadMode : CvbQuick.UploadMode.Image
}

```

**C++ Code**

Now we come to the actual code behind our project. We start out by adding the argument variables argc and argv to the main method:

```auto
int main(int argc, char* argv[])

```

Then we create a QApplication inside the main method, here we use are arguments, which we created in the step before, also don´t forget to include _QApplication_ above your main method.

```auto
#include <QApplication>

```

```auto
QApplication app(argc, argv);

```

We then register the qml components for an image display, also don´t forget to include the _image\_view\_item_ header:

```auto
#include <cvb/ui/image_view_item.hpp>

```

```auto
Cvb::UI::ImageViewItem::Register();

```

We then create a QQuickView object, that’s the window where our stream will be shown. We also have to include _QQuickView_, same procedure as every year 😄 :

```auto
#include <QQuickView>

```

```auto
QQuickView view;

```

After we did that lets set the resize mode of our _view_ to _SizeRootObjectToView_, this allows, contrary to SizeViewToRootObject, a smooth animation when resizing the window with the cursor:

```auto
view.setResizeMode(QQuickView::SizeRootObjectToView);

```

We now manually load the ui, qml file by setting the _source to the path_, where our qml file is located (in my case _C:/Users/m.glaser/source/repos/Tutorial/mainUI.qml_). I don’t recommend doing that generally but in this case its ok, for simplicity reasons. A better way is to use a relative path:

```auto
view.setSource(QUrl::fromLocalFile("C:/Users/m.glaser/source/repos/Tutorial/mainUI.qml"));

```

After that we create a variable _context_ and equal it to our view root context, this is the context of our _view_. Don’t forget to include _qmlcontext_:

```auto
#include <QQmlContext>

```

```auto
auto context = view.rootContext();

```

We continue with creating a _controller_, this is used to be able to communicate with our ui:

```auto
Cvb::UI::ImageController imageController;

```

We now set the context property to our previously named _mainImage_ and the image _controller_:

```auto
context->setContextProperty("mainImage", &imageController);

```

Now the context is set but the image controller still does nothing and no picture is currently shown. Before an image is displayed, we need to get a device and a stream.  
We get the device by creating a variable device, we then open the _Cvb Device Factory_ and search for the cvb installpath and open the _mock.vin_, with the help of the _CVB LIT_ macro. We also set the acquisition stack to vin and don´t forget to include the _device factory_ :

```auto
#include <cvb/device_factory.hpp>

```

```auto
auto device = Cvb::DeviceFactory::Open(Cvb::InstallPath() + CVB_LIT("drivers/CVMock.vin"), Cvb::AcquisitionStack::Vin);

```

This example is just for the _mock.vin_ driver but you can load any camera here.  
Now we bind the _image controller_ to the _device image_ by calling the _refresh method_, in there we set the image to the _deviceimage_ and turn the _autorefresh_ mode on:

```auto
imageController.Refresh(device->DeviceImage(), Cvb::UI::AutoRefresh::On);

```

The image is now connected to the ui, but the stream is still not started, meaning we still won’t see an image when starting the application.

Now we create a variable for the _stream_ and set it to the _device stream_. Using the _Stream()_ method without a number in the brackets automatically gets the first stream of the device:

```auto
auto stream = device->Stream();

```

Now the only thing that’s left is running the acquisition. There are two ways, you can either do it with the _stream-\>start()_ and _stream -\>wait()_ method or with a _stream handler_. In this case I am using a _single stream handler_, because we only got one stream. When you got multiple, synchronized streams you should use a _multiple stream handler_, but be careful if the streams/cameras are not perfectly synchronized you can loose images.  
This _single stream handler_ is created and used inside the _stream handler guard_, where we also set the _autorun_ to yes, meaning we are constantly acquiring images.  
The _stream handler guard_ safely stops our stream and acquisition when closing the application. Also make sure that you include the _single stream handler_ header.

```auto
#include <cvb/async/single_stream_handler.hpp>

```

```auto
Cvb::StreamHandlerGuard guard(Cvb::SingleStreamHandler::Create(stream), Cvb::AutoRun::Yes);

```

Last but not least we _resize_ our view, _show_ it, and execute our application by _returning app.exec()_:

```auto
view.resize(640, 480);
view.show();
return app.exec();

```

At the end your main class should look something like this:

```auto
#include <QApplication>
#include <QQuickView>
#include <QQmlContext>

#include <cvb/ui/image_view_item.hpp>
#include <cvb/device_factory.hpp>
#include <cvb/async/single_stream_handler.hpp>
int main(int argc, char* argv[])
{              
                //include QApplication
		QApplication app(argc, argv);

                //include cvb image view item
		Cvb::UI::ImageViewItem::Register();

		QQuickView view;
		view.setResizeMode(QQuickView::SizeRootObjectToView);

		//load qml file according to your UI file path
	       view.setSource(QUrl::fromLocalFile("C:/Users/m.glaser/source/repos/Tutorial/mainUI.qml"));

		//include qqml context
		auto context = view.rootContext();

		Cvb::UI::ImageController imageController;
		context->setContextProperty("mainImage", &imageController);

		//open device, mock.vin in our case
		//include device factory
		auto device = Cvb::DeviceFactory::Open(Cvb::InstallPath() + CVB_LIT("drivers/CVMock.vin"), Cvb::AcquisitionStack::Vin);

		//refresh the image display through the controller object
		//stream still not started
		imageController.Refresh(device->DeviceImage(), Cvb::UI::AutoRefresh::On);

		// get the first stream of the device
		// or use device->Stream(index) to get another stream
		auto stream = device->Stream();

		// There are two ways to run the acquisition:
		// - Either via stream->Start() and stream->Wait() in a separate thread
		// - or via SingleStreamHandler (Run() / Finish())
		//include single stream handler
		Cvb::StreamHandlerGuard guard(Cvb::SingleStreamHandler::Create(stream), Cvb::AutoRun::Yes);

		view.resize(640, 480);
		view.show();
		return app.exec();
}

```

That already wraps up this tutorial 😄 . I hope you found this little tutorial helpful.

---

<div class="post-metadata">

**Author:** ![MarkusTC1](https://avatars.discourse-cdn.com/v4/letter/m/3e96dc/32.png) [@MarkusTC1](https://forum.commonvisionblox.com/u/MarkusTC1)\
**Post date:** [June 2, 2022, 6:44am UTC](https://forum.commonvisionblox.com/t/getting-started-with-cvb-qml-cmake/1662/2 "2022-06-02T06:44:06Z")

</div>

Note to the CMakeList:

I made a mistake there, you need to include Qt5Widgets not OpenGL, sorry for that 😅 .  
This results in the CmakeList looking like this:

```auto
cmake_minimum_required (VERSION 3.8)

project ("Tutorial")

add_executable (Tutorial WIN32 "Tutorial.cpp")

file(TO_CMAKE_PATH "$ENV{CVB}/cmake" CVB_MODULE_PATH)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CVB_MODULE_PATH}")
find_package(CVB REQUIRED COMPONENTS CvbQuick)

find_package(Qt5Widgets REQUIRED)
find_package(Qt5Quick REQUIRED)

target_link_libraries(${PROJECT_NAME}
  CVB::CvbDriver
  CVB::CvbUI
  Qt5::Qml
  Qt5::Quick
  Qt5::Widgets
  )

```

Another note to the main function:

If you initialize the context property after you set the source of the view it results in an error message like this: “ReferenceError: mainImage is not defined”.  
Even though this error occures the application should work as intended.

To solve this error just set the context property before you set the source of the view:

```auto
//include qqml context
	auto context = view.rootContext();

	Cvb::UI::ImageController imageController;
	context->setContextProperty("mainImage", &imageController);

	//load qml file according to your UI file path
	view.setSource(QUrl::fromLocalFile("C:/Users/m.glaser/source/repos/Tutorial/mainUI.qml"));	

```

Sorry if you experienced some inconveniences and have fun coding 😄 .
