Widgets¶
Subclass the FXMainWindow¶
You can subclass any widgets in the fxwidgets module. Here's a practical example with FXMainWindow:
# Third-party
from qtpy.QtWidgets import QWidget, QVBoxLayout, QPushButton
# Internal
from fxgui import fxwidgets, fxicons
class MyWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.add_layout()
self.add_buttons()
def add_layout(self):
"""Adds a vertical layout to the main layout of the widget."""
self.main_layout = QVBoxLayout()
self.setLayout(self.main_layout)
def add_buttons(self):
"""Adds buttons to the main layout of the widget."""
# Use fxicons for theme-aware icons
home_button = QPushButton("Home")
fxicons.set_icon(home_button, "home")
settings_button = QPushButton("Settings")
fxicons.set_icon(settings_button, "settings")
self.main_layout.addWidget(home_button)
self.main_layout.addWidget(settings_button)
self.main_layout.addStretch()
class MyWindow(fxwidgets.FXMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setCentralWidget(MyWidget(parent=self))
self.adjustSize()
application = fxwidgets.FXApplication()
window = MyWindow()
window.setWindowTitle("Subclassed FXMainWindow")
window.show()
application.exec()
The Gallery¶
A window opens with every public widget, a page per kind: buttons,
inputs, display, containers, lists and trees, the timeline, windows and
dialogs, and docking. Each box is titled with the class names it shows.
Window > Theme switches the theme, so you can see a widget in each.
The Docking page needs PySide6-QtAds (see Installation).
Available Widgets¶
The fxwidgets module holds these classes:
| Class | What it is |
|---|---|
FXAccordion |
Collapsible sections stacked; one open at a time unless exclusive=False |
FXApplication |
The QApplication that themes every window it owns |
FXAvatar |
Round avatar: a photo, or initials on a disc coloured by the name |
FXBreadcrumb |
Clickable breadcrumb trail; double-click it to type a path |
FXCamelCaseValidator |
Accepts camelCase letters only |
FXCapitalizedLetterValidator |
Accepts a name starting with a capital letter |
FXCheckableComboBox |
Combo box whose popup stays open while several rows are ticked |
FXCodeBlock |
Read-only code with syntax highlighting |
FXCollapsibleWidget |
A titled section that opens and shuts its content |
FXCommand |
One row of an FXCommandPalette: a label, a callable or a list of choices, keys, a section |
FXCommandPalette |
Popup search over a window's commands, or over rows to go to; the commands run lately come first |
FXCommandRow |
A toolbar fixed in place, whose margins survive style changes |
FXConfirmDeleteDialog |
Asks for a name typed exactly before an act with no undo; Enter never deletes |
FXDropZone |
Drop target for files or folders, with a browse button and a file list |
FXElidedLabel |
Label that cuts its text with "..." when it does not fit |
FXEmojiButton |
Round icon button that opens an FXEmojiPicker and can insert into an editor |
FXEmojiPicker |
Popup grid of emoji, keyboard navigable |
FXFilePathWidget |
File or folder path field with a browse button |
FXFilteredTree |
An FXKeyboardTree under a filter bar, with expand-all and collapse-all; actions= puts a row of buttons under the tree |
FXFloatingDialog |
Dialog that opens at the pointer |
FXFlowLayout |
Layout that wraps its widgets onto new lines, like words |
FXIconButton |
Round icon button; checkable, filled with the accent when checked |
FXIconLabel |
Label that draws an icon in the theme's colours at paint time |
FXIconLineEdit |
Line edit with an icon on the left or right |
FXJoinedGroup |
Widgets side by side in one pill outline, such as a status and a Post button |
FXKeyboardTree |
Tree whose row menus, Enter and typing work from the keyboard |
FXKeycap |
A shortcut drawn as keys, one cap per key, round at the button radius; follows every theme switch |
FXLettersUnderscoreValidator |
Accepts letters and underscores, numbers optional |
FXLoadingOverlay |
Spinner over a widget, dimming it and blocking its input |
FXLoadingSpinner |
Animated loading indicator: spinner, dots or pulse |
FXLowerCaseValidator |
Accepts lowercase letters, numbers and underscores optional |
FXMainWindow |
Main window with menus, toolbar, status bar and a theme menu |
FXMentionEdit |
Text box that offers people by name after an @ and lists who it names |
FXNotificationBanner |
Card with a message that slides in from a window's right edge |
FXOutputLogHandler |
Logging handler that writes records into an FXOutputLogWidget |
FXOutputLogWidget |
Read-only log display with search |
FXPasswordLineEdit |
Password field with a show/hide eye icon |
FXPrimaryButton |
The main action of a form, on the theme's accent |
FXProgressCard |
Card showing a task's progress and status |
FXPygmentsHighlighter |
Pygments syntax highlighter for any QTextDocument |
FXRangeSlider |
Slider with two handles for a low and a high value |
FXRatingWidget |
Star rating input, halves optional |
FXResizedScrollArea |
Scroll area whose height follows its content, between a floor and a cap |
FXSearchBar |
Search field with a clear button and a debounced search signal |
FXSeating |
Seats a tray panel in the screen corner nearest its icon and slides it in |
FXSingleInstance |
Lock on a local socket name; a second start wakes the first |
FXSingleton |
Metaclass for Qt classes that have one instance |
FXSortedTreeWidgetItem |
Tree row that sorts numbers in text naturally (v2 before v10) |
FXSplashScreen |
Splash screen with a title, a text and a progress bar |
FXSplitButton |
Split button whose click and dropdown both have keys |
FXStatusBar |
Status bar with an accent line, messages, items and a busy line |
FXStatusDot |
Small clickable circle in a feedback colour, grey for no state |
FXStatusItem |
Icon and word on a status bar, lit when clickable |
FXSystemTray |
System tray icon with a menu |
FXTagChip |
One tag, removable or not |
FXTagInput |
Field that turns what you type into FXTagChips |
FXThreadLine |
Line over a comment thread, from the comment's face into each reply's |
FXThumbnailDelegate |
Item delegate with thumbnails, status dots, labels and stars |
FXTimelineSlider |
Timeline with playback, keyframes, markers and a loop region |
FXToggleSwitch |
On/off switch that slides |
FXValidatedLineEdit |
Line edit that shakes and flashes when its validator refuses a key |
fxdocking.FXDockArea docks named panes around a body; it needs
PySide6-QtAds (see Installation).
And these functions and constants:
| Name | What it does |
|---|---|
align_labels |
Gives the labels of several forms one right-aligned column |
apply_tip |
Sets a rich tooltip and a plain status tip on a widget, an action or a view's item (see Tooltips) |
fix_wrapped_heights |
Gives every word-wrapped label under a widget the height its width needs |
grab_screen_region |
Lets the user drag out a screen region and returns it, or None on Escape |
keycap |
Renders a shortcut as keys in a tooltip's HTML; on a window, use FXKeycap |
tip |
Returns the HTML apply_tip shows, in the theme in force |
DEFAULT_EMOJIS |
The emoji an FXEmojiPicker offers by default |
CRITICAL, ERROR, WARNING, SUCCESS, INFO, DEBUG |
Severities for messages, banners and progress cards |
Tip
Every widget follows a theme switch with no call of its own.
Breadcrumbs¶
from fxgui.fxwidgets import FXBreadcrumb
crumb = FXBreadcrumb(home_icon="", tab_stops=False)
crumb.set_path(["pilot", "sq010", "sh0040", "comp"])
crumb.set_edit_placeholder("Type a shot")
- Every segment but the last is a button: it tints under the pointer and shows a pointing hand. The last one is where the path already is, so it is bold and does nothing.
- The strip behind the segments is a filled field, brighter while the
pointer is over it. Double-click it to type a path; a press anywhere
outside closes the editor, and so does
exit_edit_mode(). - The colours are worked out each time the strip paints, from the
theme and from what the breadcrumb sits on: the frame colour on a
framed window's toolbar or a band marked with
mark_as_frame, the surface anywhere else. The text reads at 4.5:1 on both fills and the edge shows at 1.3:1 against the ground and both fills, in every bundled theme. A theme switch needs no call. tab_stops=Falsetakes the segments and the back and forward buttons out of the Tab order. The path editor keeps its stop.
The starting colours are class attributes, so a subclass names its own tokens:
from fxgui.fxwidgets import FXBreadcrumb
class HouseCrumb(FXBreadcrumb):
STRIP_RESTING_TOKEN = "surface_alt"
SEGMENT_HOVER_TOKEN = "text_muted"
SEGMENT_HOVER_ALPHA = 48
Do not point STRIP_RESTING_TOKEN at surface: in every bundled theme
that is the window's own colour, so on a plain window the strip
disappears.
Your Own Item-Data Roles¶
FXThumbnailDelegate reads item-data roles of its own off the items it
paints, from Qt.UserRole + 1 up to FIRST_FREE_ROLE, and
FXSortedTreeWidgetItem.SORT_ROLE sits in the same range. A view that puts
roles of its own on the same items derives them from FIRST_FREE_ROLE:
from fxgui.fxwidgets import FXThumbnailDelegate
ROW_KIND_ROLE = FXThumbnailDelegate.FIRST_FREE_ROLE
ROW_COLOR_ROLE = FXThumbnailDelegate.FIRST_FREE_ROLE + 1
Warning
Do not guess a number instead. Every number below FIRST_FREE_ROLE
is one the delegate reads: a view storing its own value on
CHILD_COUNT_VISIBLE_ROLE's number gets a child count drawn on rows
with no children.
A role added to the delegate moves FIRST_FREE_ROLE up, and every role
derived from it moves too.
Tooltips¶
apply_tip is fxgui's tooltip. It hands Qt's own setToolTip a small HTML string, and sets a markup-free status tip for the window's status bar:
from qtpy.QtWidgets import QPushButton
from fxgui.fxwidgets import apply_tip
save_button = QPushButton("Save")
apply_tip(
save_button,
"Save",
"Write the current scene to disk, overwriting the last version",
"Ctrl+S",
)
The title is in the theme's primary text, the body dimmed, and the shortcut sits on the right as keycaps, one per key: Ctrl S. The keys of one chord sit close; a second chord (Ctrl+K, Ctrl+S) sits further away. Key names come from QKeySequence, so a Mac shows its own glyphs rather than the word "Ctrl".
| Target | What happens |
|---|---|
| A widget | The tip is rebuilt each time it is about to show |
A QAction |
The tip is rebuilt when the action is hovered, before its tool button or menu shows it |
An item of a QListWidget, QTreeWidget or QTableWidget |
The view builds the tip when it shows; a tree item gets it on every column. Add the item to its view first, or apply_tip raises ValueError |
The HTML holds the colours of the theme in force, so rebuilding at show time is what makes a tip set in one theme show in the next. Every string is HTML-escaped, so a path holding & or < reaches the user as text, and a newline in the body breaks the line. Qt's rich text draws no rounded background, so a keycap in a tooltip is square.
Two lower-level helpers:
tip()returns the HTML. Call it when the tip shows: a model returnstip(...)fromdata()forQt.ToolTipRole, which Qt asks for on hover.keycap()returns a shortcut's keycaps as HTML. A label reads its text once, so a keycap on a window is anFXKeycapinstead: a widget, one cap per key, round at the button radius, that follows every theme switch.