<?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>Mark Locascio, Author at DMC, Inc.</title>
	<atom:link href="https://static.dmcinfo.com/blog/author/markl/feed/index.xml" rel="self" type="application/rss+xml" />
	<link></link>
	<description></description>
	<lastBuildDate>Fri, 21 Aug 2026 15:36:23 +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>Mark Locascio, Author at DMC, Inc.</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Getting Started with NI-DAQmx in Python </title>
		<link>https://static.dmcinfo.com/blog/41611/getting-started-with-ni-daqmx-in-python/</link>
		
		<dc:creator><![CDATA[Mark Locascio]]></dc:creator>
		<pubDate>Wed, 11 Mar 2026 13:00:00 +0000</pubDate>
				<category><![CDATA[Test and Measurement Automation]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/?p=41611</guid>

					<description><![CDATA[<p>National Instruments is&#160;largely known&#160;for LabVIEW, which seamlessly integrates NI’s hardware offerings. However, NI&#160;recognized that engineers like to use the right tool for the job, and that tool&#160;isn’t&#160;always LabVIEW. Consequently, NI has provided&#160;hardware APIs for several languages other than LabVIEW, but there&#160;isn’t&#160;yet the same depth of documentation for those languages as there is for LabVIEW. Python [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/41611/getting-started-with-ni-daqmx-in-python/">Getting Started with NI-DAQmx in Python </a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">National Instruments is&nbsp;largely known&nbsp;for LabVIEW, which seamlessly integrates NI’s hardware offerings. However, NI&nbsp;recognized that engineers like to use the right tool for the job, and that tool&nbsp;isn’t&nbsp;always LabVIEW. Consequently, NI has provided&nbsp;<a href="https://github.com/ni/nidaqmx-python" target="_blank" rel="noreferrer noopener">hardware APIs for several languages other than LabVIEW</a>, but there&nbsp;isn’t&nbsp;yet the same depth of documentation for those languages as there is for LabVIEW. </p>



<p class="wp-block-paragraph">Python currently sits at the top of the heap for data analysis tools, so let’s walk through a quick demo to help you get started with DAQmx in Python. For further reading, <a href="https://static.dmcinfo.com/our-work/ni-data-acquisition-library-and-calibration-utility-in-python/">here’s a case study</a> that describes how we’ve done something very similar for a client who wanted to integrate NI hardware in their existing Python test framework. </p>



<p class="wp-block-paragraph">You can get&nbsp;<a href="https://github.com/marklocascio/python-daqmx-demo" target="_blank" rel="noreferrer noopener">the source code for the demo on&nbsp;GitHub</a>.&nbsp;</p>



<h2 id="h-setting-up-a-python-environment-nbsp" class="wp-block-heading">Setting Up a Python Environment&nbsp;</h2>



<p class="wp-block-paragraph">Already&nbsp;have Python on your PC? Go ahead and <a href="#create">skip this part</a>.&nbsp;We’re&nbsp;going to create a virtual environment with the&nbsp;nidaqmx&nbsp;package installed.&nbsp;For this&nbsp;exercise,&nbsp;I’m&nbsp;assuming that&nbsp;you’ve&nbsp;got a Windows PC with DAQmx and MAX installed already.&nbsp;</p>



<ol class="wp-block-list">
<li><a href="https://www.python.org/downloads/" target="_blank" rel="noreferrer noopener">Install&nbsp;python&nbsp;on your system</a>, if it&nbsp;isn&#8217;t&nbsp;already installed.
<ul class="wp-block-list">
<li>I prefer to install it from a standalone installer rather than the install manager.</li>



<li>For this demo, version 3.10 or newer will work&nbsp;just fine.</li>



<li>When I install, I pick several nonstandard options from the &#8220;Customize Installation&#8221; menu.
<ul class="wp-block-list">
<li>I&nbsp;<em>do not</em>&nbsp;add python.exe to&nbsp;PATH&nbsp;(I like to explicitly call the version I want to use).</li>



<li>I&nbsp;<em>do not</em>&nbsp;install the&nbsp;py&nbsp;launcher, for the same reason.</li>



<li>I&nbsp;<em>do</em>&nbsp;install&nbsp;for all users.</li>



<li>I put every version in&nbsp;C:\pythons, for example,&nbsp;C:\pythons\python3_10,&nbsp;C:\pythons\python3_12, etc.&nbsp;</li>
</ul>
</li>



<li>No matter how you choose to install, find the path to the python interpreter (python.exe) that got installed.&nbsp;</li>
</ul>
</li>



<li>Next, create a virtual environment in the source directory.
<ul class="wp-block-list">
<li>The concept of a “virtual environment” and its many benefits are not in the scope of this blog, but if&nbsp;you&#8217;re&nbsp;a beginner, just take my word for it that you want to do this.</li>



<li>Get&nbsp;<a href="https://github.com/marklocascio/python-daqmx-demo" target="_blank" rel="noreferrer noopener">the source code from&nbsp;GitHub</a>, then navigate to that directory in PowerShell.</li>



<li>In PowerShell, run&nbsp;C:\pythons\python3_10\python.exe -m&nbsp;venv&nbsp;venv.</li>



<li>Replace the path to&nbsp;python.exe&nbsp;with the path you used.</li>
</ul>
</li>



<li>Activate the virtual environment:&nbsp;.\venv\Scripts\activate.&nbsp;</li>



<li>Install the required packages from&nbsp;<a href="https://pypi.org/" target="_blank" rel="noreferrer noopener">pypi</a>:&nbsp;(venv) PS&gt; pip install -r requirements.txt.</li>
</ol>



<p class="wp-block-paragraph">That’s&nbsp;it!&nbsp;</p>



<h2 id="create" class="wp-block-heading">Create a DAQmx Task in NI MAX&nbsp;</h2>



<p class="wp-block-paragraph">First, we will create a simulated device in&nbsp;NI MAX and&nbsp;create a task that&nbsp;acquires&nbsp;data from that device. If you have real NI hardware that&nbsp;you’d&nbsp;prefer to use, create a task that uses&nbsp;it,&nbsp;and&nbsp;I’ll&nbsp;meet you in the <a href="#labview">next section</a>.&nbsp;</p>



<p class="wp-block-paragraph">In MAX, right-click “Devices and Interfaces” and then click “Create New.”&nbsp;</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="380" height="174" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/Devices-and-Interfaces.png" alt="Devices and Interfaces display" class="wp-image-41645" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/Devices-and-Interfaces.png 380w, https://static.dmcinfo.com/wp-content/uploads/2026/02/Devices-and-Interfaces-300x137.png 300w" sizes="(max-width: 380px) 100vw, 380px" /></figure>



<p class="wp-block-paragraph">Select “Simulated NI-DAQmx Device or Modular Instrument” from the list, then click “Finish.” The “Create Simulated NI-DAQmx Device” window will appear, from which you can select a model. I will choose&nbsp;<a href="https://www.ni.com/en-us/shop/model/cdaq-9174.html" target="_blank" rel="noreferrer noopener">the cDAQ-9174</a>.&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="339" height="416" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/Create-Simulated-DAQmx-Device.png" alt="Create Simulated DAQmx Device display" class="wp-image-41647" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/Create-Simulated-DAQmx-Device.png 339w, https://static.dmcinfo.com/wp-content/uploads/2026/02/Create-Simulated-DAQmx-Device-244x300.png 244w" sizes="(max-width: 339px) 100vw, 339px" /></figure>



<p class="wp-block-paragraph">The simulated device will now appear&nbsp;in&nbsp;the list. Click it, then select “Configure Simulated&nbsp;cDAQ&nbsp;Chassis” to add simulated modules.&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="660" height="281" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/Configure-Simulated-cDAQ-Chassis.png" alt="Configure Simulated cDAQ Chassis display" class="wp-image-41649" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/Configure-Simulated-cDAQ-Chassis.png 660w, https://static.dmcinfo.com/wp-content/uploads/2026/02/Configure-Simulated-cDAQ-Chassis-300x128.png 300w" sizes="(max-width: 660px) 100vw, 660px" /></figure>



<p class="wp-block-paragraph">The “Simulated Chassis Configuration” window will appear, and you can add, say,&nbsp;<a href="https://www.ni.com/en-us/shop/model/ni-9213.html" target="_blank" rel="noreferrer noopener">a 9213 thermocouple module</a>.&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="286" height="175" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/Simulated-Chassis-Configuration.png" alt="Simulated Chassis Configuration display" class="wp-image-41651"/></figure>



<p class="wp-block-paragraph">Now that&nbsp;you’ve&nbsp;got simulated hardware set up, you can create a DAQmx task the way you ordinarily would. Expand “Data Neighborhood,” then right-click “NI-DAQmx Tasks” and click “Create New NI-DAQmx Task…”&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="498" height="202" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/Create-new-DAQmx-Task.png" alt="Create New DAQmx Task display" class="wp-image-41653" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/Create-new-DAQmx-Task.png 498w, https://static.dmcinfo.com/wp-content/uploads/2026/02/Create-new-DAQmx-Task-300x122.png 300w" sizes="(max-width: 498px) 100vw, 498px" /></figure>



<p class="wp-block-paragraph">Expand “Acquire Signals,” then “Analog Input,” then “Temperature,” and select “Thermocouple.”&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="575" height="271" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/Create-New-Thermocouple.png" alt="Create New Thermocouple display" class="wp-image-41654" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/Create-New-Thermocouple.png 575w, https://static.dmcinfo.com/wp-content/uploads/2026/02/Create-New-Thermocouple-300x141.png 300w" sizes="(max-width: 575px) 100vw, 575px" /></figure>



<p class="wp-block-paragraph">MAX will list every available thermocouple channel on all connected hardware. If you have a lot of&nbsp;attached hardware, look for the 9213 in your simulated&nbsp;cDAQ. Select a single analog input channel (ai0 in this image) and click “Next.”&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="580" height="212" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/Select-Physical-Channel.png" alt="Select Physical Channel display" class="wp-image-41655" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/Select-Physical-Channel.png 580w, https://static.dmcinfo.com/wp-content/uploads/2026/02/Select-Physical-Channel-300x110.png 300w" sizes="(max-width: 580px) 100vw, 580px" /></figure>



<p class="wp-block-paragraph">Then you will be prompted for a task name.&nbsp;I’ll&nbsp;just leave it as the default (“MyTemperatureTask”) and click “Finish.”&nbsp;</p>



<h2 id="labview" class="wp-block-heading">The LabVIEW Implementation&nbsp;</h2>



<p class="wp-block-paragraph">The completed VI is available in&nbsp;<a href="https://github.com/marklocascio/python-daqmx-demo" target="_blank" rel="noreferrer noopener">this&nbsp;GitHub&nbsp;repository</a>&nbsp;(demo.vi). The block diagram looks like this:&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="263" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/LabVIEW-Block-Diagram.png" alt="LabVIEW Block Diagram" class="wp-image-41657" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/LabVIEW-Block-Diagram.png 900w, https://static.dmcinfo.com/wp-content/uploads/2026/02/LabVIEW-Block-Diagram-300x88.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/02/LabVIEW-Block-Diagram-768x224.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">I’ll&nbsp;walk through this step-by-step, but&nbsp;I’m&nbsp;assuming that you can already read and understand basic LabVIEW code.&nbsp;</p>



<p class="wp-block-paragraph">First, I get a reference to my task (MyTemperatureTask) and I configure sample timing. I want the acquisition to run until some&nbsp;condition occurs, so I set it as a&nbsp;continuously&nbsp;sampling task. I set the sample rate to 1000 Hz, and I plan to grab data from the device twice a second (I call this the “acquisition rate,” and set it to 2 Hz). </p>



<p class="wp-block-paragraph">When you run a continuous task, the “samples per channel” input of the timing VI&nbsp;<em>really</em>&nbsp;means “create a memory buffer large enough for this many samples.” If I plan to sample at 1 kHz and grab data from the buffer every half-second, then nominally every time I grab data, I should get 500 samples. In a perfect world, if I sized the buffer&nbsp;at&nbsp;500 samples, it would always be full but would never overflow when I go to read the data.&nbsp;In reality, your&nbsp;PC has a lot to manage, so I make my buffer 10x larger than the nominal case (hence the “buffer multiplier”).&nbsp;</p>



<p class="wp-block-paragraph">Next, I start the task, and I&nbsp;immediately&nbsp;start looping. On every iteration of the loop, I read 500 samples. If there are more available in the buffer, they stay there until the next iteration. If there are fewer available, the DAQmx Read VI will block until they become available (up to the default timeout of 10 seconds). The Read VI therefore throttles the loop so that it runs at 2&nbsp;Hz and&nbsp;will catch up if it falls&nbsp;behind&nbsp;and samples temporarily pile up in the buffer.&nbsp;</p>



<p class="wp-block-paragraph">For some reason, simulated temperature tasks provide impossibly low temperatures. Literally. Most of the data is colder than absolute zero. Since the task provides data in degrees Celsius,&nbsp;we’ll&nbsp;do a simple analysis, just waiting for the data to get warm enough to enable molecular motion, then we exit the loop, stop the task, and clean up.&nbsp;</p>



<h2 id="h-the-python-implementation-nbsp" class="wp-block-heading">The Python Implementation&nbsp;</h2>



<p class="wp-block-paragraph">The completed script is available in&nbsp;<a href="https://github.com/marklocascio/python-daqmx-demo" target="_blank" rel="noreferrer noopener">this&nbsp;GitHub&nbsp;repository</a>&nbsp;(demo.py).&nbsp;</p>



<p class="wp-block-paragraph">To do the same thing in Python that we did in LabVIEW, all we need to do is tip that VI on its side:&nbsp;</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="900" height="830" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/side-by-side.png" alt="VI on its side" class="wp-image-41642" style="width:600px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/side-by-side.png 900w, https://static.dmcinfo.com/wp-content/uploads/2026/02/side-by-side-300x277.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/02/side-by-side-768x708.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">We&nbsp;do all&nbsp;the same things in the same order! You can retrieve a reference to your task using&nbsp;</p>



<p class="wp-block-paragraph"><strong>task =&nbsp;PersistedTask(task_name).load()&nbsp;</strong></p>



<p class="wp-block-paragraph">The&nbsp;<strong>nidaqmx.errors</strong>&nbsp;module provides a&nbsp;<strong>DaqError</strong>&nbsp;exception that you can use to ensure the task was found. Next, you can call the&nbsp;<strong>task.timing.cfg_samp_clk_timing()</strong>&nbsp;method to configure the task&nbsp;<strong>timing</strong>&nbsp;(note that&nbsp;it’s&nbsp;a method of the timing property of&nbsp;<strong>task</strong>).&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="332" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Timing-1.png" alt="DAQmx Timing display" class="wp-image-41773" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Timing-1.png 900w, https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Timing-1-300x111.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Timing-1-768x283.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">The task is started using&nbsp;<strong>task.start()</strong>. Nothing interesting there:&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="224" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Start-Task.vi_.png" alt="DAQmx Start Task display" class="wp-image-41664" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Start-Task.vi_.png 900w, https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Start-Task.vi_-300x75.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Start-Task.vi_-768x191.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">The&nbsp;<strong>while</strong>&nbsp;loop is similarly straightforward. Like the LabVIEW code, we stop looping early if there is an error when we call the DAQmx Read VI.&nbsp;<strong>task.read()</strong>&nbsp;also uses the same default value for the timeout (10 seconds) as the LabVIEW VI.&nbsp;</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="896" height="962" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/While-Loop.png" alt="DAQmx While loop display" class="wp-image-41666" style="width:600px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/While-Loop.png 896w, https://static.dmcinfo.com/wp-content/uploads/2026/02/While-Loop-279x300.png 279w, https://static.dmcinfo.com/wp-content/uploads/2026/02/While-Loop-768x825.png 768w" sizes="(max-width: 896px) 100vw, 896px" /></figure>



<p class="wp-block-paragraph">Once the loop ends, we just do some cleanup and&nbsp;we’re&nbsp;done!&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="900" height="153" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Loop-End.png" alt="While loop end display" class="wp-image-41668" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Loop-End.png 900w, https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Loop-End-300x51.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/02/DAQmx-Loop-End-768x131.png 768w" sizes="(max-width: 900px) 100vw, 900px" /></figure>



<p class="wp-block-paragraph">When you run the demo script in PowerShell, it will&nbsp;look something&nbsp;like this:&nbsp;</p>



<figure class="wp-block-image size-full"><img decoding="async" width="570" height="308" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/Demo-Script-PowerShell.png" alt="Demo script in PowerShell" class="wp-image-41669" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/Demo-Script-PowerShell.png 570w, https://static.dmcinfo.com/wp-content/uploads/2026/02/Demo-Script-PowerShell-300x162.png 300w" sizes="(max-width: 570px) 100vw, 570px" /></figure>



<h2 id="h-summary-nbsp" class="wp-block-heading">Summary&nbsp;</h2>



<p class="wp-block-paragraph">If you already know how to use DAQmx in LabVIEW, then you know how to use the Python&nbsp;API also! The organization of the library is the only difference, with methods like&nbsp;cfg_samp_clk_timing()&nbsp;living in the&nbsp;timing&nbsp;property of the task object. Once you get over that tiny hurdle,&nbsp;you’re&nbsp;all set to&nbsp;acquire&nbsp;and crunch your numbers all in the same place!&nbsp;</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>From NI-DAQmx integration to complete test systems, DMC delivers solutions.</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">If you&#8217;re interested in how we incorporate <a href="https://static.dmcinfo.com/blog/tag/python/" id="936">Python</a> in our <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/" id="428">Test &amp; Measurement</a> systems, reach out today and learn more about DMC&#8217;s expertise in this service area.</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/41611/getting-started-with-ni-daqmx-in-python/">Getting Started with NI-DAQmx in Python </a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using a QAbstractListModel in QML</title>
		<link>https://static.dmcinfo.com/blog/17671/using-a-qabstractlistmodel-in-qml/</link>
		
		<dc:creator><![CDATA[Mark Locascio]]></dc:creator>
		<pubDate>Mon, 27 Mar 2023 09:36:10 +0000</pubDate>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[PC Application Development]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Qt]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/17671/using-a-qabstractlistmodel-in-qml/</guid>

					<description><![CDATA[<p>The QAbstractListModel class provided by Qt can be used to organize data that will be presented visually as a list or table. Standardizing the interface with an abstract class like QAbstractListModel makes it easy to keep your model data completely isolated from your view (a software design principle known as &#8220;separation of concerns&#8220;). That abstraction [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/17671/using-a-qabstractlistmodel-in-qml/">Using a QAbstractListModel in QML</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">The <code><a href="https://doc.qt.io/qt-6/qabstractlistmodel.html">QAbstractListModel</a></code> class provided by Qt can be used to organize data that will be presented visually as a list or table. Standardizing the interface with an abstract class like <code>QAbstractListModel</code> makes it easy to keep your model data completely isolated from your view (a software design principle known as &#8220;<a href="https://csrc.nist.gov/glossary/term/separation_of_concerns">separation of concerns</a>&#8220;). That abstraction makes it a powerful and flexible tool, but it also makes the learning curve steep.</p>



<p class="wp-block-paragraph">The goal of this post is to provide concrete examples, explanations, and definitions of terms so you can more easily make use of the <code>QAbstractListModel</code> class. For your reference, you can see the complete <a href="https://github.com/marklocascio/qml-listmodel-example">example code on GitHub</a>.</p>



<h2 class="wp-block-heading" id="h-example-gui">Example GUI</h2>



<p class="wp-block-paragraph">Let&#8217;s say we&#8217;ve got a list of devices with which our software interacts. The data we&#8217;ve got for each device is:</p>



<ul class="wp-block-list">
<li>A human-readable name (a string)</li>



<li>A serial number (an integer)</li>



<li>Whether or not the device is currently connected (a Boolean)</li>
</ul>



<p class="wp-block-paragraph">Our example GUI will look like this:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/app.png" alt="Example GUI"/></figure>



<p class="wp-block-paragraph">Part of the appeal of Qt is that you can make extremely slick UIs. We will not be doing that here in order to keep the focus on listmodel concepts. I&#8217;ve resisted the urge to add eye candy for the sake of clarity, and I have crafted the example to make it clear how you <strong><em>could</em></strong> stylize the list if you wanted to.</p>



<p class="wp-block-paragraph">Additionally, the example uses Qt&#8217;s Python bindings (<a href="https://pypi.org/project/PySide6/">PySide6</a>). Everything here is equally applicable to C++, but again, for the sake of simplicity, it is presented as a Python application. The QML is identical in both cases.</p>



<h2 class="wp-block-heading" id="h-the-qml-description">The QML Description</h2>



<p class="wp-block-paragraph">First, we&#8217;ll describe the visualization of our list of devices in QML. The <a href="https://doc.qt.io/qt-6/qml-qtquick-listview.html">QML <code>ListView</code> class</a> is a great start. We&#8217;ll set three properties:</p>



<ul class="wp-block-list">
<li>
<p class="wp-block-paragraph"><code><span style="color:#c00000">model</span></code>: this is what we&#8217;ll use to bind the QML <code>ListView</code> to a <code>QAbstractListModel</code> class defined in C++ or Python</p>
</li>



<li><code><span style="color:#2f5496">delegate</span></code>: this is used to define how each item in the list is rendered as a QML object</li>



<li><code><span style="color:#bf8f00">highlight</span></code>: this is not necessary to use a <code>ListView</code>, but it is generally useful to visualize a selected item in the list</li>
</ul>



<h2 class="wp-block-heading" id="h-basic-example">Basic Example</h2>



<p class="wp-block-paragraph">A rough first draft of the QML might look like this (for the final version, <a href="https://github.com/marklocascio/qml-listmodel-example/blob/main/sample/main.qml">see here</a>):</p>



<p class="wp-block-paragraph"><code><span style="white-space: nowrap;">ListView {<br>
&nbsp;&nbsp;&nbsp;&nbsp;id: deviceList<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#c00000">model: controller.listmodel</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2f5496">delegate: Item {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width: deviceList.width<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Text {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text: "Placeholder"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MouseArea {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anchors.fill: parent<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;}</span>&nbsp;&nbsp;<span style="color:#538135">// Item delegate</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#bf8f00">highlight: Rectangle { color: "lightBlue" }</span><br>
}&nbsp;&nbsp;<span style="color:#538135">// ListView</span></span></code></p>



<h2 class="wp-block-heading" id="h-using-the-model-and-the-delegate">Using the Model and the Delegate</h2>



<p class="wp-block-paragraph">In my <code>main()</code> function, I <a href="https://github.com/marklocascio/qml-listmodel-example/blob/main/sample/__main__.py#L18">set a context property</a> called <code>controller</code> that refers to an instance of my <code>Controller</code> class:</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">Python</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>qml_app_engine = QQmlApplicationEngine()
qml_context = qml_app_engine.rootContext()
controller = Controller(parent=app)
qml_context.setContextProperty("controller", controller)</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">qml_app_engine = QQmlApplicationEngine()</span></span>
<span class="line"><span style="color: #D4D4D4">qml_context = qml_app_engine.rootContext()</span></span>
<span class="line"><span style="color: #D4D4D4">controller = Controller(</span><span style="color: #9CDCFE">parent</span><span style="color: #D4D4D4">=app)</span></span>
<span class="line"><span style="color: #D4D4D4">qml_context.setContextProperty(</span><span style="color: #CE9178">&quot;controller&quot;</span><span style="color: #D4D4D4">, controller)</span></span></code></pre></div>



<p class="wp-block-paragraph">The <code>Controller</code> class <a href="https://github.com/marklocascio/qml-listmodel-example/blob/main/sample/controller.py#L12">exposes a Qt property</a> called <code>listmodel</code>. Note that that property is declared as a <code>QObject</code> in my Python code, and that it does not need a property change signal (i.e., I use <code>constant=True</code>). In the QML above, I bind the <code>ListView</code>&#8216;s <code>model</code> property to the <code>listmodel</code> property of my <code>controller</code> object:</p>



<p class="wp-block-paragraph"><code><span style="color:#c00000">model: controller.listmodel</span></code></p>



<p class="wp-block-paragraph">The <code><span style="color:#2f5496">delegate</span></code> property of <code>ListView</code> is like a template that defines how each item in the list is rendered as a QML object. For the sake of demonstration, we&#8217;ll keep it simple here. I made it a QML <code><a href="https://doc.qt.io/qt-6/qml-qtquick-item.html">Item</a></code> that is as wide as the <code>ListView</code> itself and contains a <code><a href="https://doc.qt.io/qt-6/qml-qtquick-text.html">Text</a></code> object and a <code><a href="https://doc.qt.io/qt-6/qml-qtquick-mousearea.html">MouseArea</a></code>, but you can make it anything you like (you&#8217;ll generally make it much fancier)! For example, you might instead have something like a <code><a href="https://doc.qt.io/qt-6/qml-qtquick-layouts-rowlayout.html">RowLayout</a></code> containing a <code><a href="https://doc.qt.io/qt-6/qml-qtquick-controls2-checkbox.html">Checkbox</a></code>, an <code><a href="https://doc.qt.io/qt-6/qml-qtquick-image.html">Image</a></code>, and a <code><a href="https://doc.qt.io/qt-6/qml-qtquick-text.html">Text</a></code>. (Haven&#8217;t used layouts yet? <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10393/resizing-uis-with-qml-layouts">Start here!</a>) However you want each item in your list to be visualized, you can define it in your <code><span style="color:#2f5496">delegate</span></code>. For simplicity, I often start by just rendering it all in a <code>Text</code> item. We&#8217;ll look at how to access each item of data (name, serial number, and connection status) in the next section.</p>



<p class="wp-block-paragraph">Note also that the <code>MouseArea</code> in my <code><span style="color:#2f5496">delegate</span></code> is used to select an item in the list. Each item in the list is instantiated as a <code><span style="color:#2f5496">delegate</span></code> object, so each item in the list has a <code>MouseArea</code> that can handle click events. We&#8217;ll look at this in more detail later also.</p>



<h2 class="wp-block-heading" id="h-the-qabstractlistmodel-class">The QAbstractListModel Class</h2>



<p class="wp-block-paragraph">If you are managing a large quantity of data and you want to visualize it on your QML GUI, you have a few options. For simple cases, a <a href="https://doc.qt.io/qt-6/qml-qtquick-repeater.html"><code>Repeater</code></a> can usually get the job done just fine and is conceptually very easy to grasp. However, for very large lists, <a href="https://doc.qt.io/qt-6/qml-qtquick-repeater.html#considerations-when-using-repeater">a <code>Repeater</code> is not recommended</a> because it instantiates all visual items at once. In cases where you have a lot of data, you often only want to view or update a small section of it. For these cases, QML provides the <a href="https://doc.qt.io/qt-6/qml-qtquick-listview.html"><code>ListView</code></a> object, which expects to be bound to a <a href="https://doc.qt.io/qt-6/qabstractlistmodel.html">QAbstractListModel</a> object in your C++ or Python application.</p>



<p class="wp-block-paragraph"><code>QAbstractListModel</code> is an abstract class that cannot be instantiated itself, so you need to create a new class that inherits from it and is specialized for your needs. I would first suggest reading the section of its documentation titled <a href="https://doc.qt.io/qt-6/qabstractlistmodel.html#subclassing">&#8220;Subclassing,&#8221;</a> which states that:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">When subclassing QAbstractListModel, you must provide implementations of the <code>rowCount()</code> and <code>data()</code> functions. Well behaved models also provide a <code>headerData()</code> implementation.</p>



<p class="wp-block-paragraph">If your model is used within QML and requires roles other than the default ones provided by the <code>roleNames()</code> function, you must override it.</p>



<p class="wp-block-paragraph">For editable list models, you must also provide an implementation of <code>setData()</code>&nbsp;and implement the <code>flags()</code> function so that it returns a value containing Qt::ItemIsEditable.</p>
</blockquote>



<p class="wp-block-paragraph">It&#8217;s unlikely that those few sentences made it immediately obvious what you need to do. Let&#8217;s start with what confused me most when I got started: the concept of a &#8220;role.&#8221;</p>



<h2 class="wp-block-heading" id="h-roles">Roles</h2>



<p class="wp-block-paragraph">Think about the data we&#8217;re presenting. We have a list of devices, and each device in the list has three pieces of data (name, serial number, and connection status). You might think of each device&#8217;s data as a row in a table:</p>


<table border="0" cellpadding="1" cellspacing="1">
<thead>
<tr>
<th scope="col" style="text-align: left;">Serial Number</th>
<th scope="col" style="text-align: left;">Human-readable name</th>
<th scope="col" style="text-align: left;">Connected?</th>
</tr>
</thead>
<tbody>
<tr>
<td>123</td>
<td>name1</td>
<td>No</td>
</tr>
<tr>
<td>456</td>
<td>name2</td>
<td>Yes</td>
</tr>
<tr>
<td>789</td>
<td>name3</td>
<td>No</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">The simplest analogy is that the &#8220;role&#8221; is the piece of data that goes in each column. You might also think of it as identifying each piece of data in each object in the list. So, we will define our &#8220;roles&#8221; as <code>name</code>, <code>serial</code>, and <code>connected</code>.</p>



<p class="wp-block-paragraph">Notice also that Qt provides a <a href="https://doc.qt.io/qt-6/qt.html#ItemDataRole-enum">built-in <code>ItemDataRole</code> enum</a>. I initially found this very confusing, because it provides roles with names like <code>Qt::DisplayRole</code> and <code>Qt::EditRole</code>, which don&#8217;t really sound like individual data items to me. The built-in roles are intended for use with built-in classes like <code>QString</code> and <code>QIcon</code>, and they don&#8217;t necessarily make sense for this particular custom class, so don&#8217;t let it throw you off. Consider though, that you might have roles (items of data in your class) that aren&#8217;t pieces of data that you&#8217;d want to render as text but are instead pieces of data that determine how the display of that data behaves (like a background color or an icon).</p>



<p class="wp-block-paragraph">Roles that you want to define yourself for your own custom class can use enum values starting with <code>Qt::UserRole</code>, which has value 0x0100 = 256.</p>



<h2 class="wp-block-heading" id="h-an-aside-on-tables">An Aside on Tables</h2>



<p class="wp-block-paragraph">It&#8217;s worth mentioning that there is indeed a <a href="https://doc.qt.io/qt-6/qabstracttablemodel.html"><code>QAbstractTableModel</code></a> class as well. As shown above, we can use the role as the &#8220;second dimension&#8221; of our one-dimensional list, making it look like a table. So, when would you use <code>QAbstract<u>Table</u>Model</code>? You might use it when you have a 2D array of objects, where each object has a set of properties that you identify as &#8220;roles.&#8221;</p>



<p class="wp-block-paragraph">What makes the most sense as a data model will depend on your specific data, and it may be confusing to think about a list in terms of &#8220;rows&#8221; if your data doesn&#8217;t really seem like a table (you may not even arrange items vertically on your UI, which makes the terminology much worse!). We&#8217;re stuck with the &#8220;row&#8221; and &#8220;column&#8221; terminology used by Qt here, but the models can be used in whatever way makes the most sense for the data you need to represent.</p>



<p class="wp-block-paragraph">In most real-life applications (as well as in the example code here), I use a 1D array with multiple roles, because I find that to be the simplest and most natural data structure. However, both <code>QAbstract<u>Table</u>Model</code> and <code>QAbstract<u>Item</u>Model</code> are available to you if you need a more complex visualization of more complex data. Once you get a handle on <code>QAbstract<u>List</u>Model</code>, the more general classes will make more sense.</p>



<h2 class="wp-block-heading" id="h-how-are-roles-used-in-qml">How are Roles Used in QML?</h2>



<p class="wp-block-paragraph">As shown above, you will use the QML <code>ListView</code>&#8216;s model property to specify an object in your C++ or Python code that inherits from <code>QAbstractListModel</code>. The <code><span style="color:#2f5496">delegate</span></code> property is then used to define the QML object that will visualize that data. In this case, each item in the list has three roles (<code>name</code>, <code>serial</code>, and <code>connected</code>), and we&#8217;ll want to access each of those data items in QML independently.</p>



<p class="wp-block-paragraph">Looking at the GUI again:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/app-1.png" alt="GUI example"/></figure>



<p class="wp-block-paragraph">Each item in the list is visualized as a <code>Text</code> item where the content follows this pattern:</p>



<p class="wp-block-paragraph"><code><span style="white-space: nowrap;">[<span style="color:#00b050">index</span> of item]: [<span style="color:#00b050">name</span> role] ([<span style="color:#00b050">serial</span> role]) - [<span style="color:#00b050">connection</span> role]</span></code></p>



<p class="wp-block-paragraph">In our <span style="color:#2f5496"><code>delegate</code></span>, we can access each item of data using the name of the role:</p>



<p class="wp-block-paragraph"><span style="white-space: nowrap;"><code>ListView {<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#c00000">model: controller.listmodel</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2f5496">delegate: Text {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text: `${<span style="color:#00b050">index</span>}: ${<span style="color:#00b050">name</span>} (${<span style="color:#00b050">serial</span>}) - ${<span style="color:#00b050">connected</span> ? "OK" : "NOT FOUND"}`<br>
&nbsp;&nbsp;&nbsp;&nbsp;}</span><br>
}</code></span></p>



<p class="wp-block-paragraph">Inside the <span style="color:#2f5496"><code>delegate</code></span> object we can simply use <span style="color:#00b050"><code>index</code></span>, <span style="color:#00b050"><code>name</code></span>, <span style="color:#00b050"><code>serial</code></span> and <span style="color:#00b050"><code>connected</code></span> as if they are bound to the individual data items inside that element of the list. <span style="color:#00b050"><code>index</code></span> is provided out-of-the-box by <code>ListView</code>, but <span style="color:#00b050"><code>name</code></span>, <span style="color:#00b050"><code>serial</code></span>, and <span style="color:#00b050"><code>connected</code></span> are the <strong><em>names of roles we define ourselves</em></strong>. Within the <span style="color:#2f5496"><code>delegate</code></span> object, we can refer to those names, and our child class of <code>QAbstractListModel</code> will provide methods that QML can use to link those names to specific pieces of data.</p>



<p class="wp-block-paragraph">The <span style="color:#00b050"><code>index</code></span> value is also useful in our <code>MouseArea</code>. We added the <code>MouseArea</code> so that the user could click an item in the list and manipulate it. Since the <code>MouseArea</code> is inside the <span style="color:#2f5496"><code>delegate</code></span>, we have access to the index value. In the <code>MouseArea</code>&#8216;s signal handler <code>onClicked</code>, we will want to set <a href="https://doc.qt.io/qt-6/qml-qtquick-listview.html#currentIndex-prop">the <code>currentIndex</code> property</a> of the <code>ListView</code> to the index of the item in the list that was clicked:</p>



<p class="wp-block-paragraph"><code><span style="white-space: nowrap;">ListView {<br>
&nbsp;&nbsp;&nbsp;&nbsp;id: deviceList<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2f5496">delegate: Item {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MouseArea {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onClicked: deviceList.currentIndex = index<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp; // MouseArea<br>
&nbsp;&nbsp;&nbsp;&nbsp;}</span>&nbsp;&nbsp;<span style="color:#538135">// Item delegate</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#bf8f00">highlight: Rectangle { color: "lightBlue" }</span><br>
}&nbsp;&nbsp;<span style="color:#538135">// ListView</span></span></code></p>



<p class="wp-block-paragraph">Setting the <code>currentIndex</code> of the <code>ListView</code> enables the <code>ListView</code> to automatically animate the <span style="color:#bf8f00"><code>highlight</code></span> object that we defined. When the user clicks an item in the list, it will move the <code>Rectangle</code> to highlight the selected list item.</p>



<p class="wp-block-paragraph">As an exercise for the reader, try making the <span style="color:#2f5496"><code>delegate</code></span> more interesting. Instead of indicating the state of the connected role with just a <code>Text</code>, try using the <code>connected</code> role to set the text color of the <span style="color:#2f5496"><code>delegate</code></span>, or add an icon to each row that indicates whether or not the device is connected.</p>



<h2 class="wp-block-heading" id="h-setting-up-the-roles">Setting Up the Roles</h2>



<p class="wp-block-paragraph">Let&#8217;s circle back to this statement in the documentation:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">If your model is used within QML and requires roles other than the default ones provided by the <code>roleNames()</code> function, you must override it.</p>
</blockquote>



<p class="wp-block-paragraph">We want to use our own role names for this, so we can use names that make sense in our <span style="color:#2f5496"><code>delegate</code></span> (like <code>name</code>, <code>serial</code>, and <code>connected</code>). The mapping from integer role enum values (like <code>Qt::UserRole</code>) to strings of characters is established with the <a href="https://doc.qt.io/qt-6/qabstractitemmodel.html#roleNames"><code>QAbstractItemModel::roleNames()</code></a> method, which your custom listmodel will inherit. All classes that inherit <code>QAbstractListModel</code> need to implement this method, which returns the map from integers to byte arrays. In C++, this map is a <code>QHash&lt;int, QByteArray&gt;</code>, and in Python it is a basic <code>dict</code>. The integer is the role enum value, and the byte array is the string name used in QML to access that role in each item of the listmodel.</p>



<p class="wp-block-paragraph">I like to set up my roles by doing two things: creating an enum (starting with the value <code>Qt::UserRole</code> and incrementing from there) that enumerates my custom roles, and then creating a dictionary that maps the role enum values to byte arrays (the names used by QML to access elements of the model). In our example, I might do:</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">Python</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>class DeviceItemRoles(IntEnum):    
  NAME = Qt.UserRole
  SERIAL = auto()
  CONNECTED = auto()
  _role_names = {
      DeviceItemRoles.NAME: b'name',
      DeviceItemRoles.SERIAL: b'serial',
      DeviceItemRoles.CONNECTED: b'connected'
  }</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: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">DeviceItemRoles</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">IntEnum</span><span style="color: #D4D4D4">):    </span></span>
<span class="line"><span style="color: #D4D4D4">  NAME = Qt.UserRole</span></span>
<span class="line"><span style="color: #D4D4D4">  SERIAL = auto()</span></span>
<span class="line"><span style="color: #D4D4D4">  CONNECTED = auto()</span></span>
<span class="line"><span style="color: #D4D4D4">  _role_names = {</span></span>
<span class="line"><span style="color: #D4D4D4">      DeviceItemRoles.NAME: </span><span style="color: #569CD6">b</span><span style="color: #CE9178">&apos;name&apos;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">      DeviceItemRoles.SERIAL: </span><span style="color: #569CD6">b</span><span style="color: #CE9178">&apos;serial&apos;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">      DeviceItemRoles.CONNECTED: </span><span style="color: #569CD6">b</span><span style="color: #CE9178">&apos;connected&apos;</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span></code></pre></div>



<p class="wp-block-paragraph">Note again that in Python, the values are byte arrays (<code>b''</code>), not strings.</p>



<p class="wp-block-paragraph">With this setup, the delegate of our <code>ListView</code> can access each piece of data in each list item using the strings <code>name</code>, <code>serial</code>, and <code>connected</code>. QML knows how the role integers (from the enum) map to the names because it knows that a <code>QAbstractListModel</code> must have a <code>roleNames()</code> method, so now we just need to give it a way to access each piece of data given the list index and the role. That is the job of the <a href="https://doc.qt.io/qt-6/qabstractitemmodel.html#data"><code>QAbstractItemModel::data()</code></a> method, which we will get to shortly.</p>



<h2 class="wp-block-heading" id="h-subclassing-a-qabstractlistmodel">Subclassing a QAbstractListModel</h2>



<p class="wp-block-paragraph">Recall from the <a href="https://doc.qt.io/qt-6/qabstractlistmodel.html#subclassing">documentation</a> that subclasses of <code>QAbstractListModel</code> need to implement the <code>rowCount()</code> and <code>data()</code> methods, plus <code>roleNames()</code> if the listmodel is used in QML. We&#8217;ll cover these one-by-one, but first let&#8217;s define how we&#8217;ll store our data.</p>



<h2 class="wp-block-heading" id="h-data-storage">Data Storage</h2>



<p class="wp-block-paragraph">I find that the easiest way to store the data (for a Python application) is with a list of dictionaries, where each dictionary uses the role enum as the key for each data value. This is by no means the only way, but it is very simple and often sufficient. So, you might start developing your custom listmodel class like this:</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(2 * 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">Python</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>class DeviceListModel(QAbstractListModel):

    def __init__(self):

        super().__init__()

        self._data = []



    def add_device(self, name, serial, connected):

        new_row = {

            DeviceItemRoles.NAME: name,

            DeviceItemRoles.SERIAL: serial,

            DeviceItemRoles.CONNECTED: connected

        }



        self._data.append(new_row)</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: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">DeviceListModel</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">QAbstractListModel</span><span style="color: #D4D4D4">):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">__init__</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #4EC9B0">super</span><span style="color: #D4D4D4">().</span><span style="color: #DCDCAA">__init__</span><span style="color: #D4D4D4">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">._data = []</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">add_device</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">name</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">serial</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">connected</span><span style="color: #D4D4D4">):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        new_row = {</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            DeviceItemRoles.NAME: name,</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            DeviceItemRoles.SERIAL: serial,</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            DeviceItemRoles.CONNECTED: connected</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">._data.append(new_row)</span></span></code></pre></div>



<p class="wp-block-paragraph">When we create a new listmodel, the list of data, <code>self._data</code>, is just an empty list. We can then add device data to the list with the <code>add_device()</code> method, which takes the name, serial number, and connection status, puts them in a dictionary with the appropriate role enum values as keys, and then appends that dictionary to the data list.</p>



<p class="wp-block-paragraph">Now that we&#8217;ve established how the data is stored, we can fill out the required methods.</p>



<h2 class="wp-block-heading" id="h-the-rolenames-method">The roleNames() Method</h2>



<p class="wp-block-paragraph"><code>roleNames()</code> is the easiest to implement, because it&#8217;s already done! The <code>_role_names</code> dictionary from above is exactly what <code>roleNames()</code> should return, so this one&#8217;s a no-brainer:</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">Python</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>def roleNames(self):
    return _role_names</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: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">roleNames</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">):</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> _role_names</span></span></code></pre></div>



<p class="wp-block-paragraph">That&#8217;s it!</p>



<h2 class="wp-block-heading" id="h-the-rowcount-method">The rowCount() Method</h2>



<p class="wp-block-paragraph"><code>rowCount()</code> is similarly straightforward. The number of rows is just the number of elements in our <code>self._data</code> list. We don&#8217;t need to do much here either:</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">Python</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>def rowCount(self, parent=QModelIndex()):
    return len(self._data)</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: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">rowCount</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">parent</span><span style="color: #D4D4D4">=QModelIndex()):</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">len</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">._data)</span></span></code></pre></div>



<p class="wp-block-paragraph">The only thing to address is that weird <code>parent</code> argument. What&#8217;s that about?</p>



<p class="wp-block-paragraph">It comes from the base class, <code>QAbstract<u>Item</u>Model</code>. The base class is more general. Whereas <code>QAbstract<u>List</u>Model</code> represents a one-dimensional list of items that all have the same type of elements, <code>QAbstract<u>Item</u>Model</code> can describe trees and other complex hierarchical structures. In those cases, you need to provide the index of a parent object in the tree so the <code>rowCount()</code> method can return the number of children <strong><em>of that parent</em></strong>. Once you get your bearings with the <code>QAbstract<u>List</u>Model</code>, you can dig into the <code>QAbstract<u>Item</u>Model</code>, but for now, let&#8217;s just ignore <code>parent</code>, because it doesn&#8217;t apply to a one-dimensional list. Just give it a default <code>QModelIndex</code>.</p>



<h2 class="wp-block-heading" id="h-the-data-method">The data() Method</h2>



<p class="wp-block-paragraph">Finally, we need to implement a method that will return data values when QML asks for them. <a href="https://doc.qt.io/qt-6/qabstractitemmodel.html#data">The C++ signature of this method is:</a></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">C++</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>QVariant QAbstractItemModel::data(const QModelIndex &amp;index, int role = Qt::DisplayRole) const</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: #4EC9B0">QVariant</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">QAbstractItemModel</span><span style="color: #D4D4D4">::</span><span style="color: #DCDCAA">data</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">QModelIndex</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">&amp;</span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">int</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">role</span><span style="color: #D4D4D4"> = </span><span style="color: #4EC9B0">Qt</span><span style="color: #D4D4D4">::</span><span style="color: #4EC9B0">DisplayRole</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">const</span></span></code></pre></div>



