Responsive width adaptation for Qt: tier/priority label-collapse bars, width-class container, column-collapse header. PySide6/2, PyQt6/5.
Project description
qtflex - responsive width adaptation for Qt
Qt widgets don't adapt their labels to available width. qtflex adds a small, cooperating set: a container that measures and broadcasts a width CLASS, and consumers (action bars, tree headers) that adapt to it - CSS-media-query thinking, but content-driven instead of pixel breakpoints.
Bindings: PySide6 (tested live), PyQt6 (import-smoked), PySide2/PyQt5 (supported by the shim, untested). Zero dependencies beyond your Qt binding.
ResponsiveContainer
A width-broadcasting parent. Emits width_class_changed(str) with
'full' | 'compact' | 'min', classified against the CONTENT (member children's
natural width vs available), not magic px:
- full: everything fits at natural width
- compact: fits only when children shrink (>= 60% of natural)
- min: the floor
API: add(w, member=True) (member widths define the breakpoints),
add_layout(l), add_stretch(), layout_box(), width_class property.
Implementation note: a Qt container cannot shrink below its children's
minimumSizeHint, so the container uses Ignored horizontal size policy and
classifies against the resize EVENT width, never self.width().
ResponsiveBar
An action bar that degrades gracefully as width shrinks, in order:
- PROMOTE: restore wider label tiers while they fit
- compress spacing (max_spacing -> min_spacing)
- DEMOTE: the widest button with a shorter tier drops one tier (repeat)
- SPILL: at the tier floor, lowest-priority buttons hide into a
»overflow menu (menu label = shortest tier, click = original handler). The bar is never fully empty - the highest-priority button always stays visible.
API:
add_button(tiers, tooltip=None, on_click=None, style=None, cursor=True, priority=100)- tiers is a list widest->shortest, e.g.["Re-read all ({n})", "Re-read {n}", "RR"];{n}templates update viaset_count(btn, n). Lower priority spills first. Returns the QPushButton.add_widget(w)- fixed pass-through widget (dropdown, LED), never demoted.add_stretch()subscribe_to(container)- drive layout from a ResponsiveContainer; bars sharing one container demote in concert. Without it the bar self-measures via its own resizeEvent.
Constructor: min_spacing=1, max_spacing=6, margins=(5, 0, 5, 5).
ResponsiveHeader
Column collapse for QTreeView/QTreeWidget, same priority vocabulary.
ResponsiveHeader(tree, {2: 10, 3: 20}) - lower priority hides first;
column 0 is never hidden; unlisted columns default to priority 100.
apply(width_class): full = all shown; compact = hide 1; min = hide half.
subscribe_to(container) joins the same broadcast.
Wiring
from qtflex import ResponsiveBar, ResponsiveContainer, ResponsiveHeader
cont = ResponsiveContainer()
bar = ResponsiveBar()
cont.add(bar)
bar.subscribe_to(cont)
hdr = ResponsiveHeader(tree, {2: 10, 3: 20})
hdr.subscribe_to(cont)
qtcompat
Internal binding shim (PySide6 > PySide2 > PyQt6 > PyQt5, first importable
wins); Signal normalized across PySide/PyQt. qtflex.QT_BINDING names the
active binding.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qtflex-0.1.0.tar.gz.
File metadata
- Download URL: qtflex-0.1.0.tar.gz
- Upload date:
- Size: 7.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4fabdaf37049eb2050487a1701b195a61d333cbec659fcefc83b28506fefd90f
|
|
| MD5 |
f753958968107d575d87dff5e6355680
|
|
| BLAKE2b-256 |
65e311a844a5c5a5c437990805ad3bafff8839eb03ffbf481b5de99bf83833c8
|
Provenance
The following attestation bundles were made for qtflex-0.1.0.tar.gz:
Publisher:
publish.yml on zPirx/qtflex
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qtflex-0.1.0.tar.gz -
Subject digest:
4fabdaf37049eb2050487a1701b195a61d333cbec659fcefc83b28506fefd90f - Sigstore transparency entry: 2064029680
- Sigstore integration time:
-
Permalink:
zPirx/qtflex@94ca690e4b2ad63eda48538321365c9fa3562c74 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/zPirx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@94ca690e4b2ad63eda48538321365c9fa3562c74 -
Trigger Event:
push
-
Statement type:
File details
Details for the file qtflex-0.1.0-py3-none-any.whl.
File metadata
- Download URL: qtflex-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db1b4f0dc73895f07914f0797f8660edfbcf68434382e651f82d001872cbcb08
|
|
| MD5 |
847ab2f12afe2f8ba1dd9ae9df444152
|
|
| BLAKE2b-256 |
c164eafd7f54fa65b66cd1efdbbb40523ee38a149f49be26c8862eb5c1bea7fb
|
Provenance
The following attestation bundles were made for qtflex-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on zPirx/qtflex
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qtflex-0.1.0-py3-none-any.whl -
Subject digest:
db1b4f0dc73895f07914f0797f8660edfbcf68434382e651f82d001872cbcb08 - Sigstore transparency entry: 2064029688
- Sigstore integration time:
-
Permalink:
zPirx/qtflex@94ca690e4b2ad63eda48538321365c9fa3562c74 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/zPirx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@94ca690e4b2ad63eda48538321365c9fa3562c74 -
Trigger Event:
push
-
Statement type: