QTable Widgets and List Views

How often have you wanted to place additional widgets in the header row of a list view or a table view? Take, for example, a checkmark in the header in order to turn on and off an entire column. Qt 5 does not natively support this feature.
Dev's Corner
Spiria's Dev Team
2021-10-20 11:53
5 minute read
<div><p>A quick search will turn up some solutions, but they all have limitations. For example, the solution outlined in this <a href="https://stackoverflow.com/questions/37542803/how-to-implement-checkbox-in-header-of-qtreeview">stack overflow question</a> only supports a checkbox and, even then, only one per table. Another <a href="https://www.qt.io/blog/2012/09/28/qt-support-weekly-27-widgets-on-a-header">proposed solution</a> also only supports a checkbox, but at least it’s a good place to start.</p><p>Taking our cue from the second source, we build on it with these goals in mind:</p><ul> <li>Support for any type of widget.</li> <li>Support for multiple columns, each having its own widget.</li> <li>Ease of use.</li></ul><h2>How It Works</h2><p>The trick is to have a custom header view (<code>QHeaderView</code>) that can be set on a table (<code>QTableWidget</code>) or list (<code>QListWidget</code>). The custom header view tracks the widgets used as headers for each column. The view also handles placing and resizing the widgets to fit within the header.</p><p>Since the widgets are drawn on top of the header, you should <b>not</b> set any title for that column, but instead use a widget that has a label. Since any widget is supported, you can create a container to place an additional label if the widget you want to use does not have one.</p><p>Placing the widget on top works because Qt paints parent-widgets before children. Since the additional widgets are children of the header view, they get painted after the header and thus appear on top of it.</p><p>The API to use the custom header is very simple. You just create an instance of <code>QHeaderViewWithWidgets</code>, add the widgets to the column (called “section” in Qt), and set the header view on your table. In short, it looks like this:</p><pre><code> // Create a combo-box for the header. auto col1_check = new QCheckBox("My checkbox"); // Create the header view with the combo-box for column 1. auto header = new QHeaderViewWithWidgets(Qt::Orientation::Horizontal); header-&gt;addSectionWidget(1, col1_check); // Create the table and set the custom header. auto list = new QTableWidget; list-&gt;setHorizontalHeader(header);</code></pre><h2>The Code</h2><p>The C++ code you need to put widgets in the header of a table is available in <a href="https://github.com/pierrebai/QtAdditions">this public repository on GitHub</a>.</p><p>An example of an application using the custom header view with sub-widgets is available in the same repository, in the <code>examples\ExampleListHeaderWidget</code> folder.</p></div>

Want to Work Together?

Every great project starts with a conversation.