<p class="wp-block-paragraph">So, our implementation of the method needs to take the index of the row we want (as a <code>QModelIndex</code> object) and the role of the individual data item we want (as an integer, like our convenient <code>DeviceItemRoles</code> enum), and it will return the data as a <code>QVariant</code>. With the PySide6 bindings, there is no <code>QVariant</code>. We can return whatever Python object we want, and if there&#8217;s no data at that index or with that role, we can just return <code>None</code>. A simple implementation in Python looks like:</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(2 * 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">Python</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>def data(self, index, role):

    if role not in list(DeviceItemRoles):

        return None



    try:

        device = self._data&#91;index.row()&#93;

    except IndexError:

        return None



    if role in device:

        return device&#91;role&#93;

    return None</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: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">data</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">role</span><span style="color: #D4D4D4">):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> role </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">list</span><span style="color: #D4D4D4">(DeviceItemRoles):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">None</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">try</span><span style="color: #D4D4D4">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        device = </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">._data&#91;index.row()&#93;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">except</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">IndexError</span><span style="color: #D4D4D4">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">None</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> role </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> device:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> device&#91;role&#93;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">None</span></span></code></pre></div>



<p class="wp-block-paragraph">There&#8217;s a little more meat here than in our <code>roleNames()</code> and <code>rowCount()</code> methods. First, we check that the role integer that was passed in is an item in our <code>DeviceItemRoles</code> enum. If it isn&#8217;t, then something is looking for a role we aren&#8217;t providing, so we&#8217;ll just return <code>None</code>.</p>



<p class="wp-block-paragraph">Next, we&#8217;ll try to get the index of the item in the list. Note that you can&#8217;t index the <code>self._data</code> list using the <code>index</code> argument directly. You need to call <code>index.row()</code>, which is a consequence of the fact that <code>QAbstract<u>List</u>Model</code> is a child of the more general <code>QAbstract<u>Item</u>Model</code> class, which is not necessarily a 1D list. If you look at the <a href="https://doc.qt.io/qt-6/qmodelindex.html"><code>QModelIndex</code></a> class, you&#8217;ll see that, in addition to <code>row()</code>, it also provides <code>column()</code>, as well as various other methods that only apply to more complex structures.</p>



<p class="wp-block-paragraph">Anyway, if the given index is out of bounds, then something is looking for an invalid row, and we return <code>None</code>. Beyond that, both the index and the role are ok, so we return the appropriate value by indexing the list to get a dictionary, and then looking up the value of the role key in that dictionary. Whatever data was stored there gets returned.</p>



<h2 class="wp-block-heading" id="h-updating-inserting-and-removing-data">Updating, Inserting, and Removing Data</h2>



<p class="wp-block-paragraph">What was implemented above is sufficient for a listmodel that will never change, but that&#8217;s probably in the minority of use cases. If you only have a small-ish amount of static data, it would probably be easier to use a <code>Repeater</code>. More likely, you&#8217;ll want to add data to your list, remove data, or change data at runtime, and <code>QAbstractListModel</code> is a much better fit in these situations. In order to manipulate our list contents, we need to understand a few additional concepts.</p>



<h2 class="wp-block-heading" id="h-signaling-changes-to-existing-row-data-from-the-application">Signaling Changes to Existing Row Data from the Application</h2>



<p class="wp-block-paragraph">In general, when we bind properties to QML, we provide a signal that we emit when the property changes. QML listens for that signal, and when it gets emitted, it calls the property getter to refresh the value. This is done by a <code>QAbstractListModel</code> by using the <a href="https://doc.qt.io/qt-6/qabstractitemmodel.html#dataChanged"><code>dataChanged</code> signal</a> provided by its parent, <code>QAbstract<u>Item</u>Model</code>, which specifies which elements of the model changed (in terms of rows, columns, and roles).</p>



<p class="wp-block-paragraph">In some cases, you need to emit this signal yourself. For example, we might want our listmodel class to have a method that <a href="https://github.com/marklocascio/qml-listmodel-example/blob/main/sample/device_listmodel.py#L73">sets all devices to &#8220;disconnected.&#8221;</a> That would look like:</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">Python</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>def set_all_disconnected(self):

    for d in self._data:

        d&#91;DeviceItemRoles.CONNECTED&#93; = False

    self.dataChanged.emit(self.index(0), self.index(self.rowCount() - 1), [])</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: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">set_all_disconnected</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> d </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">._data:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        d&#91;DeviceItemRoles.CONNECTED&#93; = </span><span style="color: #569CD6">False</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.dataChanged.emit(</span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.index(</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">), </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.index(</span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.rowCount() - </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">), [])</span></span></code></pre></div>



<p class="wp-block-paragraph">In this method, we first loop over all items in the data list and set the <code>connected</code> value to <code>False</code>. Then, we only need to emit a single signal that says that all items in the list have changed (i.e., every index from 0 to <code>rowCount() - 1</code>). The empty list in the last parameter of the signal is a list of roles that changed, which can be left empty to indicate that all roles have changed. In this case, you can specify <code>[DeviceItemRoles.CONNECTED]</code> if you prefer. This only makes a difference if you have many roles.</p>



<h2 class="wp-block-heading" id="h-signaling-changes-to-the-collection-of-rows">Signaling Changes to the Collection of Rows</h2>



<p class="wp-block-paragraph">Even if you don&#8217;t <strong><em>change any existing data</em></strong>, you might <strong><em>add or remove entire rows</em></strong>, and QML will need to know what to update when that happens. In this case, we use a pair of methods, <code>beginInsertRows()</code> and <code>endInsertRows()</code>, to specify that we&#8217;re adding data (and how many rows we&#8217;re adding).</p>



<p class="wp-block-paragraph">Let&#8217;s say we want to add a new element to the list after the selected index. <a href="https://github.com/marklocascio/qml-listmodel-example/blob/main/sample/device_listmodel.py#L54">We can do that with a method like:</a></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(2 * 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">Python</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>def add_device_after_index(self, idx, name, serial, connected):

    index_of_new_device = idx + 1

    new_device = {

        DeviceItemRoles.NAME: name,

        DeviceItemRoles.SERIAL: serial,

        DeviceItemRoles.CONNECTED: connected

    }



    self.beginInsertRows(QModelIndex(), index_of_new_device, index_of_new_device)

    self._data.insert(index_of_new_device, new_device)

    self.endInsertRows()</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: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">add_device_after_index</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">idx</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">name</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">serial</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">connected</span><span style="color: #D4D4D4">):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    index_of_new_device = idx + </span><span style="color: #B5CEA8">1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    new_device = {</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        DeviceItemRoles.NAME: name,</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        DeviceItemRoles.SERIAL: serial,</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        DeviceItemRoles.CONNECTED: connected</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.beginInsertRows(QModelIndex(), index_of_new_device, index_of_new_device)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">._data.insert(index_of_new_device, new_device)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.endInsertRows()</span></span></code></pre></div>



