<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>GUI Archives | DMC, Inc.</title>
	<atom:link href="https://static.dmcinfo.com/blog/tag/gui/feed/index.xml" rel="self" type="application/rss+xml" />
	<link></link>
	<description></description>
	<lastBuildDate>Fri, 04 Sep 2026 18:58:16 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>

<image>
	<url>https://static.dmcinfo.com/wp-content/uploads/2025/04/site-icon-150x150.png</url>
	<title>GUI Archives | DMC, Inc.</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Setting Up a Light and Versatile Graphics Library (LVGL) Simulator on Your Windows PC Using MSYS2</title>
		<link>https://static.dmcinfo.com/blog/15846/setting-up-a-light-and-versatile-graphics-library-lvgl-simulator-on-your-windows-pc-using-msys2/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Tue, 19 Nov 2024 16:46:45 +0000</pubDate>
				<category><![CDATA[Embedded Development & Programming]]></category>
		<category><![CDATA[graphic user interface]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[LVGL]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/15846/setting-up-a-light-and-versatile-graphics-library-lvgl-simulator-on-your-windows-pc-using-msys2/</guid>

					<description><![CDATA[<p>The Light and Versatile Graphics Library (LVGL) is a free, open-source graphics library providing everything you need to create embedded GUIs with easy-to-use graphical elements, beautiful visual effects, and a low memory footprint. Originally designed for microcontrollers and embedded systems, LVGL can also be run on PCs for simulation purposes, making it incredibly useful for [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/15846/setting-up-a-light-and-versatile-graphics-library-lvgl-simulator-on-your-windows-pc-using-msys2/">Setting Up a Light and Versatile Graphics Library (LVGL) Simulator on Your Windows PC Using MSYS2</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">The <a href="https://lvgl.io/" target="_blank" rel="noreferrer noopener">Light and Versatile Graphics Library</a> (LVGL) is a free, open-source graphics library providing everything you need to create embedded GUIs with easy-to-use graphical elements, beautiful visual effects, and a low memory footprint. Originally designed for microcontrollers and embedded systems, LVGL can also be run on PCs for simulation purposes, making it incredibly useful for developers wanting to write and test their code on a PC before transferring it to an embedded system. Additionally, the PC application can be distributed to team members for easy evaluation of the GUI prior to the custom HMI hardware being ready. In this blog post, we&#8217;ll guide you through a unique approach to setting up a LVGL simulator on your Windows PC using MSYS2.</p>



<h2 id="h-background" class="wp-block-heading">Background</h2>



<p class="wp-block-paragraph">The simulator we&#8217;re going to set up is adapted from an example provided by LVGL at their GitHub repository. It demonstrates how to run LVGL on a PC, allowing you to develop and test your applications without needing any embedded hardware. This approach not only speeds up the development process but also enables easier debugging and testing of your applications.</p>



<h2 id="h-setting-up-your-environment" class="wp-block-heading">Setting Up Your Environment</h2>



<p class="wp-block-paragraph">To run the simulator, you&#8217;ll need Visual Studio Code (VSCode) and CMake. The default project is configured to build on both Linux and MacOS, but for this guide, we&#8217;ll focus on building this project for Windows.</p>



<h3 id="h-install-msys2" class="wp-block-heading">Install MSYS2</h3>



<p class="wp-block-paragraph">The first step is to download and install MSYS2 from <a href="https://www.msys2.org/" target="_blank" rel="noreferrer noopener">their website</a>. MSYS2 is a software distribution and building platform for Windows based on MinGW and Cygwin. It provides a Unix-like environment on Windows and a package management system for installing Unix software.</p>



<h3 id="h-launch-msys2-mingw64" class="wp-block-heading">Launch MSYS2 MINGW64</h3>



<p class="wp-block-paragraph">After installing MSYS2, open the MSYS2 MINGW64 app from your Start menu. This application provides a terminal where you can install the necessary packages.</p>



<h3 id="h-install-required-packages" class="wp-block-heading">Install required packages</h3>



<p class="wp-block-paragraph">In the MSYS2 MINGW64 terminal, you&#8217;ll need to execute a series of commands to update the package database and install the required packages. Run the following commands one by one:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">PowerShell</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>pacman -Syu
pacman -S mingw-w64-x86_64-gcc
pacman -S mingw-w64-x86_64-cmake
pacman -S mingw-w64-x86_64-SDL2
pacman -S mingw-w64-x86_64-gdb</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">pacman -Syu</span></span>
<span class="line"><span style="color: #D4D4D4">pacman -S mingw-w64-x86_64-gcc</span></span>
<span class="line"><span style="color: #D4D4D4">pacman -S mingw-w64-x86_64-cmake</span></span>
<span class="line"><span style="color: #D4D4D4">pacman -S mingw-w64-x86_64-SDL2</span></span>
<span class="line"><span style="color: #D4D4D4">pacman -S mingw-w64-x86_64-gdb</span></span></code></pre></div>



<p class="wp-block-paragraph">These commands install the MinGW-w64 GCC (C/C++ compiler), CMake (open-source, cross-platform build system), SDL2 (used for rendering the LVGL graphics on your PC), and GDB (GNU Debugger) packages.</p>



<h3 id="h-update-your-path" class="wp-block-heading">Update your PATH</h3>



<p class="wp-block-paragraph">To make the installed tools accessible from the command line, add C:\msys64\mingw64\bin to your system&#8217;s PATH environment variable. This step ensures that VSCode and other applications can find and use these tools.</p>



<h3 id="h-clone-the-project-from-github" class="wp-block-heading">Clone the project from GitHub</h3>



<p class="wp-block-paragraph">To ensure a smooth experience, there were a few changes that needed to be made to the default LVGL PC port example project. I have made those modifications and committed them to this forked git repository. This demo assumes that you are using this repository.Please check out the <a href="https://github.com/eddie-hunckler-dmc/lv_port_pc_vscode" type="link" id="https://github.com/eddie-hunckler-dmc/lv_port_pc_vscode" target="_blank" rel="noreferrer noopener">following repository using git</a>.</p>



<p class="wp-block-paragraph">If you have git installed on your system, you can use the following command:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">PowerShell</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>git clone --recursive https://github.com/eddie-hunckler-dmc/lv_port_pc_vscode</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">git clone --recursive https://</span><span style="color: #DCDCAA">github.com</span><span style="color: #D4D4D4">/eddie-hunckler-dmc/lv_port_pc_vscode</span></span></code></pre></div>



<h2 id="h-setting-up-vscode" class="wp-block-heading">Setting Up VSCode</h2>



<p class="wp-block-paragraph">Launch VSCode by double-clicking the `simulator.code-workspace` within the `lv_port_pc_vscode` directory. This will properly set up the workspace with the build and debug tools that were just installed.</p>



<p class="wp-block-paragraph">Additionally, there are two VSCode extensions that you will need to install: <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools" target="_blank" rel="noreferrer noopener">CMake Tools</a> and <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools" target="_blank" rel="noreferrer noopener">C/C++</a>. These are both the official Microsoft extensions. Install these in the Extensions tab of VSCode and enable them.</p>



<p class="wp-block-paragraph">Finally, with all the required tools installed and configured, you can use VSCode to configure, build, run, and debug the LVGL application. See the recording below for an example of how to do this.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/lvgl_demo_windows.gif" alt="Example of the debugging process"/></figure>



<h2 id="h-conclusion" class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">By following these steps, you&#8217;ve successfully set up a LVGL simulator on your Windows PC using MSYS2. This setup allows you to develop and test LVGL applications on your PC, significantly speeding up the development process. The code you write and test on your PC can later be transferred to an embedded system with minimal adjustments, making it a highly efficient way to develop embedded GUI applications.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/lvgl_demo_stm32.gif" alt="Example of a STM32 F4 dev-kit"/></figure>



<p class="wp-block-paragraph">Happy coding and enjoy exploring the capabilities of LVGL on your Windows PC!</p>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step"><strong>Develop and Test LVGL Interfaces Before Hardware Is Ready</strong>.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Explore our <a href="https://static.dmcinfo.com/services/embedded-development-and-embedded-programming/" data-type="page" data-id="431">Embedded Development</a> expertise in LVGL, MSYS2, and embedded user interface design for simulating, debugging, and validating GUIs on Windows.</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>
<p>The post <a href="https://static.dmcinfo.com/blog/15846/setting-up-a-light-and-versatile-graphics-library-lvgl-simulator-on-your-windows-pc-using-msys2/">Setting Up a Light and Versatile Graphics Library (LVGL) Simulator on Your Windows PC Using MSYS2</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Custom Image Provider Implementation in PySide</title>
		<link>https://static.dmcinfo.com/blog/17084/custom-image-provider-implementation-in-pyside/</link>
		
		<dc:creator><![CDATA[DMC]]></dc:creator>
		<pubDate>Thu, 02 Nov 2023 14:34:05 +0000</pubDate>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[PC Application Development]]></category>
		<category><![CDATA[User Interface Design]]></category>
		<category><![CDATA[Computer Vision]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[image rendering]]></category>
		<category><![CDATA[UI]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/17084/custom-image-provider-implementation-in-pyside/</guid>

					<description><![CDATA[<p>Introduction In application development, projects require various depths of involvement. Some projects may need you to interconnect a bunch of trendy frameworks and open-source libraries, while other projects will require full-scale development in a lesser-known framework not even designed for the task at hand. A framework that is particularly interesting to work with that occasionally [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/17084/custom-image-provider-implementation-in-pyside/">Custom Image Provider Implementation in PySide</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 id="h-introduction" class="wp-block-heading">Introduction</h2>



<p class="wp-block-paragraph">In application development, projects require various depths of involvement. Some projects may need you to interconnect a bunch of trendy frameworks and open-source libraries, while other projects will require full-scale development in a lesser-known framework not even designed for the task at hand. A framework that is particularly interesting to work with that occasionally lacks proper documentation is PySide.</p>



<p class="wp-block-paragraph">I’ve had an opportunity to explore some image rendering capabilities of the framework and would like to share some tips and best practice standards for your custom application.</p>



<h2 id="h-image-provider" class="wp-block-heading">Image Provider</h2>



<p class="wp-block-paragraph">Before we dive deeper into the topic, I want to note that I am using PySide6, and the image provider lives under PySide6.QtQuick.</p>



<p class="wp-block-paragraph">See this decent, thorough <a href="https://doc.qt.io/qtforpython-6/PySide6/QtQuick/QQuickImageProvider.html" type="link" id="https://doc.qt.io/qtforpython-6/PySide6/QtQuick/QQuickImageProvider.html" target="_blank" rel="noreferrer noopener">documentation page on the QQuickImageProvider</a> that you may wish to examine to gain a better understanding of the concept. </p>



<p class="wp-block-paragraph">The primary purpose of the image provider is to allow the application to render images from sources other than the standard files. Good examples of such sources are the in-memory data and dynamically generated images.</p>



<p class="wp-block-paragraph">If you simply need to render a pre-existing image in a common format, then I highly recommend looking into the native QML Image component capabilities.</p>



<h2 id="h-setup" class="wp-block-heading">Setup</h2>



<p class="wp-block-paragraph"><strong>Disclosure:</strong> code casing might be inconsistent with what you are used to in Python, but I tried incorporating both QML and Python standards where applicable.</p>



<ul class="wp-block-list">
<li><strong>camelCase</strong> – function names (QML/C++ – inherited function override&nbsp;+ consistency)</li>



<li><strong>PascalCase</strong> – objects (QML/C++ – inherited base class + consistency)</li>



<li><strong>snake_case</strong> – variables (Python – standard)</li>
</ul>



<p class="wp-block-paragraph">To begin custom image provider implementation, you have to instantiate your image provider class that inherits <strong>PySide6.QtQuick.QQuickImageProvider.</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/1-custom-image-provider-definition.png" alt="Custom Image Provider Definition"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 1. custom image provider definition</em></p></p>


<pre class="”brush:python”">
class CustomImageProvider(QQuickImageProvider):
    def __init__(self, image_provider_id: str):
        super().__init__(QQuickImageProvider.ImageType.Image)
        &quot;&quot;&quot;Image provider metadata.&quot;&quot;&quot;
        self.provider_id = image_provider_id

        &quot;&quot;&quot;Image provider data.&quot;&quot;&quot;
        self._images: dict[str, np.ndarray] = dict()

        &quot;&quot;&quot;Suggested utility objects.&quot;&quot;&quot;
        # self.SharedConstants = SharedConstants()
        # self._imageConstructor = ImageConstructor()
        # self._idConstructor = IdConstructor()
</pre>


<p class="wp-block-paragraph">Notice that I created a public property <strong>provider_id.</strong> You do not technically need it, but I highly recommend introducing one, especially if you are anticipating multiple image provider instances. For example, I worked on an app that required multiple tabs to be open in parallel, each with access to an image provider. Since each tab needed its own library of custom images, with image IDs not necessarily <em>globally </em>unique, I had to instantiate a unique image provider per tab to avoid data conflicts. The <strong>provider_id</strong> really helps identify which image provider to use and, more importantly, which image provider can be cleared out for garbage collection purposes as the tab closes.</p>



<p class="wp-block-paragraph">You also need to create a data structure to hold your images. A dictionary has the convenience of id-data mapping. QML will always request an image using a string id and mapping hashable string ids to image data sounds like a perfect opportunity to use a dictionary. To avoid any unexpected behavior, I recommend instantiating the data structure as an internal property and, thus, I called it simply <strong>_images.</strong></p>



<p class="wp-block-paragraph">In the comments I am also suggesting the usage of the following objects:</p>



<ul class="wp-block-list">
<li><strong>SharedConstants</strong> – implement to store and use constants that are shared across the application. Remember, if anything is used in both QML and Python and is ultimately hardcoded, then you should instantiate it as a shared constant, and that constant could be used by both QML and Python. Otherwise, any change to a hardcoded value will become a living nightmare of chasing down all the instances of that value in the code. <strong>Remember, you cannot easily, if at all, debug QML.</strong></li>



<li><strong>ImageConstructor</strong> – use this class to define functions that could be used to construct pixel data that would be stored in the <strong>_images</strong> data structure.</li>



<li><strong>IdConstructor</strong> – use this class to define functions that could be used to construct ids that would be used to store data in the <strong>_images</strong> data structure.</li>
</ul>



<h2 id="h-method-override" class="wp-block-heading">Method Override</h2>



<p class="wp-block-paragraph"><strong>QQuickImageProvider </strong>has <strong>requestPixmap</strong>, <strong>requestImage</strong> and <strong>requestTexture</strong> that you can override&nbsp;to implement your custom functionality. Each method’s signature is similar to the others, so I will focus on the <strong>requestImage</strong> method as I have worked with it the most.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/2-requestimage-override.png" alt="Requestimage Override"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 2. requestImage override</em></p></p>


<pre class="”brush:python”">
    def requestImage(self, image_id: str, size: QSize, requested_size: QSize) -&gt; QImage:
        if (image_id in self._images.keys()) and (self._images[image_id] is not None):
            &quot;&quot;&quot;Retrieve the image data from the image library.&quot;&quot;&quot;
            _pixels = self._images[image_id]

            &quot;&quot;&quot;According to the documentation: 
            In all cases, size must be set to the original size of the image. 
            This is used to set the width and height of the relevant Image if 
            these values have not been set explicitly.&quot;&quot;&quot;
            image_size = QSize(_pixels.shape[1], _pixels.shape[0])
            if size:
                size = image_size

            &quot;&quot;&quot;Construct the size of the returned image.&quot;&quot;&quot;
            width = (
                requested_size.width()
                if requested_size.width() &gt; 0
                else image_size.width()
            )
            height = (
                requested_size.height()
                if requested_size.height() &gt; 0
                else image_size.height()
            )

            &quot;&quot;&quot;Construct the image.&quot;&quot;&quot;
            img = QImage(
                _pixels.data,
                height,
                width,
                QImage.Format_RGBA8888,
            )

            return img
        else:
            raise ValueError(
                self.provider_id
                + &quot; image provider was unable to find image &quot;
                + image_id
            )
</pre>


<p class="wp-block-paragraph">Each of the three methods requires a signature that includes <strong>image_id</strong>, <strong>size</strong> and <strong>requested_size</strong>. It is okay to rename those input variables, but the typing must remain the same. Nevertheless, I do not recommend changing the names.</p>



<ul class="wp-block-list">
<li><strong>image_id</strong> – the string ID of the image by which you will be looking up the pixel data in the defined <strong>_images</strong> data structure.</li>



<li><strong>size</strong> – is not technically used for anything in the Python implementation of the image provider. According to the official documentation: “<em>In all cases, size must be set to the original size of the image. This is used to set the width and height of the relevant Image if these values have not been set explicitly.</em>” This is a remnant of the C++ framework. This variable is passed into this method by reference and must be updated. Every other input is passed in by value.</li>



<li><strong>requested_size</strong> – the size of the <strong>Image</strong> component in QML that requested the image from the custom image provider.</li>
</ul>



<p class="wp-block-paragraph">The return value of the overridden&nbsp;method must be a properly constructed <strong>QImage</strong> that QML will be able to display in the application. Notice that the first input for the <strong>QImage</strong> constructor is a <strong>buffer object pointing to the start of the array’s data</strong>. This is also a C++ memory management quirk that Python has to deal with. The format also plays a big role in image rendering. The current <strong>QImage.Format_RGBA8888</strong> decodes the given data array as though there are four <strong>8-bit unsigned integers for red, green, blue, and alpha channels per pixel</strong>. This is crucial, since, if you provide the wrong array type, the displayed image will either be incorrect or won’t show up at all. QML will not throw an error, so you might spend a lot of time trying to figure out why your image is not rendering. A friend of mine told me this, I am certainly not speaking from experience…</p>



<p class="wp-block-paragraph">The sizing of the image is another topic for discussion. Depending on your implementation, you might want to keep the original size of the image in any rendering case, or, on the contrary, you might always want to resize the image to the window size. Sometimes, you might need to implement the sizing so that it is dynamic and dependent on the window state/size. Basically, what I am saying is that the sizing implementation in the code above is subject to change depending on your application needs; however, you must assign the current image original size to the passed by reference <strong>size</strong> variable.</p>



<h2 id="h-data-management" class="wp-block-heading">Data Management</h2>



<p class="wp-block-paragraph">Now that we’ve implemented the basic image provider functionality, we have to develop data management capabilities. Image data must be somehow stored in the image provider, and, since the data structure <strong>_images</strong> was defined internally, we have to define functions that will allow insertion of the new data into the dictionary as well as its removal.</p>



<p class="wp-block-paragraph">It is also important to implement data validation code that could be broken down into helper functions. This is where you make sure that the data provided for addition could be displayed using the defined <strong>QImage </strong>format.</p>



<p class="wp-block-paragraph">You can also include some of your data manipulation and ID construction code. Basically, this is the perfect opportunity to get the best use out of your predefined <strong>ImageConstructor </strong>and <strong>IdConstructor </strong>objects. You still have to make sure that the data on the output is suitable for the defined <strong>QImage </strong>format.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/3-main-image-provider-management-function.png" alt="Main Image Provider Management Function"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 3. main image provider management function</em></p></p>



<p class="wp-block-paragraph">The following implementation is an example of how you can develop the data removal functionality.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/4-supplemental-management-function.png" alt="Supplemental Management Function"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 4. supplemental management function</em></p></p>


<pre class="”brush:python”">

    def addOrUpdateLayer(self, layer_id: str, pixel_data: np.ndarray) -&gt; dict:
        &quot;&quot;&quot;Data validation and manipulations to prep for the render-ready format&quot;&quot;&quot;
        # Insert your data validation code
        # Insert your data manipulation code

        &quot;&quot;&quot;Map the new data to the desired id and save to the library.&quot;&quot;&quot;
        layer = {layer_id: pixel_data}
        self._images.update(layer)

        return layer

    def removeLayer(self, layer_id: str) -&gt; None:
        &quot;&quot;&quot;Apply key-value pair deletion logic&quot;&quot;&quot;
        del self._images[layer_id]
</pre>


<h2 id="h-helper-functionality" class="wp-block-heading">Helper Functionality</h2>



<p class="wp-block-paragraph">I highly recommend keeping your custom image provider as lightweight as possible for scaling and maintainability purposes; however, you may still want to implement some basic helper functions like:</p>



<ul class="wp-block-list">
<li><strong>isIDTaken</strong> – to check whether a given ID already exists in the image provider to avoid overriding&nbsp;stored data<strong>.</strong></li>



<li><strong>isImageLoaded</strong> – to check whether the data is present in the data structure before querying it.</li>



<li><strong>clearImageProviderInstance</strong> – to manage the memory that the image provider occupies.</li>
</ul>



<p class="wp-block-paragraph">Example implementation for each is presented below:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/5-supplemental-image-provider-functionality.png" alt="Supplemental Image Provider Functionality"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 5. supplemental image provider functionality</em></p></p>


<pre class="”brush:python”">
    def isIDTaken(self, image_id: str) -&gt; bool:
        return image_id in self._images.keys()

    def isImageLoaded(self, image_id: str) -&gt; bool:
        return self._images[image_id] is not None

    def clearImageProviderInstance(self):
        self._qml_engine.removeImageProvider(self._id)
</pre>


<h2 id="h-in-action" class="wp-block-heading">In Action</h2>



<p class="wp-block-paragraph">The following code snippets do not require much explanation but are a good starting point in learning how to use the custom image provider in the scope of any application. Note, we must add an image provider to the application engine.</p>



<p class="wp-block-paragraph">Since we defined the image provider class with a unique ID property, you must provide one to each image provider you insert into the application. Keep in mind that QML engine requires you to provide a unique ID in the first place, so you should just store that ID in the image provider itself.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/6-image-provider-usage-in-an-example.png" alt="Image Provider Usage in an Example"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 6. image provider usage in an example</em></p></p>


<pre class="”brush:python”">
if __name__ == &quot;__main__&quot;:
    &quot;&quot;&quot;Set up the application.&quot;&quot;&quot;
    app = QApplication([])
    engine = QQmlApplicationEngine()

    &quot;&quot;&quot;Instantiate an image provider.&quot;&quot;&quot;
    unique_id = &quot;unique_image_provider_id&quot;
    image_provider = CustomImageProvider(unique_id)
    engine.addImageProvider(unique_id, image_provider)

    &quot;&quot;&quot;Add an image to the image provider.&quot;&quot;&quot;
    image_provider.addOrUpdateLayer(
        &quot;unique_image_id&quot;,
        np.array(
            [
                [
                    [255, 0, 0, 255],
                    [255, 0, 0, 255],
                    [255, 0, 0, 255],
                ],
                [
                    [0, 255, 0, 255],
                    [0, 255, 0, 255],
                    [0, 255, 0, 255],
                ],
                [
                    [0, 0, 255, 255],
                    [0, 0, 255, 255],
                    [0, 0, 255, 255],
                ],
            ],
            dtype=np.uint8,
        ),
    )

    &quot;&quot;&quot;Load and tun the app.&quot;&quot;&quot;
    engine.load(&quot;main.qml&quot;)
    app.exec()
</pre>


<p class="wp-block-paragraph">According to the code above, the example image we are defining has a 3-pixel height and a 3-pixel width. It’s a square of three colored stripes: red, green, blue with full opacity (4<sup>th</sup> alpha channel).</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/7-example-qml-code.png" alt="Example QML Code"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 7. example QML code</em></p></p>


<pre class="”brush:html”">
import QtQuick 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    visible: true
    width: 600
    height: 600
    title: &quot;Custom Image App&quot;

    Image {
        anchors.fill: parent
        // Set the source to the custom image provider.
        // Include the image id if you would like to show a particular image.
        source: &quot;image://unique_image_provider_id/unique_image_id&quot;
    }
}
</pre>


<p class="wp-block-paragraph">I am choosing to keep the QML code fairly simple and straightforward. This code snippet does not necessarily follow any coding standards, but rather serves as a quick and dirty playground to show off some custom image provider capabilities.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/8-produced-result.png" alt="Produced Result"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 8. produced result</em></p></p>



<p class="wp-block-paragraph">The produced result is just as we expected, a stretched out 3&#215;3 pixel image! Notice that the <strong>Image </strong>component anchors onto its parent, so the <strong>requestedSize</strong> will be inherited from the <strong>ApplicationWindow</strong> component size.</p>



<p class="wp-block-paragraph">We could also set the <strong>requestedSize</strong> manually in QML. This way, the size of the constructed image will not change dynamically with the <strong>ApplicationWindow</strong>.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/9-example-of-setting-the-image-size-manually.png" alt="Example of Setting the Image Size Manually"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 9. example of setting the image size manually</em></p></p>


<pre class="”brush:html”">
import QtQuick 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    visible: true
    width: 600
    height: 600
    title: &quot;Custom Image App&quot;

    Image {
        width: 450
        height: 300
        // Set the source to the custom image provider.
        // Include the image id if you would like to show a particular image.
        source: &quot;image://unique_image_provider_id/unique_image_id&quot;
    }
}
</pre>


<p class="wp-block-paragraph">Notice the difference in the newly rendered result:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/10-result-of-setting-the-image-size-manually.png" alt="Result of Setting the Image Size Manually"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 10. result of setting the image size manually</em></p></p>



<h2 id="h-alternative-setup" class="wp-block-heading">Alternative Setup</h2>



<p class="wp-block-paragraph">A less recommended, but valid nonetheless, implementation is to let the custom image provider insert itself into the application upon instantiation.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/11-alternative-custom-image-provider-definition.png" alt="Alternative Custom Image Provider Definition"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 11. alternative custom image provider definition</em></p></p>


<pre class="”brush:python”">
class CustomImageProvider(QQuickImageProvider):
    def __init__(
        self, image_provider_id: str, qml_application_engine: QQmlApplicationEngine
    ):
        super().__init__(QQuickImageProvider.ImageType.Image)
        &quot;&quot;&quot;Image provider metadata.&quot;&quot;&quot;
        self.provider_id = image_provider_id

        &quot;&quot;&quot;Handle image provider self insertion into the application.&quot;&quot;&quot;
        self._qml_application_engine = qml_application_engine
        self._qml_application_engine.addImageProvider(self.provider_id, self)

        &quot;&quot;&quot;Image provider data.&quot;&quot;&quot;
        self._images: dict[str, np.ndarray] = dict()

        &quot;&quot;&quot;Suggested utility objects.&quot;&quot;&quot;
        # self.SharedConstants = SharedConstants()
        # self._imageConstructor = ImageConstructor()
        # self._idConstructor = IdConstructor()
</pre>


<p class="wp-block-paragraph">The following is an example of such an image provider in action.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/12-example-usage-of-the-alternative-cuatom-image-provider.png" alt="Example Usage of the Alternative Custom Image Provider"/></figure>



<p class="wp-block-paragraph"><p style="text-align: center;"><em>Image 12. example usage of the alternative custom image provider</em></p></p>


<pre class="”brush:python”">
if __name__ == &quot;__main__&quot;:
    &quot;&quot;&quot;Set up the application.&quot;&quot;&quot;
    app = QApplication([])
    engine = QQmlApplicationEngine()

    &quot;&quot;&quot;Instantiate an image provider.&quot;&quot;&quot;
    unique_id = &quot;unique_image_provider_id&quot;
    image_provider = CustomImageProvider(unique_id, engine)

    &quot;&quot;&quot;Add an image to the image provider.&quot;&quot;&quot;
    image_provider.addOrUpdateLayer(
        &quot;unique_image_id&quot;,
        np.array(
            [
                [
                    [255, 0, 0, 255],
                    [255, 0, 0, 255],
                    [255, 0, 0, 255],
                ],
                [
                    [0, 255, 0, 255],
                    [0, 255, 0, 255],
                    [0, 255, 0, 255],
                ],
                [
                    [0, 0, 255, 255],
                    [0, 0, 255, 255],
                    [0, 0, 255, 255],
                ],
            ],
            dtype=np.uint8,
        ),
    )

    &quot;&quot;&quot;Load and tun the app.&quot;&quot;&quot;
    engine.load(&quot;main.qml&quot;)
    app.exec()
</pre>


<h2 id="h-notes-and-tips" class="wp-block-heading">Notes and Tips</h2>



<ol class="wp-block-list">
<li>Keep your image provider lightweight. Put all the functionality you think is relevant to it somewhere else, because chances are, it is not. The image provider should really be treated as a data structure that has functionality only to store and remove images.</li>



<li>Make your image provider usable in every place of your application. Avoid putting select-component/window-only functionality in here.</li>



<li>This implementation will also likely work in PySide2 since that is where I originally developed it.</li>
</ol>



<p class="wp-block-paragraph">&nbsp;<b data-stringify-type="bold">Learn more about&nbsp;</b><b data-stringify-type="bold"><a data-sk="tooltip_parent" data-stringify-link="https://static.dmcinfo.com/latest-thinking/blog/id/10393/resizing-uis-with-qml-layouts" delay="150" href="https://static.dmcinfo.com/latest-thinking/blog/id/10393/resizing-uis-with-qml-layouts" rel="noopener noreferrer" target="_blank">Resizing UIs with QML Layouts</a></b><b data-stringify-type="bold">&nbsp;and&nbsp;</b><b data-stringify-type="bold"><a data-sk="tooltip_parent" data-stringify-link="https://static.dmcinfo.com/contact" delay="150" href="https://static.dmcinfo.com/contact" rel="noopener noreferrer" target="_blank">contact us</a></b><b data-stringify-type="bold">&nbsp;today for your next project.</b></p>
<p>The post <a href="https://static.dmcinfo.com/blog/17084/custom-image-provider-implementation-in-pyside/">Custom Image Provider Implementation in PySide</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