<p class="wp-block-paragraph"><code>beginInsertRows()</code> needs three things: the <code>QModelIndex</code> of the parent into which rows are inserted (for 1D listmodels that we&#8217;re talking about here, just give it a default one), the row number that <strong><em>the first new row will have after insertion</em></strong>, and the row number that <strong><em>the last new row will have after insertion</em></strong>. I&#8217;m never able to remember this, so I almost always consult the helpful diagrams in <a href="https://doc.qt.io/qt-6/qabstractitemmodel.html#beginInsertRows">the documentation for this method</a>.</p>



<p class="wp-block-paragraph">After that, we&nbsp;insert the new data into our list, and then we call <code>endInsertRows()</code>. The <code>beginInsertRows()</code> method handles emitting a signal for you (<code>rowsAboutToBeInserted</code>), and <code>endInsertRows()</code> handles emitting a different signal for you (<code>rowsInserted</code>) so you don’t have to emit any signals yourself! These signals are used to notify QML that it’s time to refresh the <code>ListView</code> with new rows, and which ones need to be updated (if the model contains large quantities of data, we obviously only want to update as few as possible).</p>



<h2 class="wp-block-heading" id="h-signaling-changes-to-existing-row-data-from-the-gui">Signaling Changes to Existing Row Data from the GUI</h2>



<p class="wp-block-paragraph">The final scenario we&#8217;ll discuss addresses the last part of the <code>QAbstractListModel</code> documentation on subclassing:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">For editable list models, you must also provide an implementation of <code>setData()</code>&nbsp;and implement the <code>flags()</code> function so that it returns a value containing <code>Qt::ItemIsEditable</code>.</p>
</blockquote>



<p class="wp-block-paragraph">As you can see above, if <strong><em>the application</em></strong> manipulates data in the <code>QAbstractListModel</code>, it simply needs to emit a signal (<code>dataChanged</code>) to notify QML that there&#8217;s something new. The <code>setData()</code> method is used when information goes the opposite direction, <strong><em>from the UI to the application</em></strong>. For example, say the delegate contains a checkbox. If the user clicks the checkbox in a particular row, QML needs to tell the <code>QAbstractListModel</code> that there is a new value for the checkbox&#8217;s role at a particular list index. It does this by calling the <a href="https://doc.qt.io/qt-6/qabstractitemmodel.html#setData"><code>setData()</code></a> method, which takes three arguments: the <code>index</code>, the new <code>value</code>, and the <code>role</code>. It will look very similar to the <code>data()</code> method above, perhaps like:</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(2 * 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">Python</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>def setData(self, index, value, role):

    if role != MyRoleEnum.SOME_EDITABLE_ROLE:

        return False



    try:

        data_row = self._data_list&#91;index.row()&#93;

    except IndexError:

        return False



    data_row&#91;MyRoleEnum.SOME_EDITABLE_ROLE&#93; = value

    self.dataChanged.emit(index, index, &#91;MyRoleEnum.SOME_EDITABLE_ROLE&#93;)

    return True</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: #569CD6">def</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">setData</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">self</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">index</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">value</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">role</span><span style="color: #D4D4D4">):</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> role != MyRoleEnum.SOME_EDITABLE_ROLE:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">False</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">try</span><span style="color: #D4D4D4">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        data_row = </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">._data_list&#91;index.row()&#93;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">except</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">IndexError</span><span style="color: #D4D4D4">:</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">False</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    data_row&#91;MyRoleEnum.SOME_EDITABLE_ROLE&#93; = value</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">self</span><span style="color: #D4D4D4">.dataChanged.emit(index, index, &#91;MyRoleEnum.SOME_EDITABLE_ROLE&#93;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">True</span></span></code></pre></div>



<p class="wp-block-paragraph">In short, you use the <code>index</code> and <code>role</code> arguments to find the data you’re looking for in the model, you set that data to the new <code>value</code>, and then you emit <code>dataChanged</code>.</p>



<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p class="wp-block-paragraph">The <code>QAbstract<u>List</u>Model</code> (and its base class, <code>QAbstract<u>Item</u>Model</code>) is a powerful way to present a list of data to a user interface, but the extensive abstraction can make the documentation hard to parse. A <a href="https://github.com/marklocascio/qml-listmodel-example">simple example</a> should help clarify, as well as a small number of important concepts:</p>



<ul class="wp-block-list">
<li>Many of <code>QAbstract<u>List</u>Model</code>&#8216;s methods are inherited from its base classes, and consequently involve a parent <code>QModelIndex</code> that doesn&#8217;t apply to a simple list and can be very confusing.</li>



<li>A &#8220;role&#8221; is simply a way to specify individual pieces of data in a list item.</li>



<li>Roles can be used to make a list seem like a table, and that&#8217;s fine&#8230; you can still use <code>QAbstractListModel</code>!</li>



<li>When adding items to the list or removing items from it, call the <code>beginInsertRows()</code> and <code>endInsertRows()</code> methods before making your changes, and the correct signals will be emitted for you at the right times.</li>



<li>If your application updates the model by changing data in an existing item in the list (or multiple existing items in the list), make sure you emit the <a href="https://doc.qt.io/qt-6/qabstractitemmodel.html#dataChanged"><code>dataChanged</code> signal</a> after the changes are made to notify QML that it needs to update its views.</li>



<li>If the user interacts with the QML UI and modifies data in the model, you will need to implement <code>setData()</code> to store the new information in the model object, and then you will need to emit <code>dataChanged.</code></li>
</ul>



<h2 class="wp-block-heading" id="h-building-a-qt-app">Building a Qt app?</h2>



<p class="wp-block-paragraph">I&#8217;d love to help! Give us a call or <a href="mailto:sales@localhost?subject=Let's%20build%20a%20Qt%20app!">send us an email</a> to discuss!&nbsp;</p>



<p class="wp-block-paragraph"><strong>Learn more about our&nbsp;<a href="https://static.dmcinfo.com/services/application-development">Application Development</a>&nbsp;expertise and&nbsp;<a href="https://static.dmcinfo.com/contact#get-in-touch">contact us</a>&nbsp;for your next project.</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/17671/using-a-qabstractlistmodel-in-qml/">Using a QAbstractListModel in QML</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Resizing UIs with QML Layouts</title>
		<link>https://static.dmcinfo.com/blog/18019/resizing-uis-with-qml-layouts/</link>
		
		<dc:creator><![CDATA[Mark Locascio]]></dc:creator>
		<pubDate>Fri, 09 Dec 2022 09:40:04 +0000</pubDate>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[PC Application Development]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/18019/resizing-uis-with-qml-layouts/</guid>

					<description><![CDATA[<p>Overview When I was first getting exposed to QML as a language for describing user interfaces, almost everything was easy to grasp except the concept of layouts. Their behavior never seemed natural, and I spent a lot of time fighting with them before I was finally able to identify the things that didn’t do what [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/18019/resizing-uis-with-qml-layouts/">Resizing UIs with QML Layouts</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 id="h-overview" class="wp-block-heading">Overview</h2>



<p class="wp-block-paragraph">When I was first getting exposed to QML as a language for describing user interfaces, almost everything was easy to grasp except the concept of <a href="https://doc.qt.io/qt-6/qml-qtquick-layouts-layout.html" target="_blank">layouts</a>. Their behavior never seemed natural, and I spent a lot of time fighting with them before I was finally able to identify the things that didn’t do what I wanted them to do.</p>



<p class="wp-block-paragraph">This blog aims to give you the head start I didn’t have by walking you through a series of simple examples that&nbsp;illustrate most of the principles.</p>



<h2 id="h-a-brief-introduction-to-layouts" class="wp-block-heading">A Brief Introduction to Layouts</h2>



<p class="wp-block-paragraph">In short, layouts are QML elements that control how their children&nbsp;(the elements that they contain) are positioned and resized. A layout has no visible characteristics itself. There are a few types of layouts:</p>



<ul class="wp-block-list">
<li><code><a href="https://doc.qt.io/qt-6/qml-qtquick-layouts-rowlayout.html" target="_blank">RowLayout</a></code>: positions its children in a single row, either left to right (default) or right to left</li>



<li><code><a href="https://doc.qt.io/qt-6/qml-qtquick-layouts-columnlayout.html" target="_blank">ColumnLayout</a></code>: positions its children&nbsp;in a single column, either top to bottom (default) or bottom to top</li>



<li><code><a href="https://doc.qt.io/qt-6/qml-qtquick-layouts-gridlayout.html" target="_blank">GridLayout</a></code>: positions children in successive cells of a grid
 
 
<ul class="wp-block-list">
<li>Cells in the grid are rearranged when the <code>GridLayout</code> is resized.</li>



<li><code>RowLayout</code> and <code>ColumnLayout</code> are special cases of a <code>GridLayout</code> with only one row or column.</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph">The purpose of this walkthrough is to familiarize you with the <strong><em>behaviors</em></strong> of layouts (particularly behaviors that are unintuitive), not to describe all of their features. As such, we will largely focus on the <code>ColumnLayout</code>.</p>



<h2 id="h-a-side-note-on-the-stacklayout" class="wp-block-heading">A Side Note on the StackLayout</h2>



<p class="wp-block-paragraph">There is one more QML Layout type called <code><a href="https://doc.qt.io/qt-6/qml-qtquick-layouts-stacklayout.html" target="_blank">StackLayout</a></code>. This is most closely related to the concept of “tabs” or “pages,” where different sets of controls can be grouped together and displayed in the same area, and&nbsp;only one group is visible at a time. The <code>StackLayout</code> behaves much like the others, but isn’t primarily for positioning and resizing its content. Since the positioning and resizing behaviors are the interesting ones, we’ll focus on those here, and you will be more than capable of figuring out the <code>StackLayout</code> on your own.</p>



<h3 id="h-walkthrough" class="wp-block-heading">Walkthrough</h3>



<p class="wp-block-paragraph">Let’s step through a series of tests to understand the behavior of layouts.</p>



<h2 id="h-step-0-start-a-nbsp-new-qtquick-project-in-qtcreator" class="wp-block-heading">Step 0: Start a&nbsp;New QtQuick Project in QtCreator</h2>



<p class="wp-block-paragraph">I am using Qt Creator 8.0.2 on Windows, but any recent version on any platform will do. Simply create a new project from the QtQuick application template. I will be using Qt 6.2.1, but Qt5 should be nearly the same.</p>



<p class="wp-block-paragraph">When your template application is generated, you’ll have a file main.qml file that looks like the code on the left. When you build and run the project, you’ll see an empty window like the one on the right. The only change I made to the template QML file is the width of the <code>Window</code>.</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">HTML</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>import QtQuick

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")
}</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">import QtQuick</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



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


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">As a side note, you do not need to build the application to see how the window will behave. You can use the “QML utility” to visualize and interact with the currently-active QML file. This utility can be launched from the Tools menu:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/tools-menu.png" alt=""/></figure>



<p class="wp-block-paragraph">For convenience, I have that utility mapped to Ctrl-Q, <em><strong>which is not the default</strong></em>. By default, Ctrl-Q exits Qt Creator. In a default setup, don’t just hit Ctrl-Q and expect to see your QML object.</p>



<h2 id="h-step-1-add-a-rectangle" class="wp-block-heading">Step 1: Add a Rectangle</h2>



<p class="wp-block-paragraph">Let’s put something in that window, maybe just a colored rectangle to start with. In my example code, I&#8217;ll highlight changes from the previous example <code><span style="color:#0066ff">in blue</span></code>:</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(2 * 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">HTML</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>import QtQuick

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    Rectangle {
        color: "lightBlue"
    }
}</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">import QtQuick</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">        color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



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


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">We’ve already hit a snag. Where’s my rectangle?!</p>



<p class="wp-block-paragraph">It’s there&#8230; but Qt has no way of knowing how big a rectangle you want, so, naturally, it chose 0x0 pixels. The rectangle is there, but it has no height or width. It is conceptual&#8230; the <strong><em>essence</em></strong> of a rectangle, wafting in the breeze, elusive.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Lesson 1: The implicit height and width of a QML Rectangle object is zero.</p>
</blockquote>



<h2 id="h-step-2-make-it-a-much-better-rectangle" class="wp-block-heading">Step 2: Make it a Much Better Rectangle</h2>



<p class="wp-block-paragraph">We’ll specify the height and width of the rectangle so we can actually see it. Now we have:</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(2 * 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">HTML</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>import QtQuick

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    Rectangle {
        color: "lightBlue"
        height: 64
        width: 64
    }
}</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">import QtQuick</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">        color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        height: 64</span></span>
<span class="line"><span style="color: #D4D4D4">        width: 64</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



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


</td>
</tr>
</tbody>
</table>


<h2 id="h-step-3-more-rectangles-more-nbsp" class="wp-block-heading">Step 3: More Rectangles. MORE.&nbsp;</h2>



<p class="wp-block-paragraph">Next,&nbsp;add another two rectangles and vary the sizes and colors a little.</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(2 * 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">HTML</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>import QtQuick

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    Rectangle {
        color: "pink"
        height: 256
        width: 256
    }

    Rectangle {
        color: "lightGreen"
        height: 128
        width: 128
    }

    Rectangle {
        color: "lightBlue"
        height: 64
        width: 64
    }
}</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">import QtQuick</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">        color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        height: 256</span></span>
<span class="line"><span style="color: #D4D4D4">        width: 256</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">        color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        height: 128</span></span>
<span class="line"><span style="color: #D4D4D4">        width: 128</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">        color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        height: 64</span></span>
<span class="line"><span style="color: #D4D4D4">        width: 64</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



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


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">This isn’t necessarily what we wanted. In the absence of any specific information about where to put those rectangles, the only reasonable thing to do is just layer them on top of each other in the upper left corner, pink on the bottom, then light green, then light blue on top. If we hadn’t made them different sizes in exactly that order, we wouldn’t have even known, and the smaller rectangles would’ve been hidden under the larger one! We might have gotten incredibly frustrated and hurled our laptop into a fire! Boy, would IT have been mad in this extremely hypothetical example!</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Lesson 2:&nbsp;Unless you tell Qt where to put stuff, it won’t know, and it has no problem letting things overlap.</p>
</blockquote>



<h2 id="h-step-4-add-a-column-layout" class="wp-block-heading"><a id="add-column-layout" name="add-column-layout">Step 4</a>: Add a Column Layout</h2>



<p class="wp-block-paragraph">As stated above, a layout object’s job is to handle the positioning and sizing of its children. So, let’s put our three rectangles into a column layout and change nothing else. Note that, in order to bring in the layout objects, we need to import the QtQuick.Layouts module at the top:</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        Rectangle {
            color: "pink"
            height: 256
            width: 256
        }

        Rectangle {
            color: "lightGreen"
            height: 128
            width: 128
        }

        Rectangle {
            color: "lightBlue"
            height: 64
            width: 64
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 256</span></span>
<span class="line"><span style="color: #D4D4D4">            width: 256</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 128</span></span>
<span class="line"><span style="color: #D4D4D4">            width: 128</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 64</span></span>
<span class="line"><span style="color: #D4D4D4">            width: 64</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex5-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">Now we’re cookin’! The <code>ColumnLayout</code> object takes its children and arranges them in a column, in the order that they were declared. Try resizing the window, though. You’ll notice that the window resizes, but the rectangles don’t. They stay the same size, and more blank space fills the areas below and to the right of the rectangles.</p>



<h2 id="h-step-5-filling-all-available-space" class="wp-block-heading">Step 5: Filling All Available Space</h2>



<p class="wp-block-paragraph">If we want the rectangles to keep our specified <strong><em>height&nbsp;</em></strong>but always resize to be the <strong><em>width</em></strong> of the window, we can set the <code>Layout.fillWidth</code> property to true in our rectangles. This is the rectangle telling its parent layout,&nbsp;“set my width so that I’m always as wide as possible.”</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        Rectangle {
            color: "pink"
            height: 256
            Layout.fillWidth: true
        }

        Rectangle {
            color: "lightGreen"
            height: 128
            Layout.fillWidth: true
        }

        Rectangle {
            color: "lightBlue"
            height: 64
            Layout.fillWidth: true
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 256</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 128</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 64</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



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


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">WHAT. WHY?</p>



<p class="wp-block-paragraph">Instead of specifying the width of the rectangles, we told it to make them as wide as possible, and now they’re gone! You might throw several more PCs into a fire before realizing that this is because the <code>ColumnLayout</code> <strong><em>did</em></strong> in fact make them as wide as it could, but the layout can only make its children as wide as it itself is: and, by default, a layout is&#8230; 0 pixels wide.</p>



<blockquote class="is-layout-flow wp-block-quote-is-layout-flow">

<p class="wp-block-paragraph">Lesson 3: Layouts, like rectangles, have zero implicit width/height.</p>


</blockquote>



<h2 id="h-step-6-make-the-layout-wider-than-0-pixels" class="wp-block-heading">Step 6: Make the Layout Wider Than 0 Pixels</h2>



<p class="wp-block-paragraph">We want that layout to be pinned to the width of the window, so&nbsp;let’s anchor the layout to its parent’s boundaries (i.e., make the <code>ColumnLayout</code> fill the <code>Window</code> left-to-right and top-to-bottom) by setting the layout’s <code>anchors.fill</code> property to <code>parent</code> (which is the <code>Window</code> object):</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        Rectangle {
            color: "pink"
            height: 256
            Layout.fillWidth: true
        }

        Rectangle {
            color: "lightGreen"
            height: 128
            Layout.fillWidth: true
        }

        Rectangle {
            color: "lightBlue"
            height: 64
            Layout.fillWidth: true
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 256</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 128</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 64</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex7-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">That’s better! Now, the user can resize the window to be as wide or as narrow as needed, and the rectangles will always reach from the far left to the far right. If you stretch the window vertically, you’ll see that the rectangles always stay their specified height and they just get spaced farther apart as the window gets taller. Let’s see if we can fill their heights also!</p>



<h2 id="h-step-7-use-the-layout-to-fill-height" class="wp-block-heading">Step 7: Use the Layout to Fill Height</h2>



<p class="wp-block-paragraph">Now, let’s replace the <code>height</code> property of each rectangle with <code>Layout.fillHeight</code> so the layout will know to resize all of them in both width and height:</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        Rectangle {
            color: "pink"
            height: 256
            Layout.fillWidth: true
        }

        Rectangle {
            color: "lightGreen"
            height: 128
            Layout.fillWidth: true
        }

        Rectangle {
            color: "lightBlue"
            height: 64
            Layout.fillWidth: true
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 256</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 128</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            height: 64</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex8-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">Well&#8230; now, if we resize the window, the rectangles <strong><em>do</em></strong> always fill both width and height, so that&#8217;s great!&nbsp;But, now we’ve lost the ratio of heights that made these rectangles so special to begin with! How do we get that back so they fill left &amp; right but maintain a specified ratio vertically?</p>



<h2 id="h-step-8-preferred-minimum-and-maximum-sizes" class="wp-block-heading">Step 8: Preferred, Minimum, and Maximum Sizes</h2>



<p class="wp-block-paragraph">There’s a nuance here that is easy to overlook and definitely confused me. When <code>Layout.fillWidth</code> or <code>Layout.fillHeight</code> is true, how does the layout decide what proportion of that dimension is allocated to each element? By default, it makes sense to&nbsp;divide it up evenly, which is what happened. But what happens if there are other constraints, like when we specified <code>width</code> or <code>height</code>? Well, first, consider that <code>width</code> and <code>height</code> are properties of the <code>Rectangle</code> object, whereas <code>Layout.fillHeight</code> talks to the <code>Rectangle</code>’s <strong><em>parent layout</em></strong>. You should not use explicit position or size properties (like <code>x</code>, <code>y</code>, <code>width</code>, or <code>height</code>) in objects managed by a layout. The layout should be free to manage positions and sizes for you.</p>



<blockquote class="is-layout-flow wp-block-quote-is-layout-flow">

<p class="wp-block-paragraph">Lesson 4: If an object is a child of a <code>Layout</code>, don&apos;t set explicit size properties of the child. Only use the <code>Layout.*</code> properties to delegate those duties to the <code>Layout</code>.</p>


</blockquote>



<p class="wp-block-paragraph">We can, however, give the layout more information so it can make better decisions. Each element that sets <code>Layout.fillWidth</code> or <code>Layout.fillHeight</code> to true can also set:</p>



<ul class="wp-block-list">
<li><code>Layout.minimumWidth</code> and <code>Layout.minimumHeight</code></li>



<li><code>Layout.maximumWidth</code> and <code>Layout.maximumHeight</code></li>



<li><code>Layout.preferredWidth</code> and <code>Layout.preferredHeight</code></li>
</ul>



<p class="wp-block-paragraph">The minimum and maximum properties are self-explanatory, but what does “preferred” mean in the context of elements that the layout wants to stretch to fit all available space? As it turns out, <a href="https://doc.qt.io/qt-6/qtquicklayouts-overview.html#size-constraints" target="_blank">it specifies the proportions</a>! Let’s put our original heights back in there as <strong><em>preferred</em></strong> heights:</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        Rectangle {
            color: "pink"
            Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 256
        }

        Rectangle {
            color: "lightGreen"
            Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 128
        }

        Rectangle {
            color: "lightBlue"
            Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 64
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 256</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 128</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 64</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex9-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">That’s what we wanted, and now when we stretch the window vertically, the rectangles always maintain the given ratio. The green rectangle is always half the height of the pink one, and the blue one is always half the height of the green one (and therefore a quarter of the height of the pink one).</p>



<p class="wp-block-paragraph">In the absence of maximum or minimum values, you can even simplify the preferred heights down to the proportions you want. For example, the example above will behave exactly the same if you change the <code>Layout.preferredHeight</code> values to 4, 2, and 1! Sometimes I’ll do that if I don’t care about the absolute sizes and just want to express that elements should be sized in a 4:2:1 ratio (or whatever ratio you’re looking to achieve). But be aware that this is only the case when all child elements of the layout are set to fill in that direction, and they all have a preferred size in that direction.</p>



<blockquote class="is-layout-flow wp-block-quote-is-layout-flow">

<p class="wp-block-paragraph">Lesson 5: If the layout itself has a specified size, AND all child objects use <code>Layout.fillWidth/Height</code>, AND all child elements have a <code>preferredWidth/Height</code> set, then the proportion of the fill allocated to each child will be the ratios of the <code>preferredWidth/Height</code>!</p>


</blockquote>



<p class="wp-block-paragraph">Let’s dig a little deeper. What if we don’t specify the vertical height of the layout? In other words, what if we only anchor the layout’s left and&nbsp;right sides to the window?</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.left: parent.left
        anchors.right: parent.right

        Rectangle {
            color: "pink"
            Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 256
        }

        Rectangle {
            color: "lightGreen"
            Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 128
        }

        Rectangle {
            color: "lightBlue"
            Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 64
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.left: parent.left</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.right: parent.right</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 256</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 128</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 64</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex10-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">At the bottom, there’s some white space now. The layout isn’t anchored to the window’s top and bottom, so the rectangles are always their “preferred” heights, even when we stretch the window vertically. The <code>Layout.fillHeight</code> properties don’t do anything here. The layout doesn’t know what space it has available to fill if it doesn’t have a parent controlling its size in that direction! The only information the layout can use to control its own height is the sum of the implicit heights of its children (provided by their <code>Layout.preferredHeight</code> properties). The <code>Layout.fillHeight</code> properties are simply ignored.</p>



<p class="wp-block-paragraph">OK, so what happens if we <strong><em>don’t</em></strong> fill height, but we <strong><em>do</em></strong> have the layout anchored to all four sides of the window?</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        Rectangle {
            color: "pink"
            // Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 256
        }

        Rectangle {
            color: "lightGreen"
            // Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 128
        }

        Rectangle {
            color: "lightBlue"
            // Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 64
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            // Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 256</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            // Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 128</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            // Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 64</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex11-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">Now the layout knows what height the rectangles like to be, but it was not told to resize them with a <code>Layout.fillHeight</code>. So, the layout stretches, and the rectangles get repositioned, but they do <strong><em>not</em></strong> get resized vertically. If you reduced the <code>Layout.preferredHeight</code> values to 4, 2, and 1, what happens?</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        Rectangle {
            color: "pink"
            // Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 256
        }

        Rectangle {
            color: "lightGreen"
            // Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 128
        }

        Rectangle {
            color: "lightBlue"
            // Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.preferredHeight: 64
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            // Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 256</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            // Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 128</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            // Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 64</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



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


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">Interesting. You get very slim horizontal lines that are not spaced out uniformly. The layout uses the <code>Layout.preferredHeight</code> properties to allocate proportional chunks of space (see the annotated figure below), but the rectangle placed in that space has exactly the height specified by the <code>Layout.preferredHeight</code> property.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex12-spacing.png" alt=""/></figure>



<p class="wp-block-paragraph">Now, the last test we’ll do on sizing: setting the <code>Layout.preferredHeight</code> of a subset of child elements. For example, let’s say we put <code>Layout.fillHeight</code> back in there and remove the <code>Layout.preferredHeight</code> from the pink rectangle only (and restore the larger sizes 256, 128, and 64):</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        Rectangle {
            color: "pink"
            Layout.fillWidth: true
            Layout.fillHeight: true
            // Layout.preferredHeight: 256
        }

        Rectangle {
            color: "lightGreen"
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.preferredHeight: 128
        }

        Rectangle {
            color: "lightBlue"
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.preferredHeight: 64
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            // Layout.preferredHeight: 256</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 128</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 64</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex13-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">The pink rectangle is very small&#8230; it&#8217;s easy to miss, but it&#8217;s there.&nbsp;It <em><strong>does</strong></em> grow and shrink a little when resizing, but not much. The proportions of the green &amp; blue rectangles are correctly maintained, but the QML engine doesn’t really have much information about what to do with the pink one. For the sake of being thorough, let’s reduce the <code>Layout.preferredHeight</code> of the green &amp; blue rectangles to a simple 2:1 ratio:</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(2 * 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">HTML</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>ColumnLayout {
    anchors.fill: parent

    Rectangle {
        color: "pink"
        Layout.fillWidth: true
        Layout.fillHeight: true
        // Layout.preferredHeight: 4
    }

    Rectangle {
        color: "lightGreen"
        Layout.fillWidth: true
        Layout.fillHeight: true
        Layout.preferredHeight: 2
    }

    Rectangle {
        color: "lightBlue"
        Layout.fillWidth: true
        Layout.fillHeight: true
        Layout.preferredHeight: 1
    }
}</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">ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">    anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">        color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">        // Layout.preferredHeight: 4</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">        color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">        Layout.preferredHeight: 2</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">        color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">        Layout.preferredHeight: 1</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex14-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">The QML engine still maintains the correct ratio for the child elements with a specified <code>Layout.preferredHeight</code>, but the amount of space allocated for the pink one is different. This is all academic&#8230; I don&#8217;t know what the use case for this would be. My only goal is to demonstrate how things behave and establish some rules.</p>



<blockquote class="is-layout-flow wp-block-quote-is-layout-flow">

<p class="wp-block-paragraph">Lesson 6: If all children of a layout are set to fill in the direction of the layout, either give all of them a <code>Layout.preferredHeight/Width</code>, or none of them.</p>


</blockquote>



<h2 id="h-step-9-additional-constraints" class="wp-block-heading">Step 9: Additional Constraints</h2>



<p class="wp-block-paragraph">The minimum/maximum height and width properties can also be set. This allows the rectangles to&nbsp;resize, but only to a certain minimum or maximum size.&nbsp;In this case, we’ll put a maximum height on the pink rectangle. When resized, that rectangle will grow up to 384 pixels. It won’t get any taller, but the blue and&nbsp;green rectangles will continue to maintain their 2:1 ratio. In this case, it doesn’t matter if we use 256:128:64 or 4:2:1, the behavior is the same:</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        Rectangle {
            color: "pink"
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.preferredHeight: 4
            Layout.maximumHeight: 384
        }

        Rectangle {
            color: "lightGreen"
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.preferredHeight: 2
        }

        Rectangle {
            color: "lightBlue"
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.preferredHeight: 1
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 4</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.maximumHeight: 384</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 2</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">            color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 1</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex15-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">We can continue to add additional constraints, and the QML engine will do its best to resize based on all of them.</p>



<h2 id="h-step-10-a-fancy-window-with-nested-layouts" class="wp-block-heading">Step 10: A Fancy Window with Nested Layouts</h2>



<p class="wp-block-paragraph">Let’s take it up a notch by maintaining the 4:2:1 ratio of rows, and in each of those, let’s put a <code>RowLayout</code>. We’ll add more rectangles in various proportions in each of those rows. Let’s also set the spacing on the rows to zero, but leave the column layout’s spacing as the default value (5 pixels). A lot changed here, so I&#8217;ll skip the highlighting:</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(3 * 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">HTML</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>import QtQuick
import QtQuick.Layouts

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        RowLayout {
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.preferredHeight: 4

            spacing: 0

            Rectangle {
                color: "pink"
                Layout.fillWidth: true
                Layout.fillHeight: true
            }

            Rectangle {
                color: "darkRed"
                Layout.fillWidth: true
                Layout.fillHeight: true
            }
        }

        RowLayout {
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.preferredHeight: 2

            spacing: 0

            Rectangle {
                color: "lightGreen"
                Layout.fillWidth: true
                Layout.fillHeight: true
                Layout.preferredWidth: 1
            }

            Rectangle {
                color: "green"
                Layout.fillWidth: true
                Layout.fillHeight: true
                Layout.preferredWidth: 2
            }

            Rectangle {
                color: "darkGreen"
                Layout.fillWidth: true
                Layout.fillHeight: true
                Layout.preferredWidth: 3
            }
        }

        RowLayout {
            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.preferredHeight: 1

            spacing: 0

            Rectangle {
                color: "lightBlue"
                Layout.fillWidth: true
                Layout.fillHeight: true
            }

            Rectangle {
                color: "steelBlue"
                Layout.fillWidth: true
                Layout.fillHeight: true
            }

            Rectangle {
                color: "blue"
                Layout.fillWidth: true
                Layout.fillHeight: true
            }

            Rectangle {
                color: "darkBlue"
                Layout.fillWidth: true
                Layout.fillHeight: true
            }

            Rectangle {
                color: "midnightBlue"
                Layout.fillWidth: true
                Layout.fillHeight: true
            }
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 640</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        RowLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 4</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            spacing: 0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">                color: &quot;pink&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">                color: &quot;darkRed&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        RowLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 2</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            spacing: 0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">                color: &quot;lightGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.preferredWidth: 1</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">                color: &quot;green&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.preferredWidth: 2</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">                color: &quot;darkGreen&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.preferredWidth: 3</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        RowLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.preferredHeight: 1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            spacing: 0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">                color: &quot;lightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">                color: &quot;steelBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">                color: &quot;blue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">                color: &quot;darkBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Rectangle {</span></span>
<span class="line"><span style="color: #D4D4D4">                color: &quot;midnightBlue&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">                Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex16-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<h2 id="h-step-11-using-real-controls" class="wp-block-heading">Step 11: Using Real Controls</h2>



<p class="wp-block-paragraph">I mentioned previously that <code>Rectangle</code> objects don’t have an implicit size, but <a href="https://doc.qt.io/qt-6/qml-qtquick-controls2-button.html" target="_blank"><code>Button</code></a> objects do (note that we need to add <code>import QtQuick.Controls</code> to get the <code>Button</code> object). Let’s see how that changes things. First, let’s strip it down to something like what we had <a href="#add-column-layout">way back in Step 4</a>. The layout is <em><strong>not</strong></em> anchored, and it contains two buttons:</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts
import QtQuick.Controls

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {

        Button {
            text: "Top button is...short"
        }

        Button {
            text: "Bottom button is...long"
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Controls</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Top button is...short&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Bottom button is...long&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex17-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">Nothing&nbsp;terribly interesting there, but&nbsp;when the layout wasn&#8217;t anchored before (with just <code>Rectangle</code>s), we couldn&#8217;t see the contents at all. However, <code>Button</code>s <strong><em>do</em></strong> have an implicit size, whereas <code>Rectangle</code>s don&#8217;t. You can see that the <code>Button</code>s are as wide as they need to be to accommodate their text, and the layout stays &#8220;fitted&#8221; to the implicit size of those buttons. As a consequence, the buttons neither resize nor reposition when the window is resized.</p>



<p class="wp-block-paragraph">Now let’s say we want to fill the buttons in both directions:</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts
import QtQuick.Controls

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {

        Button {
            text: "Top button is...short"

            Layout.fillWidth: true
            Layout.fillHeight: true
        }

        Button {
            text: "Bottom button is...long"

            Layout.fillWidth: true
            Layout.fillHeight: true
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Controls</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Top button is...short&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Bottom button is...long&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex18-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">That’s a little more interesting. The buttons don’t fill the height and width of the whole <code>Window</code>, they fill the height and width of the <code>ColumnLayout</code>, and we didn’t say anything about how big the <code>ColumnLayout</code> should be. That is, we didn’t anchor it to the <code>Window. </code>It&nbsp;is not itself inside another layout, etc. The layout therefore just has its implicit size. The implicit height is the sum of its children’s implicit heights (plus spacing), and its implicit width is the maximum width of its children. So, when the children tell their parent layout to resize them to fill the layout’s height, nothing changes (because they already do), and, when they tell the parent layout to fill the layout’s width, really all that happens is that the narrower button fills to the same width as the wider one. Obviously, a <code>RowLayout</code> will behave the same, but in the horizontal direction instead.</p>



<p class="wp-block-paragraph">Let’s anchor the layout to the <code>Window</code> and fill width (but not height):</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts
import QtQuick.Controls

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {

        Button {
            text: "Top button is...short"

            Layout.fillWidth: true
            Layout.fillHeight: true
        }

        Button {
            text: "Bottom button is...long"

            Layout.fillWidth: true
            Layout.fillHeight: true
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Controls</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Top button is...short&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Bottom button is...long&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex19-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">Now both buttons stretch across the <code>Window</code> and are spaced out such that the column is divided in half vertically, and each button is in the vertical center of its half.</p>



<h2 id="h-step-12-alignment" class="wp-block-heading">Step 12: Alignment</h2>



<p class="wp-block-paragraph">We probably don’t want those buttons to be haphazardly floating in the middle of their space. We probably want them either both at the top, both at the bottom, or one at the top and the other at the bottom. All of this can be achieved, but first we need to understand the quirks of the <code>Layout.alignment</code> property.</p>



<p class="wp-block-paragraph">First, look at the window we created and notice the language I used above. The two buttons are not spaced equally relative to the height of the layout. There&#8217;s twice as much space between the buttons as there is between the top button and the top of the window. Conceptually, the layout’s full height is divided in half, creating two &#8220;cells,&#8221; and each&nbsp;button hovers in the center of its “cell.” This is important because the <code>Layout.alignment</code> property will align a button within its “cell,” not relative to the whole layout! So, if we align both buttons to the top, they <b><i>will not</i></b> both be at the top of the window. They are each at the top of their own “cell,” which leaves the bottom button hovering somewhere in the middle of the window:</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts
import QtQuick.Controls

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        Button {
            text: "Top button is...short"
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignTop
        }

        Button {
            text: "Bottom button is...long"
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignTop
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Controls</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Top button is...short&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.alignment: Qt.AlignTop</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Bottom button is...long&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.alignment: Qt.AlignTop</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex20-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">If the bottom button had instead used <code>Layout.alignment: Qt.AlignBottom</code>, then the top button would be at the top of the window&nbsp;and the bottom button would be at the bottom of the window. If we want both at the top,&nbsp;<code>Layout.alignment</code> isn’t what we want. We have a couple options for that:</p>



<ol class="wp-block-list">
<li>Instead of anchoring the ColumnLayout with <code>anchors.fill: parent</code>, we can just anchor it to the <code>Window</code>’s left and right sides. Then, the buttons will fill the width of the <code>Window</code>, but the layout will only take up as much height as the two buttons (plus any <code>ColumnLayout</code> spacing). The buttons will both&nbsp;be stacked at the top.</li>



<li>We can let the layout take up the whole height, and then add a dummy <a href="https://doc.qt.io/qt-6/qml-qtquick-item.html" target="_blank"><code>Item</code></a> after the second button that will eat up all available height, pushing the two buttons up to the top, like this:</li>
</ol>



<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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts
import QtQuick.Controls

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        Button {
            text: "Top button"
            Layout.fillWidth: true
        }

        Button {
            text: "Middle button"
            Layout.fillWidth: true
        }

        Item {
            Layout.fillHeight: true
        }

        Button {
            text: "Bottom button"
            Layout.fillWidth: true
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Controls</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Top button&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Middle button&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Item {</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Bottom button&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex22-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">This is useful&nbsp;because now we can also add a button at the very bottom. We wouldn’t be able to achieve this with the alignment properties unless we divided up the layout’s “cells” just right, which wouldn’t be worth the hassle. Otherwise,&nbsp;we&#8217;d have to nest another <code>ColumnLayout</code> inside the outer&nbsp;one and use it to keep the top two buttons together.</p>



<blockquote class="is-layout-flow wp-block-quote-is-layout-flow">

<p class="wp-block-paragraph">Lesson 7: Dummy <code>Item</code>s used as spacers can often give you better control of where things are positioned in the direction of the layout&rsquo;s ordering of elements.</p>


</blockquote>



<p class="wp-block-paragraph">I prefer to use spacer <code>Item</code>s instead of <code>Layout.alignment</code>, at least with regard to alignment in the direction of the layout. If we wanted things to be aligned left or right in a <code>ColumnLayout</code> (or top/bottom in a <code>RowLayout</code>), then <code>Layout.alignment</code>&nbsp;makes sense:</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(2 * 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">HTML</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>import QtQuick
import QtQuick.Layouts
import QtQuick.Controls

Window {
    width: 320
    height: 480
    visible: true
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        Button {
            text: "Top button"

            // Layout.fillWidth: true
            Layout.alignment: Qt.AlignRight
        }

        Button {
            text: "Middle button"

            // Layout.fillWidth: true
            Layout.alignment: Qt.AlignLeft
        }

        Item {
            Layout.fillHeight: true
        }

        Button {
            text: "Bottom button"

            // Layout.fillWidth: true
            Layout.alignment: Qt.AlignHCenter
        }
    }
}</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">import QtQuick</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Layouts</span></span>
<span class="line"><span style="color: #D4D4D4">import QtQuick.Controls</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">Window {</span></span>
<span class="line"><span style="color: #D4D4D4">    width: 320</span></span>
<span class="line"><span style="color: #D4D4D4">    height: 480</span></span>
<span class="line"><span style="color: #D4D4D4">    visible: true</span></span>
<span class="line"><span style="color: #D4D4D4">    title: qsTr(&quot;Hello World&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    ColumnLayout {</span></span>
<span class="line"><span style="color: #D4D4D4">        anchors.fill: parent</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Top button&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            // Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.alignment: Qt.AlignRight</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Middle button&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            // Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.alignment: Qt.AlignLeft</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Item {</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.fillHeight: true</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">        Button {</span></span>
<span class="line"><span style="color: #D4D4D4">            text: &quot;Bottom button&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">            // Layout.fillWidth: true</span></span>
<span class="line"><span style="color: #D4D4D4">            Layout.alignment: Qt.AlignHCenter</span></span>
<span class="line"><span style="color: #D4D4D4">        }</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/ex23-small.gif" alt=""/></figure>


</td>
</tr>
</tbody>
</table>


<blockquote class="is-layout-flow wp-block-quote-is-layout-flow">

<p class="wp-block-paragraph">Lesson 8: When positioning items on the axis that the layout does <strong><em>not</em></strong> control, the <code>Layout.alignment</code> property is more&nbsp;useful than it is on the axis that the layout <em><strong>does</strong></em> control.</p>


</blockquote>



<h3 id="h-summary" class="wp-block-heading">Summary</h3>



<p class="wp-block-paragraph">Layouts are a&nbsp;modern and flexible method for creating nicely-resizable QML user interfaces. Until&nbsp;you have some time to play with them and see how they behave, they can seem unintuitive. I have learned several lessons the hard way, and I will reiterate them here for your comfort and convenience:</p>



<ol class="wp-block-list">
<li>The implicit height and width of <code>Rectangle</code>s are zero.</li>



<li>Unless you tell Qt where to put stuff, it won’t know, and it has no problem letting things overlap.</li>



<li><code>Layout</code>s, like <code>Rectangle</code>s, have zero implicit width/height.</li>



<li>If an object is a child of a <code>Layout</code>, don&#8217;t set explicit size properties of the child: only use the <code>Layout.*</code> properties to delegate those duties to the <code>Layout</code>.</li>



<li>If the layout itself has a specified size, AND all child objects use <code>Layout.fillWidth/Height</code>, AND all child elements have a <code>Layout.preferredWidth/Height</code> set, then the proportion of the fill allocated to each child will be the ratios of the <code>preferredHeight/Widths</code>!</li>



<li>If all children of a layout are set to fill in the direction of the layout, either give all of them a <code>preferredHeight/Width</code>, or give them neither.</li>



<li>Dummy <code>Item</code>s used as spacers can often give you better control of where things are positioned in the direction of the layout’s ordering of elements.</li>



<li>When positioning items on the axis that the layout does <strong><em>not</em></strong> control, the <code>Layout.alignment</code> property is more&nbsp;useful than it is on the axis that the layout <em><strong>does</strong></em> control.</li>
</ol>



<h3 id="h-building-a-qt-app" class="wp-block-heading">Building a Qt App?</h3>



<p class="wp-block-paragraph">I’d love to help! Give us a call or&nbsp;<a href="mailto:sales@localhost?subject=Let's%20build%20a%20Qt%20app!">send us an email</a>&nbsp;to discuss! Learn more about our <a href="https://static.dmcinfo.com/services/application-development/web-application-development">Web Application Development</a> solutions and <a href="https://static.dmcinfo.com/contact">contact us</a> today for your next project!</p>
<p>The post <a href="https://static.dmcinfo.com/blog/18019/resizing-uis-with-qml-layouts/">Resizing UIs with QML Layouts</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>A Brief Tutorial on Qt’s Resource Files</title>
		<link>https://static.dmcinfo.com/blog/18025/a-brief-tutorial-on-qts-resource-files/</link>
		
		<dc:creator><![CDATA[Mark Locascio]]></dc:creator>
		<pubDate>Wed, 07 Dec 2022 17:32:56 +0000</pubDate>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[PC Application Development]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/18025/a-brief-tutorial-on-qts-resource-files/</guid>

					<description><![CDATA[<p>One of the many tools Qt provides for you is what’s known as the “resource compiler.” The idea is that you might have some data (say, an icon or image file) that your application needs. You could place that file in a particular location on the file system, and your application could load it at [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/18025/a-brief-tutorial-on-qts-resource-files/">A Brief Tutorial on Qt’s Resource Files</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">One of the many tools Qt provides for you is what’s known as the “<a href="https://doc.qt.io/qt-6/rcc.html">resource compiler</a>.” The idea is that you might have some data (say, an icon or image file) that your application needs. You could place that file in a particular location on the file system, and your application could load it at run time, but you would need to either ensure that it’s there every time the app runs or ensure that the app will still work without it. The resource compiler gives you an alternative: load that file at compile time and bake the data directly into your executable. Then&nbsp;you never need to worry about finding the file at runtime.</p>



<p class="wp-block-paragraph">It&#8217;s a simple and useful system that is worth understanding. The <a href="#details">first section</a> is an overview of what it is, why it’s useful, and how to use it. The <a href="#limitations">second section</a> details a few of the things I’ve run into that have tripped me up.</p>



<h2 id="h-part-1-details-of-the-qt-resource-system" class="wp-block-heading"><a id="details" name="details">Part 1:</a> Details of the Qt Resource System</h2>



<h3 id="h-the-guts-of-a-qrc-file" class="wp-block-heading">The Guts of a QRC File</h3>



<p class="wp-block-paragraph">A resource file (usually with a “.qrc” extension) is just XML that allows you to organize the app’s resources to your liking (you don’t need to write XML yourself if you’re using Qt Creator). When they’re compiled into the executable, you won’t have the luxury of a file system to help you organize and identify your files. This is the job of the QRC file, which is processed as follows at compile time:</p>



<ul class="wp-block-list">
<li>The resource compiler reads the QRC file</li>



<li>The resource compiler loads the resources listed in the QRC file</li>



<li>The resource compiler generates a C++ source file that contains a huge array of bytes containing the exact bytes of those resources</li>



<li>Your regular compiler toolchain compiles the generated C++ source code into an object file that can be linked with the rest of your application</li>



<li>Other parts of your code use a special URL notation to reference resource files, and Qt knows how to point it toward the right part of the compiled byte array</li>
</ul>



<p class="wp-block-paragraph">Let’s take a quick look at what it does behind the scenes. Let’s say I have a file that the app uses as a background image. The file is 1462239 bytes:</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">HTML</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>&lt;RCC>
    &lt;qresource prefix="/">
        &lt;file>background.png&lt;/file>
    &lt;/qresource>
&lt;/RCC></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: #808080">&lt;</span><span style="color: #F44747">RCC</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;</span><span style="color: #F44747">qresource</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">prefix</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;/&quot;</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;</span><span style="color: #F44747">file</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">background.png</span><span style="color: #808080">&lt;/</span><span style="color: #F44747">file</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;/</span><span style="color: #F44747">qresource</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #808080">&lt;/</span><span style="color: #F44747">RCC</span><span style="color: #808080">&gt;</span></span></code></pre></div>



<p class="wp-block-paragraph">In hex, 1462239 bytes is <code><span style="font-size:larger;"><strong>0x164fdf</strong></span></code>. The generated C++ source looks like this:</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">HTML</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>static const unsigned char qt_resource_data[] = {
    // /home/markl/path/to/background.png
    0x00, 0x16, 0x4f, 0xdf,
    0x89,
    0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
    ...
};</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">static const unsigned char qt_resource_data[] = {</span></span>
<span class="line"><span style="color: #D4D4D4">    // /home/markl/path/to/background.png</span></span>
<span class="line"><span style="color: #D4D4D4">    0x00, 0x16, 0x4f, 0xdf,</span></span>
<span class="line"><span style="color: #D4D4D4">    0x89,</span></span>
<span class="line"><span style="color: #D4D4D4">    0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,</span></span>
<span class="line"><span style="color: #D4D4D4">    ...</span></span>
<span class="line"><span style="color: #D4D4D4">};</span></span></code></pre></div>



<p class="wp-block-paragraph">Note that this byte array starts with the four-byte length of the file (<code><span style="font-size:larger;"><strong>0x00 0x16 0x4f 0xdf</strong></span></code>) followed by the exact bytes of the png file (which we can recognize by the standard magic bytes at the beginning of <strong><em>every</em></strong> png file, <code><span style="font-size:larger;"><strong>0x89 0x50 0x4e 0x47 0x0d 0x0a 0x1a 0x0a</strong></span></code>). Additional resource files are concatenated onto that same byte array after the background image. That is, the array contains the size of background.png, then the bytes of background.png, then four bytes denoting the length of the next file, then the bytes of the next file, and so on.</p>



<p class="wp-block-paragraph">Finally, at the bottom of the generated C++ file are some macros and other helpers. Note that you don’t need to interact with anything in this file directly. We’re only peeking behind the curtain here for educational purposes. Qt’s resource compiler will generate that C++ file for you, and your system’s toolchain will handle compiling and linking it. All you need to do is use URLs in your code to reference the resources you want to use.</p>



<h3 id="h-urls-and-aliases" class="wp-block-heading">URLs and aliases</h3>



<p class="wp-block-paragraph">Once the data is compiled into your application, it no longer has a filesystem path for you to refer to it in your code. So, Qt provides a URL format to conveniently identify resource files listed in your QRC file. You can optionally give each data file an easy-to-remember alias so you can refer to it more conveniently (and, later, you might map that same alias to a different resource file so you can change a resource without changing any of your source code). Neat!</p>



<p class="wp-block-paragraph">Let’s look at some examples. <a href="#resources-in-qrc">Figure 1</a> shows an example in which all QML resources are in a directory called “qml_dir,” and all images are in a directory called “image_dir.” In the QRC file (the right half of the figure shows Qt Creator’s QRC editor), the resources are organized into groups based on “prefixes” that you can define yourself. Here, I created three prefixes: ui, images, and icons.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/resources-on-disk-and-in-qrc.png" alt="Resources as they are arranged on the file system (left side) and in the QRC file (right side)."/></figure>



<p class="wp-block-paragraph"><em><a id="resources-in-qrc" name="resources-in-qrc">Figure 1:</a> Resources as they are arranged on the file system (left side) and in the QRC file (right side)</em></p>



<p class="wp-block-paragraph">The URL that you will use has the following general form: <code><span style="font-size:larger;"><strong>qrc:/prefix/file_path_relative_to_qrc_file</strong></span></code></p>



<p class="wp-block-paragraph">Based on the organization of my QRC file, I can refer to each resource using the following URLs:</p>


<table style="border: none; border-spacing: 16px;">
<tbody>
<tr style="border: none;">
<td style="border: none;"><span style="font-size:larger;"><strong>File path</strong></span></td>
<td style="border: none;"><span style="font-size:larger;"><strong>URL</strong></span></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>qml_dir/main.qml</code></td>
<td style="border: none;"><code>qrc:/ui/qml_dir/main.qml</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>image_dir/background.png</code></td>
<td style="border: none;"><code>qrc:/images/image_dir/background.png</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>image_dir/image1.png</code></td>
<td style="border: none;"><code>qrc:/images/image_dir/image1.png</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>image_dir/image2.png</code></td>
<td style="border: none;"><code>qrc:/images/image_dir/image2.png</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>image_dir/icon1.png</code></td>
<td style="border: none;"><code>qrc:/icons/image_dir/icon1.png</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>image_dir/icon2.png</code></td>
<td style="border: none;"><code>qrc:/icons/image_dir/icon2.png</code></td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">For example, using a <a href="https://doc.qt.io/qt-6/qml-qtquick-image.html">QML Image</a> object to display background.png would look like this:</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">HTML</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>Image {
    source: "qrc:/images/image_dir/background.png"
}</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">Image {</span></span>
<span class="line"><span style="color: #D4D4D4">    source: &quot;qrc:/images/image_dir/background.png&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">You also have the option of applying aliases to items in the resource file. Imagine that your graphic design team gives you an image with a name like <code><span style="font-size:larger;"><strong>Main Screen Background (No Transparency)_144p-FINAL v2_11-21-2022 final.png.</strong></span></code> Perhaps you would black out with rage, and when you awoke, you would recognize this as a great use case for aliases. Let’s give that image a short (readable and type-able) alias, say, <code><span style="font-size:larger;"><strong>bckgnd</strong></span></code>, which will appear in parentheses at the end of the line in the QRC file (<a href="#qrc-alias">Figure 2</a>):</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/long-filename-with-alias.png" alt="An alias applied to an image with an absurd file name"/></figure>



<p class="wp-block-paragraph"><em><a name="qrc-alias">Figure 2:</a> An alias applied to an image with an absurd file name</em></p>



<p class="wp-block-paragraph">Now, instead of typing</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">HTML</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>Image {
    source: "qrc:/images/image_dir/Main Screen Background (No Transparency)_144p-FINAL v2_11-21-2022 final.png"
}</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">Image {</span></span>
<span class="line"><span style="color: #D4D4D4">    source: &quot;qrc:/images/image_dir/Main Screen Background (No Transparency)_144p-FINAL v2_11-21-2022 final.png&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">We can use only the prefix and the alias. The alias takes the place of the relative file path in the URL, so it has form <code><span style="font-size:larger;"><strong>qrc:/prefix/alias</strong></span></code>. For example:</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">HTML</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>Image {
    source: "qrc:/images/bckgnd"
}</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">Image {</span></span>
<span class="line"><span style="color: #D4D4D4">    source: &quot;qrc:/images/bckgnd&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">The next week, when you get <code><span style="font-size:larger;"><strong>Main Screen Background (No Transparency)_144p-FINAL v2_11-21-2022 final FINAL.png</strong></span></code>, you can update the QRC file with the new file path&nbsp;but keep the same alias (<code><span style="font-size:larger;"><strong>bckgnd</strong></span></code>). None of your code needs to change at all, because the URL&nbsp;you use to reference that file doesn&#8217;t need to change!</p>



<p class="wp-block-paragraph">Returning to my original example, I might apply the following aliases:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/resources-with-aliases.png" alt="Aliases applied to all resources"/></figure>



<p class="wp-block-paragraph"><em><a name="qrc-alias">Figure 3:</a> Aliases applied to all resources</em></p>



<p class="wp-block-paragraph">All resources can now be used in code using nice short URLs:</p>


<table style="border: none; border-spacing: 16px;">
<tbody>
<tr style="border: none;">
<td style="border: none;"><span style="font-size:larger;"><strong>File path</strong></span></td>
<td style="border: none;"><span style="font-size:larger;"><strong>URL</strong></span></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>qml_dir/main.qml</code></td>
<td style="border: none;"><code>qrc:/ui/main_screen</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>image_dir/background.png</code></td>
<td style="border: none;"><code>qrc:/images/bckgnd</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>image_dir/image1.png</code></td>
<td style="border: none;"><code>qrc:/images/img1</code></td>
</tr>
<tr>
<td style="border: none;"><code>image_dir/image2.png</code></td>
<td style="border: none;"><code>qrc:/images/img2</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>image_dir/icon1.png</code></td>
<td style="border: none;"><code>qrc:/icons/start_symbol</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><code>image_dir/icon2.png</code></td>
<td style="border: none;"><code>qrc:/icons/stop_symbol</code></td>
</tr>
</tbody>
</table>


<h3 id="h-why-would-i-do-nbsp-this" class="wp-block-heading">Why Would I Do&nbsp;This?</h3>



<p class="wp-block-paragraph">For me, the most compelling reason is to manage QML files in a QtQuick application. You probably don’t want users to be exposed to the actual QML files that make up the UI, so I list all my QML files as resources. The application is probably useless without the QML files, so you’re likely to want to ensure that they can always be found, and that they can’t change.</p>



<p class="wp-block-paragraph">Another use case, as described above, is to provide some abstraction between the URL that you use to refer to resources in code and the file name that it has on disk. This helps you manage files with horrific names and allows you to easily update the file path of an aliased file without changing any of your code.</p>



<p class="wp-block-paragraph">You might also benefit from the reduced amount of code you need to write &amp; maintain. To load a file from disk, you need to know where to look for it. Is it at an absolute path? If so, how do you know what that path is on all systems? Is it a relative path? Relative to what? Once you know what path to look for, what do you do if the file isn’t there? What do you do if it <strong><em>is</em></strong> there, and there’s a problem with permissions? You can neatly sidestep all those problems if you can just compile the file directly into your app and refer to it with an easy-to-remember URL.</p>



<h2 id="h-part-2-limitations-and-gotchas" class="wp-block-heading"><a id="limitations" name="limitations">Part 2:</a> Limitations and Gotchas</h2>



<p class="wp-block-paragraph">This is all pretty simple, but there are a few things that can get you tripped up that aren’t addressed clearly in the documentation.</p>



<h3 id="h-using-a-full-url-instead-of-an-alias" class="wp-block-heading">Using a full URL instead of an alias</h3>



<p class="wp-block-paragraph">Let’s look at the example above. We’ve got the following:</p>


<table style="border: none; border-spacing: 16px;">
<tbody>
<tr style="border: none;">
<td style="border: none;"><span style="font-size:larger;"><strong>File path</strong></span></td>
<td style="border: none;"><code>image_dir/image2.png</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><span style="font-size:larger;"><strong>URL (without the alias)</strong></span></td>
<td style="border: none;"><code>qrc:/images/image_dir/image2.png</code></td>
</tr>
<tr style="border: none;">
<td style="border: none;"><span style="font-size:larger;"><strong>URL (using the alias)</strong></span></td>
<td style="border: none;"><code>qrc:/images/img2</code></td>
</tr>
</tbody>
</table>


<p class="wp-block-paragraph">Let’s say you’ve recently learned about aliases, and you applied the img2 alias to image2.png. You changed to the shorter URL several places in your code, but you missed one instance and left the full (non-aliased) URL somewhere. <strong><em>Qt’s resource URL resolver will fail to locate that resource</em></strong>. Even though the URL used to be valid, and the relative path to the file has not changed, <strong><em>if you apply an alias, you must use it</em></strong>.</p>



<p class="wp-block-paragraph">I find this unintuitive. The word “alias” to me implies that you <strong><em>can</em></strong> use it, but you don’t <strong><em>have</em></strong> to. Nevertheless, as of Qt 6.2.1, be aware that this is the case. Note that you <strong><em>can</em></strong> have a mix of aliased and not-aliased items in the same QRC file.</p>



<h3 id="h-accidental-alias-collisions" class="wp-block-heading">Accidental Alias Collisions</h3>



<p class="wp-block-paragraph">Suppose you accidentally apply the same alias to different items in a QRC file. For example, you alias both icon1.png and icon2.png as “start_symbol.” You will be able to use <code><span style="font-size:larger;"><strong>qrc:/icons/start_symbol</strong></span></code> as usual in your code, and no errors or warnings will appear at compile time or run time. This is, in fact, normal and useful behavior, but if you aren’t checking for it, it could cause a subtle bug.</p>



<p class="wp-block-paragraph">Why is this normal and useful? Because one of the common uses for resource files is to <a href="https://doc.qt.io/qt-6/resources.html#language-selectors">provide language translation features</a>. Say you have an image of a stop sign for users in the US (“STOP”) and an image of a stop sign for users in Mexico (“ALTO”). You can use the same alias to refer to one of many resources, and Qt will choose the appropriate image based on the user’s configured locale. We won’t dig into it any more here, but for more information on advanced usage and localization, <a href="https://doc.qt.io/qt-6/resources.html">see the Qt documentation</a>.</p>



<h3 id="h-multiple-qrc-files" class="wp-block-heading">Multiple QRC files</h3>



<p class="wp-block-paragraph">You might be tempted, as I was, to separate your resources into multiple QRC files. Each QRC file needs to generate a C++ source file, and then that file needs to be compiled, so you might think that it makes sense to put your QML files (which will change frequently as you develop) in their own QRC file separate from icons, images, and other relatively large files that won’t change much. This makes a lot of sense and seems like a perfectly fine practice&#8230; as long as you realize that there is no mechanism for addressing a particular QRC file in your URLs.</p>



<p class="wp-block-paragraph">Recall that the format of a URL is <code><span style="font-size:larger;"><strong>qrc:/prefix/file_path_relative_to_qrc_file</strong></span></code> or <code><span style="font-size:larger;"><strong>qrc:/prefix/alias</strong></span></code>. Nowhere in there do you have the option of specifying a particular QRC file, only the prefix and path or alias. It will still work, and it will <strong><em>not</em></strong> complain if both QRC files each contain the same prefix and the same alias, so be careful that you don’t have colliding prefixes or aliases. There’s not a lot of error checking being done, so be careful!</p>



<h3 id="h-big-files" class="wp-block-heading">Big Files</h3>



<p class="wp-block-paragraph">Recall from <a href="#details">the first section</a> that the resource compiler puts the bytes of your files into an array of bytes in a C++ source file. As you might imagine, that array can get pretty big. I have seen some instances (generally on smaller ARM systems) in which the generated (huge) C++ file fails to compile without a terribly helpful error message. In this case, you can direct the resource compiler to skip the C++ source file step and compile your resources directly into an object file.</p>



<p class="wp-block-paragraph">By default, in CMake, you can just list your resource file with the rest of your sources and tell it to automatically run the resource compiler (rcc):</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(2 * 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">HTML</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># Run Qt's Resource Compiler (rcc) automatically
set(CMAKE_AUTORCC ON)

# C++ source files
set(CPP_SRC
    main.cpp
)

# Qt resource files
set(QRC_SRC
    resources.qrc
)

# Create the executable
qt_add_executable(
    ${PROJECT_NAME}
    MANUAL_FINALIZATION
    ${CPP_SRC}
    ${QRC_SRC}
)
``</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"># Run Qt&apos;s Resource Compiler (rcc) automatically</span></span>
<span class="line"><span style="color: #D4D4D4">set(CMAKE_AUTORCC ON)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4"># C++ source files</span></span>
<span class="line"><span style="color: #D4D4D4">set(CPP_SRC</span></span>
<span class="line"><span style="color: #D4D4D4">    main.cpp</span></span>
<span class="line"><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4"># Qt resource files</span></span>
<span class="line"><span style="color: #D4D4D4">set(QRC_SRC</span></span>
<span class="line"><span style="color: #D4D4D4">    resources.qrc</span></span>
<span class="line"><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4"># Create the executable</span></span>
<span class="line"><span style="color: #D4D4D4">qt_add_executable(</span></span>
<span class="line"><span style="color: #D4D4D4">    ${PROJECT_NAME}</span></span>
<span class="line"><span style="color: #D4D4D4">    MANUAL_FINALIZATION</span></span>
<span class="line"><span style="color: #D4D4D4">    ${CPP_SRC}</span></span>
<span class="line"><span style="color: #D4D4D4">    ${QRC_SRC}</span></span>
<span class="line"><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">``</span></span></code></pre></div>



<p class="wp-block-paragraph">To skip the C++ generation step, use the <code><span style="font-size:larger;"><strong>qt_add_big_resources()</strong></span></code> function:</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(2 * 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">HTML</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># Run Qt Resource Compiler automatically
set(CMAKE_AUTORCC ON)

# C++ source files
set(CPP_SRC
    main.cpp
)

# Generate resource source files from resources.qrc
qt_add_big_resources(
    QRC_SRC
    resources.qrc
)

# Create executable
qt_add_executable(
    ${PROJECT_NAME}
    MANUAL_FINALIZATION
    ${CPP_SRC}
    ${QRC_SRC}
)</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"># Run Qt Resource Compiler automatically</span></span>
<span class="line"><span style="color: #D4D4D4">set(CMAKE_AUTORCC ON)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4"># C++ source files</span></span>
<span class="line"><span style="color: #D4D4D4">set(CPP_SRC</span></span>
<span class="line"><span style="color: #D4D4D4">    main.cpp</span></span>
<span class="line"><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4"># Generate resource source files from resources.qrc</span></span>
<span class="line"><span style="color: #D4D4D4">qt_add_big_resources(</span></span>
<span class="line"><span style="color: #D4D4D4">    QRC_SRC</span></span>
<span class="line"><span style="color: #D4D4D4">    resources.qrc</span></span>
<span class="line"><span style="color: #D4D4D4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4"># Create executable</span></span>
<span class="line"><span style="color: #D4D4D4">qt_add_executable(</span></span>
<span class="line"><span style="color: #D4D4D4">    ${PROJECT_NAME}</span></span>
<span class="line"><span style="color: #D4D4D4">    MANUAL_FINALIZATION</span></span>
<span class="line"><span style="color: #D4D4D4">    ${CPP_SRC}</span></span>
<span class="line"><span style="color: #D4D4D4">    ${QRC_SRC}</span></span>
<span class="line"><span style="color: #D4D4D4">)</span></span></code></pre></div>



<p class="wp-block-paragraph">The resource compiler will then produce object files without bothering with the intermediate C++ source. Most of the time, you might as well just use <code><span style="font-size:larger;"><strong>qt_add_big_resources()</strong></span></code>&#8230; you know what’s in the generated C++ source now, and it’s probably not that useful to you.</p>



<h2 id="h-summary" class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Qt’s resource compiler can be a nice way to simplify access to data files in your application. You just need to understand the rules regarding URL formats, and make note of a few potential pitfalls:</p>



<ul class="wp-block-list">
<li>Nothing’s stopping you from giving multiple things the same alias, so be careful</li>



<li>Nothing’s stopping you from having multiple QRC files, and nothing’s stopping you from duplicating prefixes and aliases across multiple files</li>



<li>If you applied an alias to a resource, you <strong><em>must</em></strong> use it in the URLs</li>



<li>Unless you’re especially interested in looking at the C++ source file generated by the resource compiler, feel free to skip that step and use the <code><span style="font-size:larger;"><strong>qt_add_big_resources()</strong></span></code> function in CMake</li>
</ul>



<h2 id="h-building-a-qt-app" class="wp-block-heading">Building a Qt app?</h2>



<p class="wp-block-paragraph">I’d love to help! Give us a call or <a href="mailto:sales@localhost?subject=Let's%20build%20a%20Qt%20app!">send us an email</a> to discuss!</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://static.dmcinfo.com/blog/18025/a-brief-tutorial-on-qts-resource-files/">A Brief Tutorial on Qt’s Resource Files</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Advantages of .NET and Python for Test &#038; Measurement Applications</title>
		<link>https://static.dmcinfo.com/blog/18030/advantages-of-net-and-python-for-test-measurement-applications/</link>
		
		<dc:creator><![CDATA[Mark Locascio]]></dc:creator>
		<pubDate>Wed, 07 Dec 2022 16:57:14 +0000</pubDate>
				<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[PC Application Development]]></category>
		<category><![CDATA[Test and Measurement Automation]]></category>
		<category><![CDATA[User Interface Design]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/18030/advantages-of-net-and-python-for-test-measurement-applications/</guid>

					<description><![CDATA[<p>Prologue In May 2019, at what would become the last NI Week ever, I led a session called “Learning to Love Text Again With Measurement Studio.” It was scheduled for 8:30 AM on the last day of the conference, so I was surprised that so many travel-weary engineers stumbled in, red-eyed, with clumps of taco [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/18030/advantages-of-net-and-python-for-test-measurement-applications/">Advantages of .NET and Python for Test &#038; Measurement Applications</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 id="h-prologue" class="wp-block-heading">Prologue</h2>



<p class="wp-block-paragraph">In May 2019, at what would become the last NI Week ever, I led a session called “<a href="https://forums.ni.com/ni/attachments/ni/niweeksessions/425/11/Learning%20to%20Love%20Text%20Again%20With%20Measurement%20Studio_Software.pdf">Learning to Love Text Again With Measurement Studio</a>.” It was scheduled for 8:30 AM on the last day of the conference, so I was surprised that so many travel-weary engineers stumbled in, red-eyed, with clumps of taco still stuck in their hair, ready to listen to me talk about what&nbsp;I thought was a fairly niche topic. I was wrong! The room was filled with enthusiasm, although some of it was already about where to get lunch.</p>



<p class="wp-block-paragraph">It is now December 2022. NI Week is gone, but the Test &amp; Measurement community is still hungry for Austin’s spectacular tacos and alternative software development platforms. A mere three-and-a-half years later, I have finally found time to convert that presentation into a series of blog posts for those of you who weren’t there (or who slept through it). The intent is to motivate the use of Python or Microsoft’s .NET platform as programming environments for&nbsp;<a href="https://static.dmcinfo.com/services/test-and-measurement-automation">Test &amp; Measurement Automation</a>, and to provide you with some guidance toward getting started.</p>



<h2 id="h-introduction" class="wp-block-heading">Introduction</h2>



<p class="wp-block-paragraph">The purpose of this post is to describe the advantages of Python and .NET software development for Test &amp; Measurement applications. The <em>de facto</em> standard is generally National Instruments LabVIEW, due to the shallow learning curve and the quality and&nbsp;feature set of NI hardware; however, NI is also very good about offering hardware APIs for other languages&nbsp;— which gives you the flexibility to choose another option if it’s the right tool for the job. This post will describe why, in certain circumstances, the right tool may be Python or .NET.</p>



<p class="wp-block-paragraph">In a separate post, <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10390/measurement-studio-net-programming-for-ni-enthusiasts">I also offer a brief overview of NI’s Measurement Studio</a>&nbsp;— which is a very useful set of tools that makes it easier for LabVIEW developers to get started with .NET.</p>



<p class="wp-block-paragraph">Measurement Studio offers:</p>



<ul class="wp-block-list">
<li>.NET classes and functions analogous to LabVIEW’s data analysis VIs</li>



<li>.NET data types analogous to those used by LabVIEW (e.g., analog and&nbsp;digital waveform types)</li>



<li>A .NET API for creating and managing TDMS files</li>



<li>Controls, indicators, and graph elements that can be used in .NET UIs</li>
</ul>



<p class="wp-block-paragraph">If I make a compelling case here and you’d like to try building your next Test &amp; Measurement application in .NET, I recommend getting started with the free trial of Measurement Studio. The familiar tools that it provides will help you leverage your existing LabVIEW knowledge to work efficiently in a new environment.</p>



<h2 id="h-strengths-of-labview-development" class="wp-block-heading">Strengths of LabVIEW Development</h2>



<p class="wp-block-paragraph">From the beginning, NI’s mission for LabVIEW was to make it easy for scientists and&nbsp;engineers to build Test &amp; Measurement applications. Since the mid-80s, the guiding principles of NI’s LabVIEW investment were to:</p>



<ul class="wp-block-list">
<li>Enable fast, easy software development</li>



<li>Make hardware integration as simple as possible</li>



<li>Provide a standard library with a focus on engineering functionality</li>



<li>Lower the barrier to producing graphical user interfaces</li>
</ul>



<p class="wp-block-paragraph">For these reasons, there are some use cases for which LabVIEW is an obvious win. If you need to get an application up and&nbsp;running quickly, if it needs to acquire, process, and visualize data, and if it will neither&nbsp;be deployed widely nor maintained for a very long time, then you will likely benefit from the productivity of developing in LabVIEW.</p>



<h2 id="h-where-can-we-do-better" class="wp-block-heading">Where Can We Do Better?</h2>



<p class="wp-block-paragraph">Larger projects require larger teams in order to meet delivery deadlines or maintain the software throughout its lifecycle. However, larger teams need to be able to work in parallel without stepping on each other’s toes. Beyond the initial delivery, maintaining the software can become a challenge as it ages and evolves&nbsp;and&nbsp;as developers drift in and&nbsp;out of the project. Here, we will discuss some advantages to Python and C# that reduce the complexity of maintaining a large software project throughout its lifecycle.</p>



<h3 id="h-enabling-technology" class="wp-block-heading">Enabling Technology</h3>



<p class="wp-block-paragraph">Oddly enough, the graphical nature of LabVIEW, which makes it one of the most beginner-friendly&nbsp;programming languages, also makes it extremely difficult to compare two pieces of code. It is easy to navigate and visually parse LabVIEW code, but very difficult to graphically represent <strong><em>the difference</em></strong> between two pieces of code.</p>



<p class="wp-block-paragraph">Consider the case in which you wrote a VI and shared it with a colleague. If that colleague edited it and gave you a new version, how would you find all of&nbsp;the differences? You can hunt them down on your own, but you’ll need to search every case structure and check the default value of every control. Even if it were a simple VI that could be visually compared easily, you’d have to identify each change as either functional or cosmetic (i.e., an additional wire bend is a difference, but an inconsequential one). <a href="https://labviewwiki.org/wiki/Set_up_differencing_capabilities" target="_blank">Some automated tools exist</a>, but they tend to be hard to configure and use. Furthermore, once all of the differences are identified, how do you visualize them concisely?</p>



<p class="wp-block-paragraph">Text source code is much more limited in terms of layout. It’s very easy for a computer to parse two chunks of text, compare them, and produce a simple visualization of the differences (often referred to as a “diff”). Simple as it may seem, this enables a substantial number of tools and techniques for managing source code that are not available for complex binary files like VIs. This is critical for code reviews as a quality assurance technique. Senior developers can easily review only the diffs, which are both concise and automatically generated.</p>



<h3 id="h-multi-developer-workflows" class="wp-block-heading">Multi-developer Workflows</h3>



<p class="wp-block-paragraph">Being able to see only the differences in two chunks of code is important for quality assurance, but it gets even better: a diff can also be used to easily merge changes into source code as well. This is a major enabler for multi-developer scenarios because it means that two or more developers can make changes to different parts of the same source file, and those changes can be blended together easily (i.e., they won’t collide unless there are different variations of the same lines of text).</p>



<p class="wp-block-paragraph">DMC’s platform of choice is <a href="https://about.gitlab.com/" target="_blank">GitLab</a>, which is a web-based software development management tool.</p>



<p class="wp-block-paragraph">GitLab provides:</p>



<ul class="wp-block-list">
<li>A revision-control system (<a href="https://git-scm.com/" target="_blank">git</a>)</li>



<li>Source code navigation, viewing, and comparing</li>



<li>Organized methods for users to track issues and resolutions</li>



<li>Automations for testing and building applications</li>



<li>Different user roles that enable better collaboration with both internal and&nbsp;external teams</li>



<li>Many other features</li>
</ul>



<p class="wp-block-paragraph">Of particular importance is the issue resolution workflow, which can be separated into individual workflows for different user roles, such as:</p>



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



<p class="wp-block-paragraph">In this diagram, we have several people working in parallel (from top to bottom): a technical lead, a few developers, and anyone else with access to the source. Anyone with access to the source code repository can test the code and report issues (bottom). Developers (center) can select a reported issue, create a branch of code dedicated to its resolution, resolve the issue, and submit a “merge request.” The technical lead of the project (top) can then review those merge requests, ensure the code meets quality standards (by viewing the diff of that branch with the main line of development), and merge the updated code into the main line of development independently and in parallel with the developers.</p>



<p class="wp-block-paragraph">We have found that the cadence of code reviews is easier to maintain with this workflow. GitLab serves as a portal to view only the parts of the code that have changed and allows you to discuss those changes with the developer (asynchronously, via the web interface) before merging them. Instead of sitting down in a conference room and having the developer&nbsp; walk the technical lead through all the changes in a branch, the technical lead can simply view a diff those changes&nbsp;and enter comments or suggestions that the developer can then address later (as shown below). Once all comments have been addressed and the technical lead is satisfied with the changes, they can be merged.</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/gitlab-diff.png" alt="The GitLab comparison tool shows the source code diff and allows a code reviewer to leave comments &amp; questions for the code's author."/></figure>



<p class="wp-block-paragraph">This substantially improves the code review workflow, allowing the tech lead and developers to work asynchronously, communicate effectively, and collaborate productively.</p>



<h3 id="h-separation-of-concerns" class="wp-block-heading">Separation of Concerns</h3>



<p class="wp-block-paragraph">One objective of good software design is “separation of concerns.” One must break down the problem into smaller and smaller problems, and then those into <strong><em>even smaller</em></strong> problems, continuing until there is a tree of convenient fun-size problems that can each be solved easily. Implicit in this methodology is the idea that each problem should be independent of the others. The programmer should establish clear interfaces between problems to keep them logically separate.</p>



<p class="wp-block-paragraph">If you haven’t heard of SOLID design principles, consider <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10019/dmc-attends-2019-national-instruments-cla-summit">reading through a blog post</a> by my colleague and LabVIEW <em>aficionado</em> <a href="https://static.dmcinfo.com/about/employee-bios/steven-dusing">Steven Dusing</a>. The “S” in SOLID stands for “single responsibility,” meaning that, as you separate your concerns into smaller, more manageable problems, you should end up with chunks of code that do one thing and one thing <strong><em>only</em></strong>.</p>



<p class="wp-block-paragraph">If different pieces of code are truly separated, you can even delegate them to people with different skill sets. Wouldn’t it be nice to have a UI designer handle the graphical layout of your application while engineers develop the business logic? A LabVIEW VI has a user interface (front panel) that is inextricably tied to the business logic (block diagram). This makes it dirt-simple to produce a GUI application, but it also&nbsp;makes it very hard to have a complex UI that is separate from the business logic and can be developed by a different person.</p>



<p class="wp-block-paragraph">As an example, consider <a href="https://learn.microsoft.com/en-us/dotnet/desktop/wpf/?view=netdesktop-6.0">WPF</a>, one of the graphical frameworks available on the .NET platform. The UI layout is specified with <a href="https://learn.microsoft.com/en-us/dotnet/desktop/wpf/xaml/?view=netdesktop-6.0" target="_blank">an XML-style language</a> completely separately from the run-time logic. Since the graphical layout is specified as a text language, diffs are supported for easy review, and, since it exists in its own file, your UI/UX designer can work in parallel with the engineering team. We have effectively separated our concerns: UI things get handled in a UI file by a UI expert, and business logic things get handled in C# code by C# experts.</p>



<p class="wp-block-paragraph">Outside of the .NET framework, various graphical toolkits are available&nbsp;but&nbsp;my personal preference is <a href="https://www.qt.io/" target="_blank">Qt</a>&nbsp;—&nbsp;which is available under the terms of the LGPL (mostly). Qt provides QML, which is conceptually similar to XAML (i.e., like XAML, QML is a declarative UI description language), and gets used in the same way to separate your UI design from business logic. Business logic can be implemented in Python, C++, or some other languages with third-party bindings to Qt.</p>



<h3 id="h-best-practices-for-software-development" class="wp-block-heading">Best Practices for Software Development</h3>



<p class="wp-block-paragraph">In LabVIEW 8.2, object-oriented design principles were introduced to LabVIEW, which was a difficult balancing act. NI’s team aimed to make Object-Oriented Programming (OOP) accessible to scientists and engineers who didn’t necessarily have a computer scientist’s background, without compromising the fundamentals on which LabVIEW was built.</p>



<p class="wp-block-paragraph"><a href="https://www.ni.com/en-us/support/documentation/supplemental/06/labview-object-oriented-programming--the-decisions-behind-the-de.html" target="_blank">This was done out of a recognition that</a>:</p>



<blockquote class="is-layout-flow wp-block-quote-is-layout-flow">

<p class="wp-block-paragraph">Object-oriented programming has demonstrated its superiority over procedural programming as an architecture choice in several programming languages. It encourages clear divisions between sections of the code, it is easier to debug, and it scales better for large programming teams. LabVIEW R&amp;D wanted this power to be accessible by our customers. We wanted the language to be able to enforce some of these software best-practices.</p>


</blockquote>



<p class="wp-block-paragraph">There are a lot of compelling reasons to use an object orientation (OO) approach, and NI needed to balance that with the need to maintain the concept of dataflow, and a recognition that this might not be the right approach for every person, every project, and every situation. Consequently, the implementation of OO in LabVIEW is very useful and&nbsp;very easy to use, but it is substantially different from traditional OO. For larger projects with larger teams, leveraging the scalability and modularity of a truly object-oriented language can lead to a better product and a more efficient development experience.</p>



<h3 id="h-deployment" class="wp-block-heading">Deployment</h3>



<p class="wp-block-paragraph">The three languages we’ve been discussing most (LabVIEW, C#, and Python) all need to run in the context of some set of libraries on the target machine. That may be the LabVIEW Runtime Engine, the .NET Framework, or the Python interpreter, respectively.</p>



<p class="wp-block-paragraph">Applications that will be widely distributed will generally benefit from the fact that all Windows installations either have the .NET runtime installed already, or they make it easy to do so automatically. Python even has the advantage of creating virtual environments&nbsp;which allow multiple Python interpreters to co-exist on a system, and for each project to have its own set of dependencies installed without any of them colliding with the others. Virtual environments are important for development, but they can also be used to ensure that applications are installed consistently across various systems.</p>



<p class="wp-block-paragraph">For large development projects, the deployment procedure should be considered early. In many cases, the .NET framework is already installed and available on Windows machines, and if the target will be Linux, Python is widely available and often distributed by default with an OS installation.</p>



<h3 id="h-community-support-and-nbsp-engagement" class="wp-block-heading">Community Support and&nbsp;Engagement</h3>



<p class="wp-block-paragraph">The largest and most active development communities generally produce some of the most useful third-party tools,&nbsp;often under open-source license terms. Based on the relatively informal <a href="https://www.tiobe.com/tiobe-index/">TIOBE index</a>, both C# and Python land in the top 5 most searched programming languages. Using that as a proxy for the activity of their respective communities, it is not surprising that the package managers for these platforms runneth over with useful tools and libraries that can be readily used in your projects.</p>



<p class="wp-block-paragraph">The .NET framework provides a package management system called <a href="https://www.nuget.org/" target="_blank">NuGet</a>, which currently hosts over 330,000 unique packages. For Python, the pip module is used to connect to <a href="https://pypi.org/" target="_blank">pypi</a> (over 420,000 unique packages) or other package repositories. While LabVIEW does have both JKI’s VI Package Manager (with over 1000 packages) and NI’s own package manager, neither offers the same level of community engagement.</p>



<p class="wp-block-paragraph">As projects get larger, the availability and quality of reusable tools and&nbsp;libraries can help drive down the amount of code you need to maintain yourself.</p>



<h2 id="h-summary" class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">In recent years, NI has made substantial investments in support for .NET and Python. While LabVIEW continues to be a good option for some Test &amp; Measurement applications, many (particularly large projects) could benefit from different tools.</p>



<p class="wp-block-paragraph">For some engineers, the learning curve of training up on a language other than LabVIEW may be prohibitive. In these cases, I recommend considering NI Measurement Studio as a stepping stone. Read <a href="https://static.dmcinfo.com/latest-thinking/blog/id/10390/measurement-studio-net-programming-for-ni-enthusiasts" type="link" id="https://static.dmcinfo.com/latest-thinking/blog/id/10390/measurement-studio-net-programming-for-ni-enthusiasts">my overview</a> of how Measurement Studio can fill the gaps between LabVIEW and C#.</p>



<p class="wp-block-paragraph"><strong>Learn more about DMC&#8217;s <a href="https://static.dmcinfo.com/services/test-and-measurement-automation">Test &amp; Measurement Automation solutions</a>, and <a href="https://static.dmcinfo.com/contact">contact us</a> today for your next project.</strong></p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://static.dmcinfo.com/blog/18030/advantages-of-net-and-python-for-test-measurement-applications/">Advantages of .NET and Python for Test &#038; Measurement Applications</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Measurement Studio: .NET Programming for NI Enthusiasts</title>
		<link>https://static.dmcinfo.com/blog/18038/measurement-studio-net-programming-for-ni-enthusiasts/</link>
		
		<dc:creator><![CDATA[Mark Locascio]]></dc:creator>
		<pubDate>Tue, 06 Dec 2022 11:56:45 +0000</pubDate>
				<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[PC Application Development]]></category>
		<category><![CDATA[Test and Measurement Automation]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/18038/measurement-studio-net-programming-for-ni-enthusiasts/</guid>

					<description><![CDATA[<p>Prologue In May 2019, at what would become the last NI Week ever, I led a session called “Learning to Love Text Again With Measurement Studio.” It was scheduled for 8:30 AM on the last day of the conference, so I was surprised that so many travel-weary engineers stumbled in, red-eyed, with clumps of taco [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/18038/measurement-studio-net-programming-for-ni-enthusiasts/">Measurement Studio: .NET Programming for NI Enthusiasts</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 id="h-prologue" class="wp-block-heading">Prologue</h2>



<p class="wp-block-paragraph">In May 2019, at what would become the last NI Week ever, I led a session called “<a href="https://forums.ni.com/ni/attachments/ni/niweeksessions/425/11/Learning%20to%20Love%20Text%20Again%20With%20Measurement%20Studio_Software.pdf">Learning to Love Text Again With Measurement Studio</a>.” It was scheduled for 8:30 AM on the last day of the conference, so I was surprised that so many travel-weary engineers stumbled in, red-eyed, with clumps of taco still stuck in their hair, ready to listen to me talk about what&nbsp;I thought was a fairly niche topic. I was wrong! The room was filled with enthusiasm, although some of it was already about where to get lunch.</p>



<p class="wp-block-paragraph">It is now December 2022. NI Week is gone, but the Test &amp; Measurement community is still hungry for Austin’s spectacular tacos and alternative software development platforms. A mere three-and-a-half years later, I have finally found time to convert that presentation into a series of blog posts for those of you who weren’t there (or who slept through it). The intent is to motivate the use of Python or Microsoft’s .NET platform as programming environments for <a href="https://static.dmcinfo.com/services/test-and-measurement-automation/">Test &amp; Measurement Automation</a>, and to provide you with some guidance toward getting started.</p>



<h2 id="h-introduction" class="wp-block-heading">Introduction</h2>



<p class="wp-block-paragraph">This post will focus on NI’s Measurement Studio, what it is, and why it’s useful. In another post, <a href="https://static.dmcinfo.com/blog/18030/advantages-of-net-and-python-for-test-measurement-applications/">I will write about the procedural advantages</a> (code reviews, separation of concerns, multi-developer teams) of developing Test &amp; Measurement applications in .NET or Python. In&nbsp;yet another, I will write about the abundance of tools available to you in those environments (like ORM, web applications, etc.).</p>



<h2 id="h-motivation-using-the-right-tool-for-the-job" class="wp-block-heading">Motivation: Using the Right Tool for the Job</h2>



<p class="wp-block-paragraph">As engineers, we know that there are many ways of doing a thing, and that there are many tradeoffs that need to be considered before deciding how the thing will get done. Programming languages are a dime a dozen, and they all pretty much do the same thing. So, if you’ve already got LabVIEW competency, why invest the time in learning Microsoft’s (extremely large, complicated, and intimidating) .NET stack? On the face of it, that doesn’t seem like a worthwhile tradeoff if both languages get the thing done.</p>



<p class="wp-block-paragraph">LabVIEW’s dataflow language is a great way for engineers without programming experience to write data-acquisition software quickly, without fear of encountering some freakish horror like:</p>



<p class="wp-block-paragraph"><span style="color:#990000;"><span style="font-size:larger;"><strong><code>/usr/lib/../lib/crt1.o: In function `_start':&nbsp;(.text+0x20): undefined reference to `main'</code></strong></span></span></p>



<p class="wp-block-paragraph">This is one reason why LabVIEW will always occupy a 32&#215;32 pixel area of our hearts: quickly acquiring and visualizing data just doesn’t get any easier; however, as software reaches a certain level of maturity or complexity, other development environments can substantially simplify the management of the software’s lifecycle. DMC develops <em><strong>extremely large</strong></em> Test &amp; Measurement applications with deep inheritance hierarchies and complex sets of dependencies. As a project gets larger and larger, it becomes more and more difficult to manage LabVIEW code, work on it with a team, control &amp; assure its quality, and deploy it to customers.</p>



<p class="wp-block-paragraph">Over the last several decades, the software community (separately from the engineering community) built itself many tools to achieve those same goals. As the two communities have converged over the years, their tools have become available off-the-shelf not just for the software developers, but for the mechanical engineers, the electrical engineers, and everyone else. Test &amp; Measurement applications can stand to benefit from improved processes that already exist thanks to those tools. For example, .NET, Python, and other languages offer:</p>



<ul class="wp-block-list">
<li>The humble and&nbsp;mighty&nbsp;diff (an easy way to compare two versions of textual source code)</li>



<li>Tools for multi-developer scenarios (for example, GitLab and GitHub —&nbsp;which work much better with text than with VIs)</li>



<li>Tools for code quality (such as linters, formatters, and so on)</li>



<li>Huge libraries of third-party packages</li>



<li>Really sweet dynamic UIs</li>



<li>More opportunities to adhere to good programming practices with object-oriented programming paradigms</li>
</ul>



<p class="wp-block-paragraph"><strong>Note:</strong> again,&nbsp;there will always be a time and a place for LabVIEW, but it is not “all the time” and “everywhere.”</p>



<h2 id="h-what-s-the-problem-then" class="wp-block-heading">What&#8217;s the Problem, Then?</h2>



<p class="wp-block-paragraph">The problem is that you’re busy, and you don’t have time for this.</p>



<p class="wp-block-paragraph">But what if I told you that getting started with .NET doesn’t mean you have to start from scratch? What if I told you that NI predicted this traumatic event and already provided the tools that you, a LabVIEW developer, would need to productively develop an application in C#?</p>



<h2 id="h-measurement-studio" class="wp-block-heading">Measurement Studio</h2>



<p class="wp-block-paragraph">A lot of people familiar with NI’s ecosystem have never used <a href="https://www.ni.com/en-us/shop/electronic-test-instrumentation/application-software-for-electronic-test-and-instrumentation-category/what-is-measurement-studio.html" target="_blank">Measurement Studio</a> and don’t really know what it is. Here’s what it is <strong><em>not</em></strong>:</p>



<ul class="wp-block-list">
<li>Measurement Studio is <strong><em>not</em></strong> a new language (it’s regular ol’ C#)</li>



<li>Measurement Studio is <strong><em>not</em></strong> a new IDE (it’s regular ol’ Microsoft Visual Studio)</li>



<li>Measurement Studio is <strong><em>not</em></strong> the same as LabWindows/CVI</li>



<li>Measurement Studio is <strong><em>not</em></strong> a set of hardware drivers</li>
</ul>



<p class="wp-block-paragraph">What Measurement Studio <strong><em>is</em></strong>, however, is the bridge between LabVIEW and .NET. It is a set of tools that are analogous to the ones you’re used to in LabVIEW, so you can take everything you know about LabVIEW programming and easily transition it to C#.</p>



<h3 id="h-same-concepts-different-angle" class="wp-block-heading">Same Concepts, Different Angle</h3>



<p class="wp-block-paragraph">You already know how to acquire data from DAQmx in LabVIEW:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/daqmx-labview.png" alt="Typical usage of the LabVIEW DAQmx API."/></figure>



<p class="wp-block-paragraph">If you wanted to do the same thing in .NET, your code would conceptually be the same, just&#8230; rotated 90 degrees clockwise:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/daqmx-dotnet.png" alt="The .NET API for DAQmx is directly analogous to the LabVIEW API."/></figure>



<p class="wp-block-paragraph">As you can see, NI provides a consistent API for DAQmx across multiple languages. There’s the familiar LabVIEW API for DAQmx and a parallel .NET API (i.e., there&#8217;s basically a one-to-one mapping of LabVIEW VIs to class methods in C#), as shown above. For Python fans, I would also recommend NI&#8217;s Python API for DAQmx, <a href="https://static.dmcinfo.com/our-work/ni-data-acquisition-library-and-calibration-utility-in-python/">which we&#8217;ve also used</a>.</p>



<h3 id="h-hardware-drivers-are-already-available" class="wp-block-heading">Hardware Drivers are Already Available!</h3>



<p class="wp-block-paragraph">Any time you install the DAQmx drivers, you have the option of installing the .NET language bindings, too. The DAQmx drivers are <strong><em>not</em></strong> a part of Measurement Studio (they come with all NI hardware that supports DAQmx). The same goes for some other drivers, so DAQmx, NI-VISA, and NI-GPIB drivers all have “.NET Development Support” <a href="https://knowledge.ni.com/KnowledgeArticleDetails?id=kA03q000000x0QqCAI&amp;l=en-US" target="_blank">options in the installers</a>&nbsp;—&nbsp;even without Measurement Studio. Some have even been open-sourced and hosted on GitHub, like the <a href="https://github.com/ni/vdm-dotnet" target="_blank">Vision Development Module for .NET</a>! Others are available as a separate download, like .NET APIs for NI-Switch, NI-DMM, and NI-FGEN. See <a href="https://www.ni.com/en/support/documentation/supplemental/13/national-instruments--net-support.html" type="link" id="https://www.ni.com/en/support/documentation/supplemental/13/national-instruments--net-support.html">NI’s documentation</a> here for more information.</p>



<h3 id="h-measurement-studio-s-value-add" class="wp-block-heading">Measurement Studio&#8217;s Value-Add</h3>



<p class="wp-block-paragraph">You already have your hardware drivers available, and you already know how to use them, so whether you’re working in LabVIEW or C#, you can acquire some data. Now&nbsp;you need to do stuff to it. In LabVIEW, you know how to do stuff to data. You do stuff to data all day long;&nbsp;<b><i>it’s literally your job</i></b>! So, if you’re going to work productively in C#, you’ll need to know how to do the same things. This is where Measurement Studio makes your life substantially easier. Once you install Measurement Studio, you will have access to .NET libraries that provide <b><i>the</i></b> <b><i>same functionality</i></b> that you’re already using in LabVIEW, and they’re even organized in <b><i>the same way</i></b>:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/namespace-palette.png" alt="The NationalInstruments namespace includes APIs for data acquisition, data analysis, TDMS logging, and more."/></figure>



<h4 id="h-butterworth-filter-example" class="wp-block-heading">Butterworth Filter Example</h4>



<p class="wp-block-paragraph">The parallels extend down to individual VIs, which typically map to a single .NET function or class. For example, consider the <a href="https://www.ni.com/docs/en-US/bundle/labview-api-ref/page/vi-lib/analysis/3filter-llb/butterworth-filter-vi.html" target="_blank" rel="noreferrer noopener">Butterworth Filter VI</a>.</p>



<p class="wp-block-paragraph">The analogous .NET library is provided by Measurement Studio&nbsp;and would be used like this in C#:</p>



<p class="wp-block-paragraph"><code><span style="white-space: nowrap; font-size:larger;"><strong><span style="color:#0070C0;">using</span> NationalInstruments.Analysis.Dsp.Filters;<br>
<span style="color: rgb(0, 112, 192);">var</span> <span style="color: rgb(113, 64, 121);">newFilter</span> = ButterworthLowpassFilter(<span style="color: rgb(0, 112, 192);">order</span>, <span style="color: rgb(191, 89, 0);">fs</span>, <span style="color:#BF5900;">fh</span>);<br>
<span style="color: rgb(0, 112, 192);">var</span> <span style="color: rgb(191, 89, 0);">filteredX</span> = <span style="color: rgb(113, 64, 121);">newFilter</span>.FilterData(<span style="color: rgb(191, 89, 0);">X</span>);</strong></span></code></p>



<p class="wp-block-paragraph">You simply create a <strong><code><span style="font-size:larger;">ButterworthLowpassFilter</span></code></strong> object with the same <code><span style="font-size:larger;"><strong><span style="color: rgb(0, 112, 192);">order</span></strong></span></code>, <code><span style="font-size:larger;"><strong><span style="color: rgb(191, 89, 0);">fs</span></strong></span></code>, and <code><span style="font-size:larger;"><strong><span style="color:#BF5900;">fh</span></strong></span></code>&nbsp;parameters that you’d wire to the VI. You then call that object’s <code><span style="font-size:larger;"><strong>FilterData()</strong></span></code>&nbsp;method on the input array (<code><span style="font-size:larger;"><strong><span style="color: rgb(191, 89, 0);">X</span></strong></span></code>), and it gives you the filtered output array (<code><span style="font-size:larger;"><strong><span style="color: rgb(191, 89, 0);">filteredX</span></strong></span></code>).</p>



<p class="wp-block-paragraph">There’s a specific lowpass filter class, so you don’t need the <code><span style="font-size:larger;"><strong><span style="color: rgb(0, 112, 192);">filter type</span></strong></span></code>&nbsp;input, and the <code><span style="font-size:larger;"><strong><span style="color: rgb(191, 89, 0);">fl</span></strong></span></code>&nbsp;value isn’t applicable. Nor do you need the <span style="color:#538135;"><code><span style="font-size:larger;"><strong>init/cont</strong></span></code></span>&nbsp;input (the nature of object-oriented programming means you don’t need to manipulate the filter’s state at the same time you’re trying to use it). I would make the bold claim that, while this may seem unfamiliar at first, the VI is trying to do too much, so the C# code is ultimately more intuitive &amp; readable than the VI is!</p>



<h4 id="h-tdms-example" class="wp-block-heading">TDMS example</h4>



<p class="wp-block-paragraph">Whether you’re using LabVIEW or C# to glue the parts together, you’ve acquired your data with DAQmx, filtered it with a Butterworth filter, and now you need to store that data in a TDMS file. In LabVIEW, you might have something like:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/tdms-labview.png" alt="Typical usage of the LabVIEW TDMS API."/></figure>



<p class="wp-block-paragraph">And the equivalent C# code, using libraries provided by Measurement Studio, is:</p>



<p class="wp-block-paragraph"><code><span style="white-space: nowrap; font-size:larger;"><strong><span style="color:#0070C0;">using</span> NationalInstruments.Tdms;<br>
<span style="color: rgb(0, 112, 192);">var</span> tdmsFile = <span style="color: rgb(0, 112, 192);">new</span> TdmsFile(<span style="color: #C00000;">"C:\filePath.tdms"</span>, <span style="color: rgb(0, 112, 192);">new</span> TdmsFileOptions());<br>
<span style="color: rgb(0, 112, 192);">var</span> channel = tdmsFile.AddChannelGroup(<span style="color: #C00000;">"DataGroup"</span>).AddChannel(<span style="color: #C00000;">"DataChannel"</span>, TdmsDataType.Double);<br>
channel.AppendData&lt;<span style="color: #9656A1;">double</span>&gt;(<span style="color: rgb(191, 89, 0);">123.45</span>);<br>
tdmsFile.Close();</strong></span></code></p>



<p class="wp-block-paragraph">Unlike hardware drivers, which already have .NET language bindings available in their installers, the data analysis and TDMS methods in C# <em><strong>are provided by Measurement Studio</strong></em>.</p>



<p class="wp-block-paragraph">What I hope is evident from these examples is that you don’t need to start from scratch when you use Measurement Studio. It provides equivalent classes &amp; functions to the VIs you already know you want. Measurement Studio is just a parallel universe where the only difference is that you develop data acquisition software with your keyboard instead of your mouse!</p>



<h3 id="h-debugging" class="wp-block-heading">Debugging</h3>



<p class="wp-block-paragraph">The code itself is only one piece of the puzzle. The IDE is a big part of the programming experience, too. As I mentioned before, Measurement Studio <strong><em>is not</em></strong> a new language or a new IDE. The language is just standard C#, and Measurement Studio installs a few extensions to Microsoft’s Visual Studio IDE, which is an extremely powerful programming and debugging environment.</p>



<p class="wp-block-paragraph">It’s easy to acquire, filter, and write your data to disk, but, as you develop your application, you’ll eventually need to debug a problem. In LabVIEW, you’ve got your trusty probes, breakpoints, and execution highlighting. What do you do in Visual Studio? Exactly the same things!</p>



<p class="wp-block-paragraph">You can <a href="https://learn.microsoft.com/en-us/visualstudio/debugger/debugger-feature-tour?view=vs-2019#set-a-breakpoint-and-start-the-debugger" target="_blank">easily add breakpoints</a> (yes, conditional ones, too) and step through your code line-by-line. This is standard in Visual Studio (and virtually all IDEs).</p>



<figure class="wp-block-image size-full"><img decoding="async" width="752" height="420" src="https://static.dmcinfo.com/wp-content/uploads/2022/12/dbg-tour-set-a-breakpoint.gif" alt="Microsoft Visual Studio's breakpoint feature" class="wp-image-35312"/></figure>



<p class="wp-block-paragraph">Since Measurement Studio’s .NET class libraries provide data types like the ones you’re familiar with (for example, <code><span style="font-size:larger;"><strong>AnalogWaveform</strong></span></code>), <a href="https://learn.microsoft.com/en-us/visualstudio/debugger/debugger-feature-tour?view=vs-2019#inspect-variables-with-data-tips" target="_blank">it also provides “data tips”</a> so that the debugger can inspect (“probe”) those data types while you’re debugging.</p>



<p class="wp-block-paragraph">Visual Studio brings some of its own fun debugging tricks, too. For example, you can:</p>



<ul class="wp-block-list">
<li>Edit code while it’s running in debug mode!</li>



<li>Change the flow of execution (i.e., manually move to particular lines of code) while you’re debugging!</li>



<li>Change the values of variables in memory while you’re debugging!</li>
</ul>



<h3 id="h-visualization" class="wp-block-heading">Visualization</h3>



<p class="wp-block-paragraph">When it comes to graphs &amp; charts, nothing’s easier than LabVIEW. In Test &amp; Measurement applications, you’re almost certainly going to need to plot some data, and Measurement Studio makes it easy.</p>



<p class="wp-block-paragraph">The current standard for GUI development in .NET is <a href="https://learn.microsoft.com/en-us/dotnet/desktop/wpf/?view=netdesktop-6.0" target="_blank">WPF</a>, which provides standard controls and indicators like buttons, text boxes, sliders, etc; however, as a LabVIEW developer, you’re going to want some LEDs, some touchscreen-friendly switches, and some high-visibility dial gauges alongside your graphs and charts. Measurement Studio has you covered here, too, by providing <a href="https://www.ni.com/en-us/shop/electronic-test-instrumentation/application-software-for-electronic-test-and-instrumentation-category/what-is-measurement-studio.html" target="_blank">familiar controls and indicators for your WPF user interface</a>:</p>



<figure class="wp-block-image"><img decoding="async" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/wpf-controls.png" alt="A sample of WPF controls. Some are provided by the .NET framework, others are provided by Measurement Studio."/></figure>



<p class="wp-block-paragraph">And, as a bonus, WPF provides plenty of customization and styling options&nbsp;—&nbsp;as well as hardware-accelerated vector graphics and easy re-sizing.</p>



<h2 id="h-summary" class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Measurement Studio gives you the following tools to help ease your transition from LabVIEW to .NET:</p>



<ul class="wp-block-list">
<li>Convenient NI-style controls, indicators, and graphs that you’re used to</li>



<li>Convenient NI-style data types that you’re used to</li>



<li>Convenient NI-style APIs for all the analysis functions you’re used to</li>



<li>A convenient NI-style TDMS API that you’re used to</li>
</ul>



<p class="wp-block-paragraph">These tools can help you continue to work productively as you migrate from LabVIEW to an unfamiliar programming environment. With all these convenient, NI-style tools available, you can ease right into it.</p>



<p class="wp-block-paragraph">All I’ve done here is talk about how Measurement Studio can help <strong><em>if you choose</em></strong> to develop your application in .NET instead of LabVIEW. We haven’t even discussed <strong><em>why</em></strong> you would choose that! If this post has made C# seem more accessible with Measurement Studio but you&#8217;re still not sure why it&#8217;s worth trying, then I would suggest reading through <a href="https://static.dmcinfo.com/blog/18030/advantages-of-net-and-python-for-test-measurement-applications/">this related post</a>&nbsp;to give you more insight on how platforms like .NET and Python can help you build and maintain your Test &amp; Measurement software.</p>



<p class="wp-block-paragraph"><strong>Learn more about DMC&#8217;s <a href="https://static.dmcinfo.com/services/test-and-measurement-automation">Test &amp; Measurement Automation solutions</a>, and <a href="https://static.dmcinfo.com/contact">contact us</a> today for your next project.</strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/18038/measurement-studio-net-programming-for-ni-enthusiasts/">Measurement Studio: .NET Programming for NI Enthusiasts</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using WebDAV to Transfer Files from a Linux cRIO</title>
		<link>https://static.dmcinfo.com/blog/26523/using-webdav-to-transfer-files-from-a-linux-crio/</link>
		
		<dc:creator><![CDATA[Mark Locascio]]></dc:creator>
		<pubDate>Wed, 08 Jul 2015 11:59:39 +0000</pubDate>
				<category><![CDATA[Test and Measurement Automation]]></category>
		<category><![CDATA[Data Analysis]]></category>
		<category><![CDATA[LabVIEW for Real-Time and FPGA]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/26523/using-webdav-to-transfer-files-from-a-linux-crio/</guid>

					<description><![CDATA[<p>When using a realtime system for data acquisition or control, there is often a need to transfer files between the real time device and a PC. There are many ways to do this, but newer Linux-based NI CompactRIOs come with WebDAV and SSL support enabled by default. This makes WebDAV an easy option to use [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/26523/using-webdav-to-transfer-files-from-a-linux-crio/">Using WebDAV to Transfer Files from a Linux cRIO</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">When using a realtime system for data acquisition or control, there is often a need to transfer files between the real time device and a PC. There are many ways to do this, but newer Linux-based NI CompactRIOs come with WebDAV and SSL support enabled by default. This makes WebDAV an easy option to use right out of the box. The first time I used it, I noticed a couple pitfalls that are worth documenting. This will be a brief post to point out those details. For this post, I used an <a href="http://sine.ni.com/nips/cds/view/p/lang/en/nid/211620" target="_blank">NI cRIO-9068</a>.</p>

<p class="wp-block-paragraph"><strong>Configuration</strong><br />
As mentioned above, the Linux cRIOs have WebDAV and SSL support enabled by default. To confirm, open NI-MAX, and expand Remote Systems. Expand the cRIO, then Software, then NI CompactRIO. You should see SSL Support and WebDAV Server listed, as in Figure 1.<br />
<img decoding="async" alt="" class="MobileImage" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Figure-1-1.png"  /><br />
<em>Figure 1: A properly-configured cRIO includes SSL Support and the WebDAV Server.</em><br />
<br />
As long as those are available, you&rsquo;re already configured.<br />
<br />
<strong>Establishing a Connection in Windows</strong><br />
If a WebDAV server is running on the cRIO, then you can connect directly in Windows as if it were a traditional network shared directory. Both Windows 7 and 8 have built-in WebDAV clients. So, let&rsquo;s say the cRIO&rsquo;s IP address is 192.168.10.200 (and your PC is on a subnet with the cRIO):</p>

<ul class="wp-block-list">
 <li>Open Windows Explorer</li>
 <li>In Windows 8, click the Computer menu, then Map Network Drive.</li>
 <li>In Windows 7, press Alt to expose the menu bar, then click Tools, then Map Network Drive.</li>
 <li>Select a drive letter.</li>
 <li>Uncheck Reconnect at logon, since the cRIO may not always be available.</li>
 <li>In the &ldquo;Folder:&rdquo; field, type &ldquo;http://192.168.10.200/files&rdquo;
 <ul class="wp-block-list">
  <li>Use your cRIO&rsquo;s IP address, of course.</li>
  <li>Don&rsquo;t forget the &ldquo;/files&rdquo; at the end! This isn&rsquo;t a placeholder for the filename you&rsquo;re looking for, it is the literal string &ldquo;/files.&rdquo;</li>
 </ul>
 </li>
 <li>Click finish, and give it a second. It will then ask you for a username and password.
 <ul class="wp-block-list">
  <li>These are the same credentials used to log in to the cRIO over SSH, or in NI-MAX.</li>
  <li>By default, the username is &ldquo;admin&rdquo; and the password is blank.</li>
 </ul>
 </li>
 <li>Hit OK, give it another couple seconds, and you should be presented with an Explorer window showing the files on the cRIO&rsquo;s hard drive.</li>
</ul>

<p class="wp-block-paragraph">If this works, then you know WebDAV is working fine on your PC client and your cRIO server.<br />
<br />
<strong>A Few Brief Words about File Paths</strong><br />
Note that you cannot write files anywhere you like on the cRIO&rsquo;s hard drive. If you&rsquo;re familiar with Linux, the hard drive layout will look familiar. /home/lvuser/natinst/bin is where we&rsquo;ll make files in this example. /C/ni-rt/startup is a symbolic link to /home/lvuser/natinst/bin in order to preserve some compatibility with the conventions of older cRIOs. If none of this makes sense to you, don&rsquo;t worry about it, just keep your files in /home/lvuser/natinst/bin until you get it figured out.<br />
<br />
<strong>Transferring files in LabVIEW</strong><br />
If you&rsquo;ve been able to connect in Windows, then you should be able to connect programmatically in LabVIEW. A complete example VI is show below in Figure 2. Note that this VI runs on the PC, so the transfer is in terms of &ldquo;getting&rdquo; the file from the cRIO. The example takes all of its VIs from LabVIEW&rsquo;s WebDAV palette, which you can access from the Data Communication palette &rarr; Protocols palette &rarr; WebDAV palette &rarr; WebDAV Synchronous.<br />
&nbsp;<br />
<em><span id="cke_bm_392S" style="display: none;">&nbsp;</span></em><span id="cke_bm_210S" style="display: none;">&nbsp;</span><img decoding="async" alt="Figure 2: An example VI that transfers a file from the cRIO to the PC, then deletes the file on the cRIO." class="MobileImage" src="https://static.dmcinfo.com/wp-content/uploads/2025/05/Figure-2-1.png"  /><span id="cke_bm_210E" style="display: none;">&nbsp;</span></p>

<p class="wp-block-paragraph"><em>F</em><em>igure 2: A demo program that transfers a file from the cRIO to the PC, then deletes the file on the cRIO. Note that this VI runs on the PC side.<span id="cke_bm_392E" style="display: none;">&nbsp;</span></em><br />
<br />
The Asynchronous VIs will also work, but will return before the operation completes. This is nice if you want to tell WebDAV to get multiple files, and then just let your program move on while those transfer in the background. However, in this example, I want to get my file and then delete it from the cRIO. I therefore use the Synchronous VIs so I know the &ldquo;get&rdquo; operation is complete before deleting.<br />
<br />
The important information here is the following:</p>

<ul class="wp-block-list">
 <li>The &ldquo;host uri prefix&rdquo; input of the Open Session VI is exactly the same as what you used to connect in Windows Explorer. Don&rsquo;t forget, you need the literal &ldquo;/files&rdquo; part at the end.</li>
 <li>The &ldquo;username&rdquo; and &ldquo;password&rdquo; inputs of Open Session are the same as what you used in Windows Explorer also.</li>
 <li>The &ldquo;verify server&rdquo; input of Open Session can be used for higher-level authentication, but for the cRIO, set it to false.</li>
 <li>The &ldquo;relative uri&rdquo; input of Get is the path to the file you want to get, using the UNIX file path convention.</li>
 <li>The &ldquo;local file path&rdquo; input of Get is where your file will go on your PC, using the Windows file path convention.
 <ul class="wp-block-list">
  <li>You cannot just give it a directory path. This VI is not smart enough to know that you want to put it there and keep the same filename. Your &ldquo;local file path&rdquo; must be a path ending in a file name.</li>
  <li>It will be happy to overwrite a file on your local drive, if a file already exists at &ldquo;local file path.&rdquo;</li>
 </ul>
 </li>
</ul>

<p class="wp-block-paragraph"><strong>Conclusion</strong><br />
Since the cRIO hosts the WebDAV server, the PC is acting as a client that connects, gets the files it wants, then disconnects. This is completely different than having the cRIO send (or &ldquo;put&rdquo;) files to the PC, but has the advantage of being already configured by default. For more information, see the online manuals for the <a href="http://zone.ni.com/reference/en-XX/help/371361K-01/lvcomm/webdav_sync/" target="_blank">synchronous</a> and <a href="http://zone.ni.com/reference/en-XX/help/371361K-01/lvcomm/webdav_async/" target="_blank">asynchronous</a> VIs.</p>
<p>The post <a href="https://static.dmcinfo.com/blog/26523/using-webdav-to-transfer-files-from-a-linux-crio/">Using WebDAV to Transfer Files from a Linux cRIO</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>New FPGA Tools from NI and Xilinx at NI Week 2013</title>
		<link>https://static.dmcinfo.com/blog/28156/new-fpga-tools-from-ni-and-xilinx-at-ni-week-2013/</link>
		
		<dc:creator><![CDATA[Mark Locascio]]></dc:creator>
		<pubDate>Mon, 12 Aug 2013 11:48:14 +0000</pubDate>
				<category><![CDATA[LabVIEW]]></category>
		<category><![CDATA[Test and Measurement Automation]]></category>
		<category><![CDATA[LabVIEW for Real-Time and FPGA]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/blog/28156/new-fpga-tools-from-ni-and-xilinx-at-ni-week-2013/</guid>

					<description><![CDATA[<p>There&#8217;s plenty to love about the field-programmable gate array, or FPGA. It is essentially a customizable silicon chip that you can reprogram as many times as you want or need to in order to achieve specialized high-speed processing. In many cases, you may have a low-volume product for which an application-specific integrated circuit (ASIC) would [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/28156/new-fpga-tools-from-ni-and-xilinx-at-ni-week-2013/">New FPGA Tools from NI and Xilinx at NI Week 2013</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">There&#8217;s plenty to love about the field-programmable gate array, or <a href="/services/test-and-measurement-automation/labview-programming-for-real-time-and-fpga">FPGA</a>. It is essentially a customizable silicon chip that you can reprogram as many times as you want or need to in order to achieve specialized high-speed processing. In many cases, you may have a low-volume product for which an application-specific integrated circuit (ASIC) would be prohibitively expensive. An FPGA is simply a generic grid of logical units on the chip that can be interconnected programmatically, allowing you to program the logic to suit your needs.</p>



<p class="wp-block-paragraph">That capability is extremely powerful. A hardware implementation of any particular algorithm is generally faster than a software implementation. FPGAs reap the speed benefits of hardware processing, but also give an engineer the ability to not only program a generic silicon die, but to reprogram it to fix bugs or improve performance. Furthermore, given enough space on the array, multiple stages of a calculation can be processed at once, either purely in parallel, or in a pipeline.</p>



<p class="wp-block-paragraph">Designing the gate layout of an FPGA may seem daunting, but it is, of course, not done by hand. In fact, during <a href="https://static.dmcinfo.com/blog/28173/dmc-at-ni-week-2013/">NI Week 2013</a>, National Instruments has held a number of helpful information sessions that introduce the tools available for specifying that layout. To begin, <a href="http://www.ni.com/labview/" target="_blank">LabVIEW</a> itself has supported FPGA programming using a subset of its G programming language since 2003. A LabVIEW programmer can simply write an algorithm using a constrained set of functions, and LabVIEW will interface with <a href="http://www.xilinx.com/" target="_blank">Xilinx</a> software to produce the hardware description that will then be used to define the connections on the chip.</p>



<p class="wp-block-paragraph">Due to the nature of FPGAs, however, familiar programming constructs such as loops, array operations, and floating-point operations must be used sparingly, if at all. Writing truly optimized algorithms can be tedious and error-prone, and writing un-optimized algorithms may waste a lot of gates unnecessarily, restricting the throughput and decreasing the amount of parallel processing that can be done.</p>



<p class="wp-block-paragraph">One of the tools NI introduced at NI Week 2013 was the <a href="http://www.ni.com/white-paper/14036/en/" target="_blank">LabVIEW IP Builder</a>, which features optimization technology from Xilinx. IP Builder provides more access to typical programming features, using smart algorithms to apply pipelining, loop-unrolling, and parallelization rules to standard LabVIEW algorithms. This way, you only need to make a few tweaks to your programming style to write an FPGA-friendly algorithm.</p>



<p class="wp-block-paragraph">The rest of the optimization is achieved by specifying &#8220;directives&#8221; that tell IP Builder which optimizations you&#8217;d like to apply. On FPGAs, multiplier circuits are scarce. If you know that your algorithm needs them, but simultaneous uses are not possible, you can instruct the algorithm to use the same multiplier in several parts of the code to conserve that resource. Perhaps you know that your algorithm takes arrays as inputs, but that the entire array isn&#8217;t needed all at once. Directing the hardware synthesis in this way allows IP Builder to properly allocate the FPGA&#8217;s resources and increase throughput.</p>



<p class="wp-block-paragraph">The crowd chimed in with a few good tips and design practices. Some optimizations due to poorly chosen directives can cause your algorithm to behave differently than intended. It was recommended that you run an un-optimized version of the FPGA code and compare it to an optimized version to ensure that the algorithm&#8217;s output is as expected. This is especially true if the algorithm requires conversions from fixed-point to floating-point values. The FPGA experts agreed that IP Builder could be a valuable tool for computing polynomials, FIR filters, integrators, and the like.</p>



<p class="wp-block-paragraph">Xilinx has also developed a new &#8220;system on a chip&#8221; (SoC) called <a href="http://www.xilinx.com/content/xilinx/en/products/silicon-devices/soc/zynq-7000.html" target="_blank">Zynq</a>, which couples two ARM processor cores with an FPGA on a single die. Zynq is featured on NI&#8217;s new cRIO-9068. Combining general-purpose CPUs and a dedicated FPGA on the same chip means the parts can all easily exchange data. Certain parts of the code can be taken off the CPU, and the burden placed on the FPGA, allowing both to focus on tasks for which they are most capable, and generating significant performance improvements all around.</p>



<p class="wp-block-paragraph">The significant improvement in usability and performance makes FPGAs even more attractive. We&#8217;re looking forward to giving these new technologies a test drive here in the DMC offices!</p>



<p class="wp-block-paragraph"><a href="https://static.dmcinfo.com/blog/28173/dmc-at-ni-week-2013/">DMC at NI Week 2013</a></p>



<p class="wp-block-paragraph"><a href="https://static.dmcinfo.com/blog/28153/ni-week-2013-recap/">NI Week 2013 Recap</a></p>



<p class="wp-block-paragraph"><strong><a href="/services/test-and-measurement-automation/labview-programming-for-real-time-and-fpga">Learn more about DMC&#8217;s LabVIEW programming for real-time and FPGA expertise.</a></strong></p>
<p>The post <a href="https://static.dmcinfo.com/blog/28156/new-fpga-tools-from-ni-and-xilinx-at-ni-week-2013/">New FPGA Tools from NI and Xilinx at NI Week 2013</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
