Skip to content

fxwidgets

The fxgui widgets, each in its own private module, exported here.

Classes:

Name Description
FXAccordion

A multi-section collapsible accordion widget.

FXApplication

Customized QApplication class.

FXAvatar

A circle showing a person's photo, or their initials on a disc.

FXBreadcrumb

A path of clickable segments, with optional back and forward.

FXCamelCaseValidator

Accept camelCase letters: a lowercase start, no digits or symbols.

FXCapitalizedLetterValidator

Accept letters only; fixup capitalises the first.

FXCheckableComboBox

A combo whose popup stays open while several rows are ticked.

FXCodeBlock

A read-only code block with syntax highlighting and theme styling.

FXCollapsibleWidget

A header that slides its content open and shut on a click.

FXCommand

One row of the palette, and what picking it does.

FXCommandPalette

A frameless popup over window's commands; Enter runs, Escape closes.

FXCommandRow

A toolbar fixed in place: no handle, no floating, nothing to hide it.

FXConfirmDeleteDialog

Ask for a word, typed exactly, before an act with no undo.

FXDropZone

A drag and drop zone widget for file and folder selection.

FXElidedLabel

A QLabel that cuts its text with an ellipsis when it does not fit.

FXEmojiButton

A round icon button that opens an FXEmojiPicker just below itself.

FXEmojiPicker

A popup grid of emoji; picking one emits it and closes the popup.

FXFilePathWidget

A path field with a Browse button, a drop target and a validity mark.

FXFilteredTree

A tree under a filter bar, with expand-all and collapse-all buttons.

FXFloatingDialog

A floating dialog that appears at the cursor's position.

FXFlowLayout

Lay widgets out left to right, wrapping to a new line when full.

FXIconButton

A round, flat icon button, filled with the accent when checked.

FXIconLabel

A label that draws a QIcon when painted, so it takes theme inks then.

FXIconLineEdit

A line edit with an icon inside it, on the left or the right.

FXJoinedGroup

Widgets side by side in one button outline, with a divider between.

FXKeyboardTree

A tree whose rows a keyboard reaches as well as a mouse.

FXKeycap

A keyboard shortcut drawn as keys, one cap per key.

FXLettersUnderscoreValidator

Accept letters and underscores, and digits if allowed.

FXLoadingOverlay

A loading spinner centred over the parent widget.

FXLoadingSpinner

A quarter arc of the accent running round a muted ring.

FXLowerCaseValidator

Lowercase typed letters; accept digits or underscores if allowed.

FXMainWindow

Customized QMainWindow class.

FXMentionEdit

A text box that offers people by name after an @.

FXNotificationBanner

A notification card that slides in at the parent's top right.

FXOutputLogHandler

Logging handler that sends records to an output log widget.

FXOutputLogWidget

A read-only log pane with ANSI colours, search and a throttle.

FXPasswordLineEdit

A password field whose eye icon shows or hides what was typed.

FXPrimaryButton

The main action of a form, drawn on the theme's accent.

FXProgressCard

A card showing a task's progress: a title, a bar, a status icon.

FXPygmentsHighlighter

Syntax highlighter using Pygments for multi-language support.

FXRangeSlider

A slider with two handles for a low and a high value.

FXRatingWidget

A row of stars to click, with a preview under the pointer.

FXResizedScrollArea

A scroll area that can fit its content.

FXSearchBar

A line edit with a search icon, Qt's clear button and a debounce.

FXSeating

Seat a panel in the screen corner nearest its tray icon; slide it in.

FXSingleInstance

A lock on a local socket name; a second start wakes the first.

FXSingleton

Metaclass for Qt classes that are singletons.

FXSortedTreeWidgetItem

A row that sorts by its SORT_ROLE key, else naturally by its text.

FXSplashScreen

A splash screen: the image, a panel with the title, and a progress bar.

FXSplitButton

A split button whose click and dropdown both have keys.

FXStatusBar

Customized QStatusBar class.

FXStatusDot

A filled circle in a feedback colour, or grey for no state.

FXStatusItem

An icon and a word on a status bar, flat, lit when it is clickable.

FXSystemTray

A tray icon whose menu opens on a left click too, ending in Quit.

FXTagChip

A single removable tag chip.

FXTagInput

A field whose Enter turns the text into a chip; a chip's x removes it.

FXThreadLine

A line over a thread, from a comment's face into each reply's face.

FXThumbnailDelegate

Paint rows as a thumbnail, a title, a description and status marks.

FXTimelineSlider

A timeline/scrubber widget for DCC applications.

FXToggleSwitch

An on/off switch that slides, as tall as a push button.

FXValidatedLineEdit

A line edit that provides visual feedback when input is rejected.

Functions:

Name Description
align_labels

Give the labels of every form in forms one right-aligned column.

apply_tip

Set a rich tooltip on target, plus a markup-free status tip.

code_color

Return the colour code highlighting gives token in the current theme.

fix_wrapped_heights

Give every word-wrapped label under widget the height its width needs.

grab_screen_region

Let the user drag out a region of window's screen; None on Escape.

keycap

Render a keyboard shortcut as rich text, one keycap per key.

tip

Build the HTML for a rich tooltip.

Classes

FXAccordion

FXAccordion(
    parent: Optional[QWidget] = None,
    exclusive: bool = True,
    animation_duration: int = 150,
)

Bases: QWidget

A multi-section collapsible accordion widget.

Uses FXCollapsibleWidget for each section. By default, only one section can be open at a time (exclusive mode).

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

exclusive

bool

If True, only one section can be open at a time.

True

animation_duration

int

Duration of expand/collapse animation in ms.

150
Signals

section_expanded: Emitted when a section is expanded (section index). section_collapsed: Emitted when a section is collapsed (section index).

Examples:

>>> accordion = FXAccordion()
>>> accordion.add_section("General", general_content, icon="settings")
>>> accordion.add_section("Advanced", advanced_content, icon="tune")
>>> accordion.add_section("Info", info_content, icon="info")

Methods:

Name Description
__iter__

Iterate over sections.

__len__

Return the number of sections.

add_section

Add a section titled title, return it.

collapse_all

Collapse all sections.

collapse_section

Collapse the section at index; out of range does nothing.

exclusive

Return whether only one section can be open at a time.

expand_all

Expand all sections.

expand_section

Expand the section at index; out of range does nothing.

get_section

Return the section at index, or None out of range.

remove_section

Remove the section at index; an index out of range does nothing.

set_exclusive

Set whether only one section can be open at a time.

Methods:

__iter__
__iter__()

Iterate over sections.

__len__
__len__() -> int

Return the number of sections.

add_section
add_section(
    title: str,
    content: Optional[Union[QWidget, QLayout]] = None,
    icon: Optional[str] = None,
) -> FXCollapsibleWidget

Add a section titled title, return it.

Parameters:

Name Type Description Default
content
Optional[Union[QWidget, QLayout]]

A widget or a layout for the section's body.

None
icon
Optional[str]

An icon name for the header.

None
collapse_all
collapse_all() -> None

Collapse all sections.

collapse_section
collapse_section(index: int) -> None

Collapse the section at index; out of range does nothing.

exclusive
exclusive() -> bool

Return whether only one section can be open at a time.

expand_all
expand_all() -> None

Expand all sections.

Raises:

Type Description
RuntimeError

The accordion is exclusive.

expand_section
expand_section(index: int) -> None

Expand the section at index; out of range does nothing.

get_section
get_section(index: int) -> Optional[FXCollapsibleWidget]

Return the section at index, or None out of range.

remove_section
remove_section(index: int) -> None

Remove the section at index; an index out of range does nothing.

set_exclusive
set_exclusive(value: bool) -> None

Set whether only one section can be open at a time.

FXApplication

FXApplication(*args, **kwargs)

Bases: QApplication

Customized QApplication class.

On initialization, the application loads the previously saved theme from persistent storage. If no theme was saved, defaults to "dark".

Note

Qt allows a single QApplication per process. When one already exists and is not an FXApplication (e.g. inside Houdini, Maya, or Nuke), calling FXApplication() returns the host's application instance untouched instead of raising RuntimeError. fxgui styling is NOT applied to the host application in that case; fxgui's windows, dialogs, tray menu and splash register themselves as themed roots.

FXAvatar

FXAvatar(
    name: str = "",
    parent: Optional[QWidget] = None,
    *,
    size: int = 26,
    pixmap: Optional[QPixmap] = None
)

Bases: QWidget

A circle showing a person's photo, or their initials on a disc.

The disc colour comes from the name, so one person keeps one colour in every thread and across runs.

Parameters:

Name Type Description Default

name

str

The person's name; its first two words give the initials.

''

parent

Optional[QWidget]

Parent widget.

None

size

int

The circle's diameter, in logical pixels.

26

pixmap

Optional[QPixmap]

A photo, cropped to the circle. Replaces the initials.

None

Examples:

>>> avatar = FXAvatar("Anne Martin", size=32)
>>> avatar.set_pixmap(QPixmap("anne.png"))

Methods:

Name Description
color

Return the disc colour the name picks.

initials

Return the initials drawn on the disc, empty for no name.

name

Return the person's name.

paintEvent

Paint the photo or the initials disc.

set_name

Show name's initials and colour, and use it as the tooltip.

set_pixmap

Show pixmap cropped round, or the initials again for None.

set_size

Resize the circle to size logical pixels across.

Methods:

color
color() -> QColor

Return the disc colour the name picks.

initials
initials() -> str

Return the initials drawn on the disc, empty for no name.

name
name() -> str

Return the person's name.

paintEvent
paintEvent(event) -> None

Paint the photo or the initials disc.

set_name
set_name(name: str) -> None

Show name's initials and colour, and use it as the tooltip.

set_pixmap
set_pixmap(pixmap: Optional[QPixmap]) -> None

Show pixmap cropped round, or the initials again for None.

set_size
set_size(size: int) -> None

Resize the circle to size logical pixels across.

FXBreadcrumb

FXBreadcrumb(
    parent: Optional[QWidget] = None,
    separator: str = "chevron_right",
    home_icon: str = "home",
    show_navigation: bool = False,
    path_separator: str = "/",
    home_path: Optional[List[str]] = None,
    tab_stops: bool = True,
)

Bases: QWidget

A path of clickable segments, with optional back and forward.

A double-click opens an editor to type a path; Escape or a click away closes it.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

separator

str

Icon name for separator between segments.

'chevron_right'

home_icon

str

Icon name for the home/root segment.

'home'

show_navigation

bool

Show back/forward navigation buttons.

False

path_separator

str

Character used to join path segments in edit mode.

'/'

home_path

Optional[List[str]]

Path segments to navigate to when home is clicked. If None, navigates to the first segment only.

None

tab_stops

bool

Whether the segments and the back and forward buttons take Tab stops. False leaves them to the mouse; the path editor keeps its own.

True
Signals

segment_clicked: Emitted when a segment is clicked (index, path list). home_clicked: Emitted when the home segment is clicked. path_edited: Emitted when user submits a typed path (raw string). navigated_back: Emitted when navigating back in history. navigated_forward: Emitted when navigating forward in history.

Examples:

>>> breadcrumb = FXBreadcrumb(show_navigation=True)
>>> breadcrumb.set_path(["Home", "Projects", "MyProject", "Assets"])
>>> breadcrumb.segment_clicked.connect(
...     lambda idx, path: print(f"Navigate to: {'/'.join(path[:idx+1])}")
... )
>>> breadcrumb.path_edited.connect(lambda text: print(f"User typed: {text}"))

Methods:

Name Description
append_segment

Append segment to the path.

can_go_back

Check if back navigation is available.

can_go_forward

Check if forward navigation is available.

clear

Clear the breadcrumb path.

clear_history

Clear the navigation history.

enterEvent

Brighten the strip while the pointer is anywhere over the path.

enter_edit_mode

Switch to edit mode with the line edit visible.

eventFilter

Enter the editor on a double-click; leave it on Escape or away.

exit_edit_mode

Close the editor without submitting, as Escape does.

go_back

Step back through the history; return whether it moved.

go_forward

Step forward through the history; return whether it moved.

home_path

Return where a home click goes; None means the first segment.

is_editing

Check if currently in edit mode.

leaveEvent

Return the strip to its resting fill.

navigate_to

Cut the path after index and say segment_clicked.

path

Return the current path segments.

pop_segment

Remove and return the last segment, or None on an empty path.

set_edit_placeholder

Set the hint the path editor shows while it is empty.

set_home_path

Set the path a home click goes to; None means the first segment.

set_path

Show path, recording it in the history unless told not to.

Methods:

append_segment
append_segment(segment: str) -> None

Append segment to the path.

can_go_back
can_go_back() -> bool

Check if back navigation is available.

can_go_forward
can_go_forward() -> bool

Check if forward navigation is available.

clear
clear() -> None

Clear the breadcrumb path.

clear_history
clear_history() -> None

Clear the navigation history.

enterEvent
enterEvent(event) -> None

Brighten the strip while the pointer is anywhere over the path.

Not a :hover rule: once the path is drawn, the widget directly under the pointer is a segment, never the strip.

enter_edit_mode
enter_edit_mode() -> None

Switch to edit mode with the line edit visible.

eventFilter
eventFilter(obj, event)

Enter the editor on a double-click; leave it on Escape or away.

While the editor is up this widget also filters the application: a press on a heading or a window's background moves no focus.

exit_edit_mode
exit_edit_mode() -> None

Close the editor without submitting, as Escape does.

Public: a window-level Escape shortcut fires before this widget sees the key, so such a window calls this itself.

go_back
go_back() -> bool

Step back through the history; return whether it moved.

go_forward
go_forward() -> bool

Step forward through the history; return whether it moved.

home_path
home_path() -> Optional[List[str]]

Return where a home click goes; None means the first segment.

is_editing
is_editing() -> bool

Check if currently in edit mode.

leaveEvent
leaveEvent(event) -> None

Return the strip to its resting fill.

navigate_to
navigate_to(index: int) -> None

Cut the path after index and say segment_clicked.

path
path() -> List[str]

Return the current path segments.

pop_segment
pop_segment() -> Optional[str]

Remove and return the last segment, or None on an empty path.

set_edit_placeholder
set_edit_placeholder(text: str) -> None

Set the hint the path editor shows while it is empty.

set_home_path
set_home_path(path: Optional[List[str]]) -> None

Set the path a home click goes to; None means the first segment.

set_path
set_path(path: List[str], record_history: bool = True) -> None

Show path, recording it in the history unless told not to.

FXCamelCaseValidator

FXCamelCaseValidator(parent=None)

Bases: QRegularExpressionValidator

Accept camelCase letters: a lowercase start, no digits or symbols.

Examples:

>>> from qtpy.QtWidgets import QLineEdit
>>> line_edit = QLineEdit()
>>> line_edit.setValidator(FXCamelCaseValidator())

FXCapitalizedLetterValidator

Bases: QValidator

Accept letters only; fixup capitalises the first.

Examples:

>>> from qtpy.QtWidgets import QLineEdit
>>> line_edit = QLineEdit()
>>> line_edit.setValidator(FXCapitalizedLetterValidator())

Methods:

Name Description
fixup

Automatically capitalize the first letter.

validate

Allow only letters; a lowercase start waits for fixup.

Methods:

fixup
fixup(input_string: str) -> str

Automatically capitalize the first letter.

validate
validate(input_string: str, pos: int)

Allow only letters; a lowercase start waits for fixup.

FXCheckableComboBox

FXCheckableComboBox(parent: Optional[QWidget] = None)

Bases: QComboBox

A combo whose popup stays open while several rows are ticked.

A plain QComboBox closes its popup on the first click, so ticking three values would take three openings. Here a click or Space ticks the row and the popup stays; the closed combo reads the ticked rows.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None
Signals

checked_changed: The ticked rows' texts, in row order.

Examples:

>>> combo = FXCheckableComboBox()
>>> combo.add_items(["render", "cache", "plate"])
>>> combo.set_checked_items(["cache"])

Methods:

Name Description
add_items

Add one unticked row per text.

checked_items

Return the ticked rows' texts, in row order.

display_text

Return what the closed combo reads: the ticked rows, joined.

eventFilter

Tick a row on a click or Space, and keep the popup open.

paintEvent

Draw the combo with the ticked rows as its text.

set_checked_items

Tick exactly the rows whose text is in texts.

Methods:

add_items
add_items(texts: Iterable[str]) -> None

Add one unticked row per text.

checked_items
checked_items() -> List[str]

Return the ticked rows' texts, in row order.

display_text
display_text() -> str

Return what the closed combo reads: the ticked rows, joined.

eventFilter
eventFilter(watched: QObject, event: QEvent) -> bool

Tick a row on a click or Space, and keep the popup open.

paintEvent
paintEvent(event) -> None

Draw the combo with the ticked rows as its text.

set_checked_items
set_checked_items(texts: Iterable[str]) -> None

Tick exactly the rows whose text is in texts.

FXCodeBlock

FXCodeBlock(
    code: str = "", language: str = "python", parent: Optional[QWidget] = None
)

Bases: QWidget

A read-only code block with syntax highlighting and theme styling.

Parameters:

Name Type Description Default

code

str

The code string to display.

''

language

str

The programming language (e.g., "python", "javascript").

'python'

parent

Optional[QWidget]

The parent widget.

None
Example

code = ''' ... def hello(): ... print("Hello, World!") ... ''' code_block = FXCodeBlock(code)

Methods:

Name Description
code

Return the code shown.

set_code

Show code, stripped, and fit the height to it.

set_language

Highlight language from now on, plain text if unknown.

Methods:

code
code() -> str

Return the code shown.

set_code
set_code(code: str) -> None

Show code, stripped, and fit the height to it.

set_language
set_language(language: str) -> None

Highlight language from now on, plain text if unknown.

FXCollapsibleWidget

FXCollapsibleWidget(
    parent: Optional[QWidget] = None,
    title: str = "",
    icon: Optional[Union[QIcon, str]] = None,
    animation_duration: int = 150,
    max_content_height: int = 300,
)

Bases: QWidget

A header that slides its content open and shut on a click.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

title

str

Title displayed in the header.

''

icon

Optional[Union[QIcon, str]]

Optional icon to display before the title. Can be a QIcon, an icon name string (for fxicons), or None.

None

animation_duration

int

Duration of expand/collapse animation in ms.

150

max_content_height

int

Maximum height of the open content area; taller content scrolls. 0 means no limit.

300
Signals

expanded: Emitted when the widget is expanded. collapsed: Emitted when the widget is collapsed.

Examples:

>>> from qtpy.QtWidgets import QLabel, QVBoxLayout
>>> collapsible = FXCollapsibleWidget(title="Settings")
>>> layout = QVBoxLayout()
>>> layout.addWidget(QLabel("Option 1"))
>>> layout.addWidget(QLabel("Option 2"))
>>> collapsible.set_content_layout(layout)
>>>
>>> # With an icon
>>> collapsible_with_icon = FXCollapsibleWidget(
...     title="Settings",
...     icon="settings"
... )

Initialize the collapsible section.

Methods:

Name Description
animation_duration

Return the animation duration in milliseconds.

collapse

Hide the content, sliding shut unless animate is False.

eventFilter

Toggle on a left click anywhere on the header.

expand

Show the content, sliding open unless animate is False.

icon

Return the icon before the title, or None.

is_expanded

Return whether the widget is expanded.

max_content_height

Return the open content area's cap; 0 means no limit.

set_animation_duration

Set the animation duration in milliseconds.

set_content_layout

Put content_layout on a new widget as the content.

set_content_widget

Show widget as the content.

set_icon

Set an icon to display before the title.

set_max_content_height

Set the open content area's cap, at once if it is open.

set_title

Set the title text.

title

Return the title text.

toggle

Toggle the expanded/collapsed state.

Methods:

animation_duration
animation_duration() -> int

Return the animation duration in milliseconds.

collapse
collapse(animate: bool = True) -> None

Hide the content, sliding shut unless animate is False.

eventFilter
eventFilter(watched: QObject, event: QEvent) -> bool

Toggle on a left click anywhere on the header.

expand
expand(animate: bool = True) -> None

Show the content, sliding open unless animate is False.

icon
icon() -> Optional[QIcon]

Return the icon before the title, or None.

is_expanded
is_expanded() -> bool

Return whether the widget is expanded.

max_content_height
max_content_height() -> int

Return the open content area's cap; 0 means no limit.

set_animation_duration
set_animation_duration(value: int) -> None

Set the animation duration in milliseconds.

set_content_layout
set_content_layout(content_layout: QLayout) -> None

Put content_layout on a new widget as the content.

set_content_widget
set_content_widget(widget: QWidget) -> None

Show widget as the content.

set_icon
set_icon(icon: Union[QIcon, str, None]) -> None

Set an icon to display before the title.

Parameters:

Name Type Description Default
icon
Union[QIcon, str, None]

The icon to display. Can be: - A QIcon instance - A string icon name (resolved via fxicons.get_icon) - None to remove the icon

required

Examples:

>>> collapsible = FXCollapsibleWidget(title="Settings")
>>> collapsible.set_icon("settings")  # Using icon name
>>> collapsible.set_icon(QIcon("path/to/icon.png"))  # Using QIcon
>>> collapsible.set_icon(None)  # Remove icon
set_max_content_height
set_max_content_height(value: int) -> None

Set the open content area's cap, at once if it is open.

set_title
set_title(title: str) -> None

Set the title text.

title
title() -> str

Return the title text.

toggle
toggle() -> None

Toggle the expanded/collapsed state.

FXCommand dataclass

FXCommand(
    label: str,
    run: Optional[Callable[[], None]] = None,
    keys: str = "",
    section: str = "",
    enabled: bool = True,
    tip: str = "",
    icon: str = "",
    choices: Optional[Callable[[], List[FXCommand]]] = None,
    key: str = "",
)

One row of the palette, and what picking it does.

Parameters:

Name Type Description Default

label

str

What the row reads.

required

run

Optional[Callable[[], None]]

Called when the row is picked; unused where choices is set.

None

keys

str

Its shortcut, as QKeySequence reads it, shown at the right.

''

section

str

The group it belongs to, shown beside the label and matched by the search.

''

enabled

bool

False shows the row greyed; picking it shows tip.

True

tip

str

Shown under the list while the row is current.

''

icon

str

An icon's name, drawn left of the label: a material one, or library:name for another library, such as brands:houdini_mark.

''

choices

Optional[Callable[[], List[FXCommand]]]

Picking the row lists what this returns, in place, to pick one; a choice with its own choices steps in again.

None

key

str

What the palette remembers the row by; the label where empty. Give one where the label changes, as "Show Log" and "Hide Log".

''

FXCommandPalette

FXCommandPalette(
    window: QWidget,
    commands: Callable[[], List[FXCommand]],
    recent: Sequence[str] = (),
)

Bases: QFrame

A frameless popup over window's commands; Enter runs, Escape closes.

Every typed word must appear, in order, in a row's label and section. Rows run lately come first, the latest on top, as in VS Code; then rows where the words start words.

Parameters:

Name Type Description Default

window

QWidget

The window the palette opens over.

required

commands

Callable[[], List[FXCommand]]

Returns the commands each time the palette opens.

required

recent

Sequence[str]

The keys run lately, the latest first, to start from.

()
Signals

recent_changed: The keys run lately, the latest first, after a run; store them to keep the order across sessions.

Examples:

>>> palette = FXCommandPalette(window, lambda: [
...     FXCommand("Collapse all", tree.collapseAll, "Ctrl+-"),
... ])
>>> palette.open_commands(position="top")

Methods:

Name Description
keyPressEvent

Move with the arrows and pages; Escape closes.

open_commands

Open on the window's commands, at position in the window.

open_go_to

Open on the rows load hands back; picking one selects its id.

rank

Return how well query matches text, lower first; None for no.

Methods:

keyPressEvent
keyPressEvent(event: QKeyEvent) -> None

Move with the arrows and pages; Escape closes.

open_commands
open_commands(
    placeholder: str = "Type a command", position: str = "center"
) -> None

Open on the window's commands, at position in the window.

Raises:

Type Description
ValueError

If position is not one of POSITIONS.

open_go_to
open_go_to(
    load: GoTo,
    select: Callable[[str], None],
    placeholder: str = "Type a name, or > for a command",
    loading: str = "Loading",
    position: str = "center",
) -> None

Open on the rows load hands back; picking one selects its id.

A leading > switches to the commands. Until load calls back, the list reads loading.

Parameters:

Name Type Description Default
load
GoTo

Called once with a callback taking (row id, words) pairs; it may call back later, from this thread.

required
select
Callable[[str], None]

Called with the picked row's id.

required
placeholder
str

What the empty field says.

'Type a name, or > for a command'
loading
str

What the list says until the rows land.

'Loading'
position
str

Where in the window it opens; one of POSITIONS.

'center'

Raises:

Type Description
ValueError

If position is not one of POSITIONS.

rank staticmethod
rank(query: str, text: str) -> Optional[int]

Return how well query matches text, lower first; None for no.

Every word of query must appear in text in order, ignoring case; the rank counts the words that start no word of text.

FXCommandRow

FXCommandRow(
    title: str = "Command row",
    parent: Optional[QWidget] = None,
    margins: Optional[Tuple[int, int, int, int]] = None,
    spacing: Optional[int] = None,
    icon_size: int = 17,
)

Bases: QToolBar

A toolbar fixed in place: no handle, no floating, nothing to hide it.

Its margins and spacing hold through style and theme changes, which otherwise reset a toolbar's layout to the style's own.

Parameters:

Name Type Description Default

title

str

The toolbar's window title. Defaults to "Command row".

'Command row'

parent

Optional[QWidget]

Parent widget. Defaults to None.

None

margins

Optional[Tuple[int, int, int, int]]

Left, top, right and bottom, in pixels. Defaults to the style's own.

None

spacing

Optional[int]

Between controls, in pixels. Defaults to the style's own.

None

icon_size

int

The side of its tool button icons. Defaults to 17.

17

Examples:

>>> row = FXCommandRow(margins=(6, 6, 6, 0))
>>> window.addToolBar(Qt.TopToolBarArea, row)

Methods:

Name Description
changeEvent

Put the margins back after a style change resets them.

Methods:

changeEvent
changeEvent(event: QEvent) -> None

Put the margins back after a style change resets them.

FXConfirmDeleteDialog

FXConfirmDeleteDialog(
    parent: Optional[QWidget] = None,
    *,
    title: str,
    body: str,
    confirm_word: str
)

Bases: QDialog

Ask for a word, typed exactly, before an act with no undo.

Delete opens only while the field holds confirm_word exactly, and it is never the default button, so a stray Enter destroys nothing. Clicking the word copies it.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

title

str

The window title, naming what is going.

required

body

str

What will be destroyed, including that it cannot be undone.

required

confirm_word

str

What has to be typed.

required

Examples:

>>> dialog = FXConfirmDeleteDialog(
...     window, title="Delete beauty v004",
...     body="This cannot be undone.", confirm_word="beauty")
>>> if dialog.exec():
...     delete_version()

Methods:

Name Description
copy_word

Put the confirmation word on the clipboard.

eventFilter

Copy the word when its label is clicked.

Methods:

copy_word
copy_word() -> None

Put the confirmation word on the clipboard.

eventFilter
eventFilter(watched: QObject, event: QEvent) -> bool

Copy the word when its label is clicked.

FXDropZone

FXDropZone(
    parent: Optional[QWidget] = None,
    title: str = "Drag and Drop Files Here",
    description: str = "or use the Browse Files... button below",
    accept_mode: str = "files",
    extensions: Optional[Set[str]] = None,
    multiple: bool = True,
    icon_name: str = "upload_file",
    show_formats: bool = True,
    show_buttons: bool = True,
    show_tree: bool = True,
)

Bases: QWidget

A drag and drop zone widget for file and folder selection.

The zone takes drops on its placeholder and on its file list alike: neither child accepts drops, so Qt hands them to the zone.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

title

str

Main title text displayed in the drop zone.

'Drag and Drop Files Here'

description

str

Description text displayed below the title.

'or use the Browse Files... button below'

accept_mode

str

What to accept: 'files', 'folders' or 'both'.

'files'

extensions

Optional[Set[str]]

Allowed file extensions, such as {'.png', '.JPG'}; case and a missing leading dot do not matter. None accepts all.

None

multiple

bool

Whether to allow multiple file/folder selection.

True

icon_name

str

Icon name to display (default: 'upload_file').

'upload_file'

show_formats

bool

Whether to display accepted formats below title.

True

show_buttons

bool

Whether to show Browse/Clear buttons.

True

show_tree

bool

Whether to show file tree after files are dropped.

True

Raises:

Type Description
ValueError

accept_mode is not one of ACCEPT_MODES.

Signals

files_dropped: Emitted when files/folders are dropped or selected. Passes a list of Path objects. files_cleared: Emitted when files are cleared. file_removed: Emitted when a single file is removed from the tree. Passes the Path that was removed. drag_entered: Emitted when a valid drag enters the drop zone. drag_left: Emitted when a drag leaves the drop zone.

Examples:

>>> # Accept image files only with tree view
>>> drop_zone = FXDropZone(
...     title="Drop Images Here",
...     description="or use the Browse Files... button below",
...     extensions={'.png', '.jpg', '.exr'},
...     show_tree=True
... )
>>> drop_zone.files_dropped.connect(lambda paths: print(paths))
>>>
>>> # Accept folders only (no tree)
>>> folder_zone = FXDropZone(
...     title="Drop Project Folder",
...     accept_mode='folders',
...     show_tree=False
... )

Methods:

Name Description
accept_mode

Return the accept mode: 'files', 'folders' or 'both'.

add_files

Add the paths not held yet, saying files_dropped.

clear

Remove every file and say files_cleared.

description

Return the description text.

dragEnterEvent

Accept a drag that carries a path the zone takes.

dragLeaveEvent

Return the area to rest.

dropEvent

Add the accepted paths; edge the area in error if none were.

extensions

Return the accepted extensions, lowercase with a leading dot.

file_tree

Return the file tree widget, or None without show_tree.

has_files

Return whether files have been added.

multiple

Return whether multiple selection is enabled.

selected_files

Return the list of selected files.

set_accept_mode

Set the accept mode: 'files', 'folders' or 'both'.

set_description

Set the description text.

set_extensions

Set the accepted extensions; None or none at all accepts all.

set_files

Replace the selected files, saying nothing.

set_icon

Show the fxicons icon icon_name in the area.

set_multiple

Set whether multiple selection is enabled.

set_title

Set the title text.

title

Return the title text.

Methods:

accept_mode
accept_mode() -> str

Return the accept mode: 'files', 'folders' or 'both'.

add_files
add_files(paths: List[Path]) -> None

Add the paths not held yet, saying files_dropped.

clear
clear() -> None

Remove every file and say files_cleared.

description
description() -> str

Return the description text.

dragEnterEvent
dragEnterEvent(event: QDragEnterEvent) -> None

Accept a drag that carries a path the zone takes.

dragLeaveEvent
dragLeaveEvent(event: QDragLeaveEvent) -> None

Return the area to rest.

dropEvent
dropEvent(event: QDropEvent) -> None

Add the accepted paths; edge the area in error if none were.

extensions
extensions() -> Optional[Set[str]]

Return the accepted extensions, lowercase with a leading dot.

file_tree
file_tree() -> Optional[QTreeWidget]

Return the file tree widget, or None without show_tree.

has_files
has_files() -> bool

Return whether files have been added.

multiple
multiple() -> bool

Return whether multiple selection is enabled.

selected_files
selected_files() -> List[Path]

Return the list of selected files.

set_accept_mode
set_accept_mode(value: str) -> None

Set the accept mode: 'files', 'folders' or 'both'.

Raises:

Type Description
ValueError

value is not one of ACCEPT_MODES.

set_description
set_description(value: str) -> None

Set the description text.

set_extensions
set_extensions(value: Optional[Iterable[str]]) -> None

Set the accepted extensions; None or none at all accepts all.

set_files
set_files(paths: List[Path]) -> None

Replace the selected files, saying nothing.

set_icon
set_icon(icon_name: str) -> None

Show the fxicons icon icon_name in the area.

set_multiple
set_multiple(value: bool) -> None

Set whether multiple selection is enabled.

set_title
set_title(value: str) -> None

Set the title text.

title
title() -> str

Return the title text.

FXElidedLabel

FXElidedLabel(
    text: str = "",
    parent: Optional[QWidget] = None,
    mode: TextElideMode = ElideRight,
)

Bases: QLabel

A QLabel that cuts its text with an ellipsis when it does not fit.

On one line the text is cut where mode says. With wordWrap() on and a maximum height set, it is cut from the right at the last line that fits; mode has no meaning across wrapped lines.

Parameters:

Name Type Description Default

text

str

The label's text.

''

parent

Optional[QWidget]

Parent widget.

None

mode

TextElideMode

Where one line is cut. Qt.ElideMiddle keeps apart strings that share a tail, such as paths under one root.

ElideRight

Examples:

>>> label = FXElidedLabel("a very long identity", mode=Qt.ElideMiddle)

Methods:

Name Description
changeEvent

Re-elide text in a new font.

elided_text

Return the text as painted, shortened to fit the label.

event

Show the whole text as the tip of a cut label with no tip set.

minimumSizeHint

Return no width and one line's height, so the label can shrink.

mode

Return where one line is cut when it does not fit.

resizeEvent

Re-elide text when the label is resized.

setText

Set the text and store the full text for elision.

set_mode

Cut one line where mode says from now on.

sizeHint

Ask for the room the whole text needs, on one line.

text

Return the whole text that was set, not the shortened one.

Methods:

changeEvent
changeEvent(event: QEvent) -> None

Re-elide text in a new font.

elided_text
elided_text() -> str

Return the text as painted, shortened to fit the label.

event
event(event: QEvent) -> bool

Show the whole text as the tip of a cut label with no tip set.

minimumSizeHint
minimumSizeHint() -> QSize

Return no width and one line's height, so the label can shrink.

mode
mode() -> TextElideMode

Return where one line is cut when it does not fit.

resizeEvent
resizeEvent(event) -> None

Re-elide text when the label is resized.

setText
setText(text: str) -> None

Set the text and store the full text for elision.

set_mode
set_mode(mode: TextElideMode) -> None

Cut one line where mode says from now on.

sizeHint
sizeHint() -> QSize

Ask for the room the whole text needs, on one line.

text
text() -> str

Return the whole text that was set, not the shortened one.

FXEmojiButton

FXEmojiButton(
    parent: Optional[QWidget] = None,
    emojis: Optional[Sequence[str]] = None,
    size: int = 28,
)

Bases: FXIconButton

A round icon button that opens an FXEmojiPicker just below itself.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

emojis

Optional[Sequence[str]]

The emoji to offer. Defaults to DEFAULT_EMOJIS.

None

size

int

The circle's diameter, in logical pixels.

28
Signals

emoji_picked(str): The emoji picked.

Examples:

>>> button = FXEmojiButton(toolbar)
>>> button.attach(comment_editor)

Methods:

Name Description
attach

Insert each picked emoji at editor's cursor and focus it again.

open_picker

Show the popup just below the button, or above it near the bottom.

picker

Return the popup, built on first use.

Methods:

attach
attach(editor: QWidget) -> None

Insert each picked emoji at editor's cursor and focus it again.

Replaces the editor attached before, if any.

Parameters:

Name Type Description Default
editor
QWidget

A QLineEdit, QPlainTextEdit or QTextEdit.

required

Raises:

Type Description
TypeError

If editor is none of those.

open_picker
open_picker() -> None

Show the popup just below the button, or above it near the bottom.

picker
picker() -> FXEmojiPicker

Return the popup, built on first use.

FXEmojiPicker

FXEmojiPicker(
    parent: Optional[QWidget] = None,
    emojis: Optional[Sequence[str]] = None,
    columns: int = 8,
)

Bases: QFrame

A popup grid of emoji; picking one emits it and closes the popup.

Arrow keys move through the grid, Enter or Space picks, Escape closes without picking.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget; the popup stays its child.

None

emojis

Optional[Sequence[str]]

The emoji to offer. Defaults to DEFAULT_EMOJIS.

None

columns

int

How many emoji per row.

8
Signals

emoji_picked(str): The emoji picked.

Examples:

>>> picker = FXEmojiPicker(button)
>>> picker.emoji_picked.connect(editor.insertPlainText)
>>> picker.popup_at(button.mapToGlobal(QPoint(0, button.height())))

Methods:

Name Description
buttons

Return the grid's buttons, one per emoji, in order.

columns

Return how many emoji each row holds.

eventFilter

Move through the grid with the arrows, pick with Enter or Space.

mousePressEvent

Close on a press outside, without reopening from the anchor.

popup_at

Show the popup at global pos, kept on screen.

Methods:

buttons
buttons() -> List[QToolButton]

Return the grid's buttons, one per emoji, in order.

columns
columns() -> int

Return how many emoji each row holds.

eventFilter
eventFilter(watched: QObject, event: QEvent) -> bool

Move through the grid with the arrows, pick with Enter or Space.

mousePressEvent
mousePressEvent(event) -> None

Close on a press outside, without reopening from the anchor.

popup_at
popup_at(pos: QPoint, anchor: Optional[QRect] = None) -> None

Show the popup at global pos, kept on screen.

Parameters:

Name Type Description Default
pos
QPoint

The popup's top-left, in global coordinates.

required
anchor
Optional[QRect]

The global rect of the widget that opened it. With no room below, the popup opens above it instead of covering it.

None

FXFilePathWidget

FXFilePathWidget(
    parent: Optional[QWidget] = None,
    mode: str = "file",
    placeholder: str = "Select path...",
    file_filter: str = "All Files (*)",
    default_path: Optional[str] = None,
    validate: bool = True,
)

Bases: QWidget

A path field with a Browse button, a drop target and a validity mark.

The check runs on a worker thread, so a share that does not answer stalls the mark, never the window.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

mode

str

Selection mode: 'file', 'files', 'folder' or 'save'.

'file'

placeholder

str

Placeholder text.

'Select path...'

file_filter

str

File filter for file dialogs (e.g., "Images (*.png *.jpg)").

'All Files (*)'

default_path

Optional[str]

Default path for the file dialog.

None

validate

bool

Whether to show validation indicator.

True

Raises:

Type Description
ValueError

mode is not one of MODES.

Signals

path_changed: Emitted when the path changes. path_valid: Whether the path exists as the mode asks, after each check.

Examples:

>>> path_widget = FXFilePathWidget(mode='file', file_filter="Python (*.py)")
>>> path_widget.path_changed.connect(lambda p: print(f"Path: {p}"))
>>>
>>> # Folder mode
>>> folder_widget = FXFilePathWidget(mode='folder')

Methods:

Name Description
clear

Clear the path input.

dragEnterEvent

Handle drag enter for file drops.

dropEvent

Handle file drop.

is_valid

Return whether the current path is valid.

path

Return the current path.

set_file_filter

Set the dialogs' filter, such as "Images (*.png *.jpg)".

set_mode

Set the mode: 'file', 'files', 'folder' or 'save'.

set_path

Set the path shown.

Methods:

clear
clear() -> None

Clear the path input.

dragEnterEvent
dragEnterEvent(event) -> None

Handle drag enter for file drops.

dropEvent
dropEvent(event) -> None

Handle file drop.

is_valid
is_valid() -> bool

Return whether the current path is valid.

path
path() -> str

Return the current path.

set_file_filter
set_file_filter(filter_str: str) -> None

Set the dialogs' filter, such as "Images (*.png *.jpg)".

set_mode
set_mode(mode: str) -> None

Set the mode: 'file', 'files', 'folder' or 'save'.

Raises:

Type Description
ValueError

mode is not one of MODES.

set_path
set_path(path: str) -> None

Set the path shown.

FXFilteredTree

FXFilteredTree(
    tree: Optional[FXKeyboardTree] = None,
    placeholder: str = "Filter...",
    actions: Optional[QLayout] = None,
    parent: Optional[QWidget] = None,
)

Bases: QWidget

A tree under a filter bar, with expand-all and collapse-all buttons.

Typing on the tree goes to the bar, and the bar narrows the tree with fxutils.filter_tree: a match keeps its subtree and its ancestors.

Parameters:

Name Type Description Default

tree

Optional[FXKeyboardTree]

The tree to wrap; a new FXKeyboardTree when omitted.

None

placeholder

str

What the empty filter bar says.

'Filter...'

actions

Optional[QLayout]

A row of buttons under the tree, if any.

None

parent

Optional[QWidget]

The parent widget.

None

FXFloatingDialog

FXFloatingDialog(
    parent: Optional[QWidget] = None,
    icon: Optional[QPixmap] = None,
    title: Optional[str] = None,
    popup: bool = False,
)

Bases: QDialog

A floating dialog that appears at the cursor's position.

It closes when any mouse button except the right one is pressed, and is deleted once closed.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget. Defaults to None.

None

icon

Optional[QPixmap]

The title's icon. Defaults to a home icon in the theme's icon color.

None

title

Optional[str]

The dialog title. Defaults to "Floating Dialog".

None

popup

bool

Whether it closes on a click outside, as a menu does. A popup casts no painted shadow. Defaults to False.

False

Methods:

Name Description
mousePressEvent

Close on a press of any button but the right one.

set_dialog_icon

Set the title's icon; None is the theme's home icon.

set_dialog_title

Set the title; None or empty reads "Floating Dialog".

show_under_cursor

Centre the dialog on the cursor at its final size and run it.

Methods:

mousePressEvent
mousePressEvent(event: QMouseEvent) -> None

Close on a press of any button but the right one.

set_dialog_icon
set_dialog_icon(icon: Optional[QPixmap] = None) -> None

Set the title's icon; None is the theme's home icon.

set_dialog_title
set_dialog_title(title: Optional[str] = None) -> None

Set the title; None or empty reads "Floating Dialog".

show_under_cursor
show_under_cursor() -> int

Centre the dialog on the cursor at its final size and run it.

Returns:

Name Type Description
int int

exec()'s DialogCode, Accepted or Rejected.

FXFlowLayout

FXFlowLayout(parent: Optional[QWidget] = None, spacing: int = PANE_GAP)

Bases: QLayout

Lay widgets out left to right, wrapping to a new line when full.

A QHBoxLayout asks for every item's width at once, so a row of tags in a narrow dock widens the dock; this one grows taller instead.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Widget the layout is set on.

None

spacing

int

Gap in pixels between items, across and down; the pane gap by default.

PANE_GAP

Examples:

>>> flow = FXFlowLayout()
>>> for tag in ("comp", "lighting", "fx"):
...     flow.addWidget(QLabel(tag))

Methods:

Name Description
addItem

Keep item, in order.

count

Return how many items are laid out.

expandingDirections

Grow in neither direction: the width decides the height.

hasHeightForWidth

Say the height follows the width, as a wrap does.

heightForWidth

Return the height wrapping into width takes.

itemAt

Return the item at index, or None past the end.

minimumSize

Return the widest single item: nothing narrower can hold it.

setGeometry

Place every item inside rect, wrapping.

sizeHint

Return the minimum size: asking for more would widen the parent.

takeAt

Remove and return the item at index, or None past the end.

Methods:

addItem
addItem(item: QLayoutItem) -> None

Keep item, in order.

count
count() -> int

Return how many items are laid out.

expandingDirections
expandingDirections() -> Orientations

Grow in neither direction: the width decides the height.

hasHeightForWidth
hasHeightForWidth() -> bool

Say the height follows the width, as a wrap does.

heightForWidth
heightForWidth(width: int) -> int

Return the height wrapping into width takes.

itemAt
itemAt(index: int) -> Optional[QLayoutItem]

Return the item at index, or None past the end.

minimumSize
minimumSize() -> QSize

Return the widest single item: nothing narrower can hold it.

setGeometry
setGeometry(rect: QRect) -> None

Place every item inside rect, wrapping.

sizeHint
sizeHint() -> QSize

Return the minimum size: asking for more would widen the parent.

takeAt
takeAt(index: int) -> Optional[QLayoutItem]

Remove and return the item at index, or None past the end.

FXIconButton

FXIconButton(
    icon: str,
    parent: Optional[QWidget] = None,
    *,
    tip: str = "",
    checkable: bool = False,
    checked_icon: Optional[str] = None,
    size: Optional[int] = None
)

Bases: QToolButton

A round, flat icon button, filled with the accent when checked.

Parameters:

Name Type Description Default

icon

str

A material icon name.

required

parent

Optional[QWidget]

Parent widget.

None

tip

str

The tooltip, set through apply_tip.

''

checkable

bool

Whether a click toggles the button.

False

checked_icon

Optional[str]

The icon shown while checked. Defaults to icon.

None

size

Optional[int]

The circle's diameter, in logical pixels. Defaults to a push button's height.

None

Examples:

>>> eye = FXIconButton("visibility_off", bar, tip="Show to client",
...                    checkable=True, checked_icon="visibility")

FXIconLabel

FXIconLabel(
    icon: Optional[QIcon] = None,
    parent: Optional[QWidget] = None,
    size: int = 16,
)

Bases: QLabel

A label that draws a QIcon when painted, so it takes theme inks then.

A QLabel pixmap is baked once; an fxicons icon here follows every theme switch with no signal. Disabled draws the icon's Disabled mode.

Examples:

>>> label = FXIconLabel(size=18)
>>> fxicons.set_icon(label, "info", color="feedback_info_foreground")

Methods:

Name Description
icon

Return the icon drawn.

iconSize

Return the size the icon is drawn at.

minimumSizeHint

Return the size hint: the icon is not drawn smaller.

paintEvent

Draw the icon in the mode the enabled state asks for.

pixmap

Return the icon as drawn now, or the plain pixmap without one.

setIcon

Draw icon, or nothing for None or a null icon.

setIconSize

Draw the icon at size.

sizeHint

Return the icon size plus the margins.

Methods:

icon
icon() -> QIcon

Return the icon drawn.

iconSize
iconSize() -> QSize

Return the size the icon is drawn at.

minimumSizeHint
minimumSizeHint() -> QSize

Return the size hint: the icon is not drawn smaller.

paintEvent
paintEvent(event) -> None

Draw the icon in the mode the enabled state asks for.

pixmap
pixmap() -> QPixmap

Return the icon as drawn now, or the plain pixmap without one.

setIcon
setIcon(icon: Optional[QIcon]) -> None

Draw icon, or nothing for None or a null icon.

setIconSize
setIconSize(size: QSize) -> None

Draw the icon at size.

sizeHint
sizeHint() -> QSize

Return the icon size plus the margins.

FXIconLineEdit

FXIconLineEdit(
    parent: Optional[QWidget] = None,
    icon_name: Optional[str] = None,
    icon_position: str = "left",
)

Bases: QLineEdit

A line edit with an icon inside it, on the left or the right.

The icon is a QLineEdit.addAction action, so Qt places it and keeps it out of the Tab chain.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

The parent widget.

None

icon_name

Optional[str]

The icon to show; None for none.

None

icon_position

str

"left" or "right".

'left'

Raises:

Type Description
ValueError

If icon_position is neither.

FXJoinedGroup

FXJoinedGroup(parent: Optional[QWidget] = None)

Bases: QFrame

Widgets side by side in one button outline, with a divider between.

A child with keyboard focus lights the whole outline in the accent.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

Examples:

>>> group = FXJoinedGroup(composer)
>>> group.add_widget(status_combo)
>>> group.add_widget(FXPrimaryButton("Post", group))

Methods:

Name Description
add_widget

Append widget at the right end of the group.

event

Re-place the children when one is deleted or moved elsewhere.

eventFilter

Re-place the children when one is shown or hidden.

Methods:

add_widget
add_widget(widget: QWidget) -> None

Append widget at the right end of the group.

event
event(event: QEvent) -> bool

Re-place the children when one is deleted or moved elsewhere.

eventFilter
eventFilter(watched: QObject, event: QEvent) -> bool

Re-place the children when one is shown or hidden.

FXKeyboardTree

FXKeyboardTree(parent: Optional[QWidget] = None)

Bases: QTreeWidget

A tree whose rows a keyboard reaches as well as a mouse.

  • The Menu key and Shift+F10 emit customContextMenuRequested at the current row, so one handler builds every row menu.
  • Enter runs the primary act set with set_primary_act.
  • Typing goes to the field set with type_into, rather than Qt's keyboard search, which on a lazy tree finds only loaded rows.

Methods:

Name Description
keyPressEvent

Route the menu keys, Enter and typing, then let Qt have the rest.

open_current_menu

Ask for the current row's menu, as a right-click on it would.

set_primary_act

Run act on the current row on Enter; None gives Enter back.

type_into

Send what is typed on this tree to field.

Methods:

keyPressEvent
keyPressEvent(event: QKeyEvent) -> None

Route the menu keys, Enter and typing, then let Qt have the rest.

open_current_menu
open_current_menu() -> bool

Ask for the current row's menu, as a right-click on it would.

Returns:

Type Description
bool

Whether there was a current row to ask about.

set_primary_act
set_primary_act(act: Optional[Callable[[QTreeWidgetItem], None]]) -> None

Run act on the current row on Enter; None gives Enter back.

type_into
type_into(field: QLineEdit, qt_keys: str = TREE_KEYS) -> None

Send what is typed on this tree to field.

Parameters:

Name Type Description Default
field
QLineEdit

The filter field; focus moves there on the first key.

required
qt_keys
str

The characters that stay Qt's own tree commands.

TREE_KEYS

FXKeycap

FXKeycap(keys: str = '', parent: Optional[QWidget] = None)

Bases: QWidget

A keyboard shortcut drawn as keys, one cap per key.

Each cap is round at the button radius, and its look is a registered rule, so it follows every theme switch.

Examples:

>>> row.addWidget(FXKeycap("Ctrl+S"))

Methods:

Name Description
keys

Return the key sequence as it was given.

set_keys

Show keys, a Qt key sequence, as one cap per key.

Methods:

keys
keys() -> str

Return the key sequence as it was given.

set_keys
set_keys(keys: str) -> None

Show keys, a Qt key sequence, as one cap per key.

FXLettersUnderscoreValidator

FXLettersUnderscoreValidator(
    allow_numbers: bool = False, parent: Optional[QWidget] = None
)

Bases: QRegularExpressionValidator

Accept letters and underscores, and digits if allowed.

Parameters:

Name Type Description Default

allow_numbers

bool

If True, allows numbers in addition to letters and underscores.

False

parent

Optional[QWidget]

Parent widget.

None

Examples:

>>> from qtpy.QtWidgets import QLineEdit
>>> line_edit = QLineEdit()
>>> line_edit.setValidator(FXLettersUnderscoreValidator(allow_numbers=True))

FXLoadingOverlay

FXLoadingOverlay(
    parent: Optional[QWidget] = None,
    message: Optional[str] = None,
    dim: bool = True,
    block_input: bool = True,
    size: int = 48,
)

Bases: QWidget

A loading spinner centred over the parent widget.

By default the overlay dims the parent and takes its mouse, for a long operation the user must wait out. A view still usable while its rows load passes dim=False, block_input=False.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget to overlay.

None

message

Optional[str]

Optional message to display below the spinner.

None

dim

bool

Whether to darken the parent behind the spinner.

True

block_input

bool

Whether the overlay takes the parent's mouse.

True

size

int

The spinner's diameter in pixels.

48

Examples:

>>> overlay = FXLoadingOverlay(my_widget, "Loading assets...")
>>> overlay.show()
>>> # ... do some work ...
>>> overlay.hide()

Methods:

Name Description
eventFilter

Cover the parent again when it resizes.

hideEvent

Stop the spinner.

paintEvent

Paint the semi-transparent background, if dimming.

showEvent

Cover the parent, come to the front and start the spinner.

Methods:

eventFilter
eventFilter(watched: QObject, event: QEvent) -> bool

Cover the parent again when it resizes.

hideEvent
hideEvent(event) -> None

Stop the spinner.

paintEvent
paintEvent(event) -> None

Paint the semi-transparent background, if dimming.

showEvent
showEvent(event) -> None

Cover the parent, come to the front and start the spinner.

FXLoadingSpinner

FXLoadingSpinner(
    parent: Optional[QWidget] = None,
    size: Optional[int] = None,
    line_width: Optional[int] = None,
    color: str = "accent_primary",
)

Bases: QWidget

A quarter arc of the accent running round a muted ring.

The animation runs only while the spinner can be seen.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

size

Optional[int]

Size of the spinner in pixels. Defaults to a button's height.

None

line_width

Optional[int]

Width of the ring. Defaults to a tenth of size, 2 px at least.

None

color

str

The arc's color: a theme token name, followed through a switch, or a colour. Defaults to accent_primary; the ring is border_light.

'accent_primary'

Examples:

>>> spinner = FXLoadingSpinner(size=32)
>>> spinner.start()
>>> # ... do some work ...
>>> spinner.stop()

Methods:

Name Description
hideEvent

Pause the animation while nothing can see it.

is_spinning

Return whether the spinner is started.

paintEvent

Paint the muted ring, then the arc over it.

set_color

Set the arc's color: a theme token name or a colour.

showEvent

Resume the animation a hide paused.

start

Start the animation, and show the spinner if it has a parent.

stop

Stop the animation.

Methods:

hideEvent
hideEvent(event) -> None

Pause the animation while nothing can see it.

is_spinning
is_spinning() -> bool

Return whether the spinner is started.

paintEvent
paintEvent(event) -> None

Paint the muted ring, then the arc over it.

set_color
set_color(color: str) -> None

Set the arc's color: a theme token name or a colour.

showEvent
showEvent(event) -> None

Resume the animation a hide paused.

start
start() -> None

Start the animation, and show the spinner if it has a parent.

stop
stop() -> None

Stop the animation.

FXLowerCaseValidator

FXLowerCaseValidator(
    allow_numbers: bool = False,
    allow_underscores: bool = False,
    parent: Optional[QWidget] = None,
)

Bases: QRegularExpressionValidator

Lowercase typed letters; accept digits or underscores if allowed.

Parameters:

Name Type Description Default

allow_numbers

bool

If True, allows numbers in addition to lowercase letters.

False

allow_underscores

bool

If True, allows underscores in addition to lowercase letters.

False

parent

Optional[QWidget]

Parent widget.

None

Examples:

>>> from qtpy.QtWidgets import QLineEdit
>>> line_edit = QLineEdit()
>>> line_edit.setValidator(FXLowerCaseValidator(allow_numbers=True))

Methods:

Name Description
validate

Lowercase the input, then check it against the pattern.

Methods:

validate
validate(input_string: str, pos: int)

Lowercase the input, then check it against the pattern.

FXMainWindow

FXMainWindow(
    parent: Optional[QWidget] = None,
    icon: Optional[Union[str, QIcon]] = None,
    title: Optional[str] = None,
    size: Optional[Tuple[int, int]] = None,
    documentation: Optional[str] = None,
    project: Optional[str] = None,
    version: Optional[str] = None,
    company: Optional[str] = None,
    ui_file: Optional[str] = None,
    fit_to_contents: bool = False,
    framed: bool = False,
)

Bases: QMainWindow

Customized QMainWindow class.

The window's icon and name sit at the menu bar's right end, in title_corner; set_banner_text and set_banner_icon change them. The project, version and company live on the status bar's items, which the About dialog reads.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget. Defaults to None.

None

icon

Optional[Union[str, QIcon]]

The window's icon: a path to an image, or a QIcon. With neither, an icon already set on the running QApplication is left in place and fxgui's own logo is used only if there is none. Defaults to None.

None

title

Optional[str]

Title of the window, and the name in the menu bar corner. Defaults to None.

None

size

Optional[Tuple[int, int]]

Window size as width and height. Defaults to 500 x 600.

None

documentation

Optional[str]

URL the Help menu's Documentation opens; the entry is disabled without a valid one. Defaults to None.

None

project

Optional[str]

The status bar's project. Defaults to None, hidden.

None

version

Optional[str]

The status bar's version. Defaults to None, hidden.

None

company

Optional[str]

The status bar's company. Defaults to None, hidden.

None

ui_file

Optional[str]

A Designer file loaded as the central widget, kept as ui. Defaults to None.

None

fit_to_contents

bool

Whether to grow to the layout's own sizeHint on first show, grow-only and bounded by the screen. Defaults to False.

False

framed

bool

Whether to draw the window as a frame around its panes. The menu bar, toolbars, status bar and the window behind the central widget paint the theme's frame color with no lines between them, even for bars set later. Icon-only push buttons on those bands go flat (fxRole="flat") unless they carry a role already. Mark bands of your own with fxstyle.mark_as_frame. Defaults to False.

False

Attributes:

Name Type Description
title_corner QWidget

The widget at the menu bar's right end holding banner_icon and banner_label.

main_menu, window_menu, theme_menu, help_menu (QMenu

fxgui's menus on the current menu bar, or None with none.

refresh_action QAction

Ctrl+Alt+R, on no menu; an application adds it where its refresh belongs.

Methods:

Name Description
add_corner_widget

Add widget to the menu bar corner, left of the icon and name.

center_on_screen

Center the window on the primary screen's available area.

documentation

Return the URL Help > Documentation opens, or None.

event

Route status tips after the items; watch a framed window's bands.

eventFilter

Fit the corner to the bar, re-place it, and flatten framed bands.

setMenuBar

Set the menu bar; it gets fxgui's menus, the corner and the frame.

setStatusBar

Set the status bar; a framed window paints it in the frame.

setWindowTitle

Set the window title; None or empty reads "Window".

set_banner_icon

Set the icon in the menu bar corner.

set_banner_text

Set the name in the menu bar corner.

set_documentation

Set the URL Help > Documentation opens; no valid URL disables it.

showEvent

Grow once to the layout's own size, if this window asked to.

toggle_theme

Switch every fxgui window to the next available theme.

Attributes

help_menu property
help_menu: Optional[QMenu]

The Help menu on the current menu bar.

main_menu property
main_menu: Optional[QMenu]

The File menu on the current menu bar.

theme_menu property
theme_menu: Optional[QMenu]

The Window menu's Theme submenu.

window_menu property
window_menu: Optional[QMenu]

The Window menu on the current menu bar.

Methods:

add_corner_widget
add_corner_widget(widget: QWidget) -> None

Add widget to the menu bar corner, left of the icon and name.

The corner is placed again whenever widget grows or shrinks.

center_on_screen
center_on_screen() -> None

Center the window on the primary screen's available area.

Examples:

>>> window = FXMainWindow()
>>> window.resize(800, 600)
>>> window.center_on_screen()
>>> window.show()
documentation
documentation() -> Optional[str]

Return the URL Help > Documentation opens, or None.

event
event(event: QEvent) -> bool

Route status tips after the items; watch a framed window's bands.

eventFilter
eventFilter(watched: QObject, event: QEvent) -> bool

Fit the corner to the bar, re-place it, and flatten framed bands.

setMenuBar
setMenuBar(menu_bar: Optional[QMenuBar]) -> None

Set the menu bar; it gets fxgui's menus, the corner and the frame.

None removes the bar and fxgui's menus with it; the corner waits for the next bar.

setStatusBar
setStatusBar(status_bar: Optional[QStatusBar]) -> None

Set the status bar; a framed window paints it in the frame.

setWindowTitle
setWindowTitle(title: str) -> None

Set the window title; None or empty reads "Window".

set_banner_icon
set_banner_icon(
    icon: Optional[Union[QIcon, str]], size: Optional[int] = None
) -> None

Set the icon in the menu bar corner.

Parameters:

Name Type Description Default
icon
Optional[Union[QIcon, str]]

A QIcon, or an icon name, which follows theme switches.

required
size
Optional[int]

The size of the icon. Defaults to 16.

None
set_banner_text
set_banner_text(text: str) -> None

Set the name in the menu bar corner.

set_documentation
set_documentation(url: Optional[str]) -> None

Set the URL Help > Documentation opens; no valid URL disables it.

showEvent
showEvent(event) -> None

Grow once to the layout's own size, if this window asked to.

Grow-only, so a larger requested size stays, and once, so a window dragged smaller is not pushed back out. Bounded by the screen the window is on.

toggle_theme
toggle_theme() -> str

Switch every fxgui window to the next available theme.

Returns:

Name Type Description
str str

The new theme that was applied.

Examples:

>>> window = FXMainWindow()
>>> window.show()
>>> new_theme = window.toggle_theme()
>>> print(f"Switched to {new_theme} theme")

FXMentionEdit

FXMentionEdit(
    parent: Optional[QWidget] = None, lines: int = 3, closes: bool = False
)

Bases: QPlainTextEdit

A text box that offers people by name after an @.

A chosen person is written as @<their name>; mentions answers who the text still names. Two people of one name are offered with their ids. Ctrl+Enter emits submitted, Escape cancelled.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

lines

int

How many lines tall the box is.

3

closes

bool

Whether Escape closes the box, so it takes Escape before any window shortcut does.

False
Signals

submitted: Ctrl+Enter was pressed. cancelled: Escape was pressed with no name list open.

Examples:

>>> box = FXMentionEdit(card)
>>> box.set_people({"anne.martin": "Anne Martin"})
>>> box.submitted.connect(lambda: post(box.toPlainText()))

Methods:

Name Description
changeEvent

Hold the lines again in the font and frame a sheet hands it.

event

Claim Escape from window shortcuts when the box closes on it.

insert_mention

Write person as @<name>, replacing an @ being typed.

kept

Return the text and who it names, for restore to put back.

keyPressEvent

Submit on Ctrl+Enter; an open name list takes Enter and Escape.

mentions

Return the ids the text still names, in the order chosen.

reset

Empty the box and forget who was named.

restore

Put back what kept returned, the cursor at its end.

set_people

Offer people, as id to the name shown.

Methods:

changeEvent
changeEvent(event: QEvent) -> None

Hold the lines again in the font and frame a sheet hands it.

event
event(event: QEvent) -> bool

Claim Escape from window shortcuts when the box closes on it.

insert_mention
insert_mention(person: str) -> None

Write person as @<name>, replacing an @ being typed.

kept
kept() -> Tuple[str, Dict[str, str]]

Return the text and who it names, for restore to put back.

keyPressEvent
keyPressEvent(event) -> None

Submit on Ctrl+Enter; an open name list takes Enter and Escape.

mentions
mentions() -> Tuple[str, ...]

Return the ids the text still names, in the order chosen.

reset
reset() -> None

Empty the box and forget who was named.

restore
restore(text: str, chosen: Mapping[str, str]) -> None

Put back what kept returned, the cursor at its end.

set_people
set_people(people: Mapping[str, str]) -> None

Offer people, as id to the name shown.

FXNotificationBanner

FXNotificationBanner(
    parent: Optional[QWidget] = None,
    message: str = "",
    severity_type: Optional[int] = None,
    timeout: Optional[int] = None,
    actions: Optional[Mapping[str, Callable[[], None]]] = None,
    closable: bool = True,
    width: int = 320,
    logger: Optional[Logger] = None,
    title: Optional[str] = None,
    icon: Optional[str] = None,
    margin: int = 16,
    top: Optional[int] = None,
    spacing: int = PANE_GAP,
)

Bases: QFrame

A notification card that slides in at the parent's top right.

Cards on one parent stack, and close up when one is dismissed.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

The widget the card sits on; it positions the card.

None

message

str

The notification message, rich text.

''

severity_type

Optional[int]

CRITICAL, ERROR, WARNING, SUCCESS, INFO or DEBUG; None for a plain card with title and icon.

None

timeout

Optional[int]

Milliseconds before it dismisses itself; 0 never. Defaults to 5000, and to 0 for ERROR and CRITICAL: an error waits for the artist to read it.

None

actions

Optional[Mapping[str, Callable[[], None]]]

Buttons as {label: callback}, left to right, the first styled primary. A card with actions never times out; a click runs the callback, then dismisses the card.

None

closable

bool

Whether to show a close button.

True

width

int

The card's fixed width.

320

logger

Optional[Logger]

Logs the message when shown, at the severity's level.

None

title

Optional[str]

Replaces the severity's title.

None

icon

Optional[str]

An icon name replacing the severity's icon.

None

margin

int

From the parent's right edge.

16

top

Optional[int]

From the parent's top to the first banner. Defaults to margin.

None

spacing

int

Between stacked notifications; the pane gap.

PANE_GAP
Signals

closed: Emitted when the banner is closed.

Examples:

>>> # Simple notification - auto-positions and stacks
>>> banner = FXNotificationBanner(
...     parent=window,
...     message="File saved successfully!",
...     severity_type=SUCCESS,
... )
>>> banner.show()
>>>
>>> # Custom notification
>>> banner = FXNotificationBanner(
...     parent=window,
...     message="New version available!",
...     title="Update",
...     icon="system_update",
... )
>>> banner.show()
>>>
>>> # Interactive notification - waits for the artist to answer
>>> banner = FXNotificationBanner(
...     parent=window,
...     message="Publish failed on 3 shots.",
...     severity_type=ERROR,
...     actions={"Retry": retry_publish, "Open log": open_log},
... )
>>> banner.show()

Methods:

Name Description
add_action

Add an action button to the banner.

dismiss

Dismiss the notification with slide-out animation to the right.

eventFilter

Keep the banner at the parent's right edge as it resizes.

message

Return the message the banner says.

set_message

Show message, refitting the card and the stack.

set_timeout

Set the timeout in ms, 0 for none; a shown card counts from now.

set_top

Set the first banner's distance from the parent's top.

show

Show the notification with slide-in animation from the right.

Methods:

add_action
add_action(
    text: str, callback: Optional[Callable[[], None]] = None
) -> QPushButton

Add an action button to the banner.

A banner with an action never times out. Clicking one runs its callback, then dismisses the banner.

Returns:

Name Type Description
QPushButton QPushButton

The button.

Examples:

>>> banner.add_action("Retry", retry_publish)
dismiss
dismiss() -> None

Dismiss the notification with slide-out animation to the right.

eventFilter
eventFilter(obj, event) -> bool

Keep the banner at the parent's right edge as it resizes.

message
message() -> str

Return the message the banner says.

set_message
set_message(message: str) -> None

Show message, refitting the card and the stack.

set_timeout
set_timeout(timeout: int) -> None

Set the timeout in ms, 0 for none; a shown card counts from now.

set_top
set_top(top: int) -> None

Set the first banner's distance from the parent's top.

show
show(unique: bool = False) -> bool

Show the notification with slide-in animation from the right.

Automatically calculates position based on other active notifications for the same parent widget, stacking them vertically with spacing.

Parameters:

Name Type Description Default
unique
bool

If a banner on the same parent already says this message, show nothing and delete this one.

False

Returns:

Name Type Description
bool bool

Whether the banner was shown.

FXOutputLogHandler

FXOutputLogHandler(log_widget: FXOutputLogWidget)

Bases: Handler

Logging handler that sends records to an output log widget.

The widget is held weakly: once it is deleted the handler removes itself from every logger instead of raising on each record.

Parameters:

Name Type Description Default

log_widget

FXOutputLogWidget

The FXOutputLogWidget to send messages to.

required

Methods:

Name Description
detach

Remove this handler from the root logger and every named logger.

emit

Send a record to the widget, or detach if the widget is gone.

Attributes:

Name Type Description
log_widget Optional[FXOutputLogWidget]

The widget records go to, or None once it is gone.

Attributes

log_widget property

The widget records go to, or None once it is gone.

Methods:

detach
detach(*_args) -> None

Remove this handler from the root logger and every named logger.

emit
emit(record: LogRecord) -> None

Send a record to the widget, or detach if the widget is gone.

FXOutputLogWidget

FXOutputLogWidget(
    parent: Optional[QWidget] = None,
    max_blocks: int = 0,
    hang_indent: Optional[Union[str, Pattern]] = None,
)

Bases: QWidget

A read-only log pane with ANSI colours, search and a throttle.

Records reach it through an FXOutputLogHandler added to a logger, or through append_log and append_many.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

max_blocks

int

How many lines the pane keeps before Qt prunes the oldest, as a terminal's scrollback does. Defaults to 0, no limit: only the consumer knows whether dropping old records is safe.

0

hang_indent

Optional[Union[str, Pattern]]

A regular expression matching a record's header, such as its time, level and logger name. A wrapped record's later lines then start under the end of the match, not at column 0. Nothing is added to the text, so a copy gives the original.

None
Signals

log_message: Emitted with a message and its level when a record is received (for thread-safe delivery).

Examples:

>>> import logging
>>> from fxgui import fxwidgets
>>> log_widget = fxwidgets.FXOutputLogWidget()
>>> logging.root.addHandler(fxwidgets.FXOutputLogHandler(log_widget))

Methods:

Name Description
append_log

Queue text for the pane; every record queued is shown.

append_many

Queue lines in order, behind whatever is already queued.

clear_log

Clear the log output.

eventFilter

Send Shift+Enter in the search field to the previous match.

keyPressEvent

Open search on Ctrl+F; close it on Escape.

show_all_levels

Show every line again, as Show all does.

show_levels

Show only records from minimum up to, not including, below.

show_search

Show the search bar and put the cursor in it.

Methods:

append_log
append_log(text: str, level: int = NOTSET) -> None

Queue text for the pane; every record queued is shown.

The first record of a burst is written at once, the rest on the throttle's ticks.

Parameters:

Name Type Description Default
text
str

Text to append (may contain ANSI color codes).

required
level
int

The record's logging level, which show_levels reads.

NOTSET
append_many
append_many(lines: Sequence[str]) -> None

Queue lines in order, behind whatever is already queued.

For a history written elsewhere: one call, and the throttle writes them in as few repaints as it can.

Parameters:

Name Type Description Default
lines
Sequence[str]

Each without its own newline; may carry ANSI codes.

required
clear_log
clear_log() -> None

Clear the log output.

eventFilter
eventFilter(watched: QObject, event: QEvent) -> bool

Send Shift+Enter in the search field to the previous match.

keyPressEvent
keyPressEvent(event: QKeyEvent) -> None

Open search on Ctrl+F; close it on Escape.

show_all_levels
show_all_levels() -> None

Show every line again, as Show all does.

show_levels
show_levels(minimum: int = NOTSET, below: Optional[int] = None) -> None

Show only records from minimum up to, not including, below.

The defaults show every line. While filtered, a bar under the log names the filter and offers Show all, and lines appended without a level stay hidden.

show_search() -> None

Show the search bar and put the cursor in it.

FXPasswordLineEdit

FXPasswordLineEdit(
    parent: Optional[QWidget] = None, icon_position: str = "right"
)

Bases: FXIconLineEdit

A password field whose eye icon shows or hides what was typed.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

The parent widget.

None

icon_position

str

"left" or "right".

'right'

FXPrimaryButton

FXPrimaryButton(
    text: Union[str, QWidget, None] = "",
    parent: Optional[QWidget] = None,
    *,
    icon: Optional[str] = None
)

Bases: QPushButton

The main action of a form, drawn on the theme's accent.

The look lives in the theme stylesheet under QPushButton[fxRole="primary"], so any QPushButton given that property matches it too.

Parameters:

Name Type Description Default

text

Union[str, QWidget, None]

The button's label, or its parent as with QPushButton.

''

parent

Optional[QWidget]

Parent widget.

None

icon

Optional[str]

A material icon name, drawn in the on-accent icon colour.

None

Examples:

>>> post = FXPrimaryButton("Post", form, icon="send")

Methods:

Name Description
enterEvent

Draw the icon in the hover fill's ink.

leaveEvent

Draw the icon in the resting fill's ink.

set_icon_name

Draw the material icon icon in the on-accent icon colour.

Methods:

enterEvent
enterEvent(event) -> None

Draw the icon in the hover fill's ink.

leaveEvent
leaveEvent(event) -> None

Draw the icon in the resting fill's ink.

set_icon_name
set_icon_name(icon: str) -> None

Draw the material icon icon in the on-accent icon colour.

FXProgressCard

FXProgressCard(
    parent: Optional[QWidget] = None,
    title: str = "Task",
    description: Optional[str] = None,
    progress: int = 0,
    status: Optional[int] = None,
    show_percentage: bool = True,
    icon: Optional[str] = None,
)

Bases: QFrame

A card showing a task's progress: a title, a bar, a status icon.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

title

str

Card title.

'Task'

description

Optional[str]

Optional description text.

None

progress

int

Initial progress value (0-100).

0

status

Optional[int]

Status icon type (SUCCESS, ERROR, WARNING, INFO, etc.).

None

show_percentage

bool

Whether to show percentage text.

True

icon

Optional[str]

Optional icon name to display next to the title.

None
Signals

progress_changed: Emitted when progress changes. completed: Emitted when progress reaches 100%.

Examples:

>>> card = FXProgressCard(
...     title="Rendering",
...     description="Frame 50/100",
...     progress=50
... )
>>> card.set_progress(75)

Methods:

Name Description
set_description

Set the description; empty hides it.

set_progress

Show value, held to 0-100; say completed at 100.

set_status

Show severity status's icon, or none for None.

set_title

Set the card title.

Methods:

set_description
set_description(description: str) -> None

Set the description; empty hides it.

set_progress
set_progress(value: int) -> None

Show value, held to 0-100; say completed at 100.

set_status
set_status(status: Optional[int]) -> None

Show severity status's icon, or none for None.

set_title
set_title(title: str) -> None

Set the card title.

FXPygmentsHighlighter

FXPygmentsHighlighter(document: QTextDocument, language: str = 'python')

Bases: QSyntaxHighlighter

Syntax highlighter using Pygments for multi-language support.

The whole document is lexed once per change; each block then takes its slice of the tokens, and records the token type at its end as its state so Qt carries a change (an opened string) to the blocks below.

Parameters:

Name Type Description Default

document

QTextDocument

The QTextDocument to highlight.

required

language

str

The programming language name (e.g., "python", "javascript").

'python'
Example

highlighter = FXPygmentsHighlighter(text_edit.document(), "python")

Methods:

Name Description
highlightBlock

Apply the document's tokens that fall inside this block.

language

Return the language highlighted, "text" for an unknown one.

refresh_formats

Rebuild the formats for the current theme and rehighlight.

set_language

Highlight language from now on, plain text if unknown.

Methods:

highlightBlock
highlightBlock(text: str) -> None

Apply the document's tokens that fall inside this block.

language
language() -> str

Return the language highlighted, "text" for an unknown one.

refresh_formats
refresh_formats(_theme_name: Optional[str] = None) -> None

Rebuild the formats for the current theme and rehighlight.

set_language
set_language(language: str) -> None

Highlight language from now on, plain text if unknown.

FXRangeSlider

FXRangeSlider(
    parent: Optional[QWidget] = None,
    minimum: int = 0,
    maximum: int = 100,
    low: Optional[int] = None,
    high: Optional[int] = None,
    show_values: bool = True,
)

Bases: QWidget

A slider with two handles for a low and a high value.

Arrows move the active handle, Page keys a tenth of the range, Space switches handle.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

minimum

int

Minimum value of the range.

0

maximum

int

Maximum value of the range.

100

low

Optional[int]

Initial low value.

None

high

Optional[int]

Initial high value.

None

show_values

bool

Whether to show value labels.

True
Signals

range_changed: Emitted when either handle changes (low, high). low_changed: Emitted when the low value changes. high_changed: Emitted when the high value changes.

Examples:

>>> slider = FXRangeSlider(minimum=0, maximum=100)
>>> slider.range_changed.connect(lambda l, h: print(f"Range: {l}-{h}"))
>>> slider.set_values(25, 75)

Methods:

Name Description
high

Return the high value.

keyPressEvent

Adjust the active handle from the keyboard.

leaveEvent

Handle mouse leave.

low

Return the low value.

minimumSizeHint

Return the minimum size.

mouseMoveEvent

Handle mouse move.

mousePressEvent

Handle mouse press.

mouseReleaseEvent

Handle mouse release.

paintEvent

Paint the groove, the span between the handles, and the values.

set_high

Set the high value, held between the low value and the maximum.

set_low

Set the low value, held between the minimum and the high value.

set_maximum

Set the maximum value; the minimum and the handles follow it.

set_minimum

Set the minimum value; the maximum and the handles follow it.

set_values

Set both values, clamped; signal only what moved.

sizeHint

Return the preferred size.

Methods:

high
high() -> int

Return the high value.

keyPressEvent
keyPressEvent(event: QKeyEvent) -> None

Adjust the active handle from the keyboard.

Left/Down and Right/Up move the active handle by 1, PageUp/PageDown by 10% of the range, Home/End jump it to the extremes, and Space switches between the low and high handle.

leaveEvent
leaveEvent(event) -> None

Handle mouse leave.

low
low() -> int

Return the low value.

minimumSizeHint
minimumSizeHint()

Return the minimum size.

mouseMoveEvent
mouseMoveEvent(event: QMouseEvent) -> None

Handle mouse move.

mousePressEvent
mousePressEvent(event: QMouseEvent) -> None

Handle mouse press.

mouseReleaseEvent
mouseReleaseEvent(event: QMouseEvent) -> None

Handle mouse release.

paintEvent
paintEvent(event) -> None

Paint the groove, the span between the handles, and the values.

set_high
set_high(value: int) -> None

Set the high value, held between the low value and the maximum.

set_low
set_low(value: int) -> None

Set the low value, held between the minimum and the high value.

set_maximum
set_maximum(maximum: int) -> None

Set the maximum value; the minimum and the handles follow it.

set_minimum
set_minimum(minimum: int) -> None

Set the minimum value; the maximum and the handles follow it.

set_values
set_values(low: int, high: int) -> None

Set both values, clamped; signal only what moved.

sizeHint
sizeHint()

Return the preferred size.

FXRatingWidget

FXRatingWidget(
    parent: Optional[QWidget] = None,
    max_rating: int = 5,
    initial_rating: float = 0,
    allow_half: bool = False,
    icon_size: int = 20,
    filled_icon: str = "star",
    empty_icon: str = "star_border",
    half_icon: str = "star_half",
)

Bases: QWidget

A row of stars to click, with a preview under the pointer.

Arrows step the rating, digits set it, Home and End jump, Delete clears.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

max_rating

int

Maximum number of stars.

5

initial_rating

float

Initial rating value.

0

allow_half

bool

Whether to allow half-star ratings.

False

icon_size

int

Size of star icons in pixels.

20

filled_icon

str

Icon name for filled stars.

'star'

empty_icon

str

Icon name for empty stars.

'star_border'

half_icon

str

Icon name for half-filled stars.

'star_half'
Signals

rating_changed: Emitted when the rating changes.

Examples:

>>> rating = FXRatingWidget(max_rating=5, initial_rating=3)
>>> rating.rating_changed.connect(lambda r: print(f"Rating: {r}"))

Methods:

Name Description
clear_rating

Clear the rating (set to 0).

keyPressEvent

Adjust the rating from the keyboard.

leaveEvent

Drop the hover preview.

mouseMoveEvent

Preview the rating under the pointer.

mousePressEvent

Handle mouse click to set rating.

paintEvent

Paint a focus indicator under the star labels when focused.

rating

Return the current rating.

set_rating

Set the rating, clamped and rounded; emit says rating_changed.

Methods:

clear_rating
clear_rating() -> None

Clear the rating (set to 0).

keyPressEvent
keyPressEvent(event: QKeyEvent) -> None

Adjust the rating from the keyboard.

Left/Down decrease, Right/Up increase (by 0.5 when half stars are allowed), digit keys set the rating directly, Home/End jump to the extremes, and Delete/Backspace clear it.

leaveEvent
leaveEvent(event) -> None

Drop the hover preview.

mouseMoveEvent
mouseMoveEvent(event: QMouseEvent) -> None

Preview the rating under the pointer.

mousePressEvent
mousePressEvent(event: QMouseEvent) -> None

Handle mouse click to set rating.

paintEvent
paintEvent(event) -> None

Paint a focus indicator under the star labels when focused.

rating
rating() -> float

Return the current rating.

set_rating
set_rating(rating: float, emit: bool = True) -> None

Set the rating, clamped and rounded; emit says rating_changed.

FXResizedScrollArea

FXResizedScrollArea(
    parent: Optional[QWidget] = None,
    floor: Optional[int] = None,
    cap: Optional[int] = None,
)

Bases: QScrollArea

A scroll area that can fit its content.

Given a floor or a cap, its minimum height is its content's height, held between the two, and follows the content as rows come and go: the area grows with a short list and scrolls a long one. Qt loses the content's height a few layouts deep, so it is read here.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

floor

Optional[int]

The least height, in pixels, however short the content.

None

cap

Optional[int]

The most height the content may ask for; past it, it scrolls.

None

Examples:

>>> checks = FXResizedScrollArea(floor=60, cap=240)
>>> checks.setWidgetResizable(True)

Methods:

Name Description
minimumSizeHint

Return the content's height between floor and cap, if set.

viewportEvent

Tell the layout outside when the content's height changes.

Methods:

minimumSizeHint
minimumSizeHint() -> QSize

Return the content's height between floor and cap, if set.

viewportEvent
viewportEvent(event: QEvent) -> bool

Tell the layout outside when the content's height changes.

FXSearchBar

FXSearchBar(
    parent: Optional[QWidget] = None,
    placeholder: str = "Search...",
    debounce_ms: int = 300,
)

Bases: FXIconLineEdit

A line edit with a search icon, Qt's clear button and a debounce.

It is one Tab stop: the icon and the clear button are line edit actions, which take no focus.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

placeholder

str

Placeholder text.

'Search...'

debounce_ms

int

How long typing pauses before search_changed.

300
Signals

search_changed: The text, once typing pauses. search_submitted: The text, on Enter; cancels a pending change.

Examples:

>>> search = FXSearchBar(placeholder="Search assets...")
>>> search.search_changed.connect(lambda text: print(text))

FXSeating

FXSeating(panel: QWidget)

Seat a panel in the screen corner nearest its tray icon; slide it in.

The corner nearest the icon, else the pointer (the icon is in the overflow flyout), else the lower right; EDGE_GAP off both edges, as Windows seats its own flyouts. A panel not yet on screen rises into its seat while it fades up.

Parameters:

Name Type Description Default

panel

QWidget

The top-level widget to seat.

required

Examples:

>>> seating = FXSeating(panel)
>>> tray.activated.connect(
...     lambda _r: seating.show_at(tray.geometry(), QCursor.pos())
... )

Methods:

Name Description
anchor_point

Return the tray icon's middle, else cursor, else None.

center

Centre the panel on its screen and forget the anchor.

clamp

Return corner moved so a size rect sits gap inside screen.

popup_corner

Return where a panel of size puts its top-left, inside screen.

screen_for

Return the anchor's screen, else the panel's own.

seat

Move the panel against its last anchor at its real size.

show_at

Seat the panel against this anchor and bring it to the front.

stop

Abandon an entrance and leave the panel opaque; call on hide.

Methods:

anchor_point staticmethod
anchor_point(tray: QRect, cursor: Optional[QPoint]) -> Optional[QPoint]

Return the tray icon's middle, else cursor, else None.

center
center() -> None

Centre the panel on its screen and forget the anchor.

clamp staticmethod
clamp(corner: QPoint, size: QSize, screen: QRect, gap: int = 0) -> QPoint

Return corner moved so a size rect sits gap inside screen.

popup_corner classmethod
popup_corner(
    size: QSize, tray: QRect, cursor: Optional[QPoint], screen: QRect
) -> QPoint

Return where a panel of size puts its top-left, inside screen.

Parameters:

Name Type Description Default
size
QSize

The panel's real size; a never-shown panel's sizeHint is too small and spills off the corner.

required
tray
QRect

QSystemTrayIcon.geometry(), possibly empty.

required
cursor
Optional[QPoint]

The pointer for a clicked show, None for an automatic one.

required
screen
QRect

The target screen's availableGeometry().

required
screen_for
screen_for(tray: QRect, cursor: Optional[QPoint]) -> Optional[QScreen]

Return the anchor's screen, else the panel's own.

The anchor's, not the panel's: on two monitors the panel may be a screen away.

seat
seat() -> None

Move the panel against its last anchor at its real size.

Call from the panel's resizeEvent too. Does nothing before the first show_at.

show_at
show_at(tray: QRect, cursor: Optional[QPoint]) -> None

Seat the panel against this anchor and bring it to the front.

A panel not on screen slides in; one already up is only raised.

stop
stop() -> None

Abandon an entrance and leave the panel opaque; call on hide.

FXSingleInstance

FXSingleInstance(name: str, parent: Optional[QObject] = None)

Bases: QObject

A lock on a local socket name; a second start wakes the first.

Put the user in name so two accounts on one machine each get their own copy. QtNetwork is imported on claim, so a host without it can still import fxgui.

Parameters:

Name Type Description Default

name

str

The socket name to hold, such as f"my-app-{getuser()}".

required

parent

Optional[QObject]

Parent object.

None
Signals

woken: Another start asked for this copy; show the window.

Raises:

Type Description
RuntimeError

From claim, when no copy runs but the name cannot be listened on.

Examples:

>>> instance = FXSingleInstance(f"my-app-{getpass.getuser()}")
>>> if not instance.claim():
...     sys.exit(0)  # the running copy has been woken
>>> instance.woken.connect(window.show)

Methods:

Name Description
claim

Take the name, or wake the copy that holds it and return False.

Methods:

claim
claim() -> bool

Take the name, or wake the copy that holds it and return False.

FXSingleton

FXSingleton(*args, **kwargs)

Bases: type(QObject)

Metaclass for Qt classes that are singletons.

A call returns the live instance, shown and raised, or builds one when there is none or Qt has deleted it. Each subclass gets its own. A call that finds a live instance ignores its arguments, so a menu entry can call MyWindow(parent=host) every time; reset_instance first to build with new ones.

Examples:

>>> from fxgui import fxwidgets
>>>
>>> class MySingletonWindow(fxwidgets.FXMainWindow, metaclass=fxwidgets.FXSingleton):
...     pass
>>>
>>> window1 = MySingletonWindow()
>>> window2 = MySingletonWindow()
>>> assert window1 is window2  # Same instance

Methods:

Name Description
reset_instance

Forget the instance, so the next call builds a new one.

Methods:

reset_instance
reset_instance()

Forget the instance, so the next call builds a new one.

FXSortedTreeWidgetItem

Bases: QTreeWidgetItem

A row that sorts by its SORT_ROLE key, else naturally by its text.

Natural order puts "v9" before "v10". Keyed rows come before keyless ones, so mixing the two still gives one order. A key lives on its own role since Qt stores display and edit data together. Never super().__lt__(): it re-enters this override through Shiboken and recurses until segfault.

Methods:

Name Description
__lt__

Compare by the sort column's key, else by its natural text.

Methods:

__lt__
__lt__(other: QTreeWidgetItem) -> bool

Compare by the sort column's key, else by its natural text.

FXSplashScreen

FXSplashScreen(
    image_path: Optional[str] = None,
    icon: Optional[str] = None,
    title: Optional[str] = None,
    information: Optional[str] = None,
    show_progress_bar: bool = False,
    project: Optional[str] = None,
    version: Optional[str] = None,
    company: Optional[str] = None,
    fade_in: bool = False,
    overlay_opacity: float = 1.0,
    corner_radius: int = 0,
    border_width: int = 0,
    border_color: Optional[str] = None,
)

Bases: QSplashScreen

A splash screen: the image, a panel with the title, and a progress bar.

showMessage writes in the panel. A click hides it, as Qt's own does.

Parameters:

Name Type Description Default

image_path

Optional[str]

The image, cropped to 16:9. Defaults to fxgui's.

None

icon

Optional[str]

A path to the icon beside the title. Defaults to fxgui's.

None

title

Optional[str]

The title. Defaults to "Untitled".

None

information

Optional[str]

The text under the title. Defaults to "".

None

show_progress_bar

bool

Whether the progress bar shows before set_progress. Defaults to False.

False

project

Optional[str]

The copyright line's project. Defaults to None.

None

version

Optional[str]

The copyright line's version. Defaults to None.

None

company

Optional[str]

The copyright line's company. Defaults to None.

None

fade_in

bool

Whether to fade in over a second when shown. Defaults to False.

False

overlay_opacity

float

The panel's opacity, 0.0 to 1.0. Defaults to 1.0.

1.0

corner_radius

int

The corner radius, in pixels. Defaults to 0.

0

border_width

int

The border width, in pixels. Defaults to 0, none.

0

border_color

Optional[str]

The border color. Defaults to None, the theme's border_light.

None

Raises:

Type Description
ValueError

image_path is not an image Qt can read.

Methods:

Name Description
event

Handle an event, skipping Qt's wait in the Show event.

paintEvent

Draw the image clipped to the rounded corners.

set_progress

Show the progress bar at value out of max_range, drawn now.

showEvent

Fade in over a second, if asked to.

Methods:

event
event(event: QEvent) -> bool

Handle an event, skipping Qt's wait in the Show event.

paintEvent
paintEvent(event) -> None

Draw the image clipped to the rounded corners.

set_progress
set_progress(value: int, max_range: int = 100) -> None

Show the progress bar at value out of max_range, drawn now.

showEvent
showEvent(event) -> None

Fade in over a second, if asked to.

FXSplitButton

FXSplitButton(parent: Optional[QWidget] = None)

Bases: QToolButton

A split button whose click and dropdown both have keys.

A plain MenuButtonPopup answers only Space. Enter clicks it, and DROPDOWN_KEYS open the menu through popup, since showMenu runs an event loop of its own.

Methods:

Name Description
dropdown_hint

Return DROPDOWN_KEYS as the platform spells them, for a tip.

keyPressEvent

Click on Enter and open the menu on DROPDOWN_KEYS.

settle

Leave the button only what it still has to do.

sizeHint

Return Qt's width at a push button's height.

Methods:

dropdown_hint classmethod
dropdown_hint() -> str

Return DROPDOWN_KEYS as the platform spells them, for a tip.

keyPressEvent
keyPressEvent(event: QKeyEvent) -> None

Click on Enter and open the menu on DROPDOWN_KEYS.

settle
settle(click: bool) -> None

Leave the button only what it still has to do.

Parameters:

Name Type Description Default
click
bool

Whether a plain click still runs something. Without one a click opens the menu; without a menu the arrow goes; with neither the button hides.

required
sizeHint
sizeHint() -> QSize

Return Qt's width at a push button's height.

FXStatusBar

FXStatusBar(
    parent: Optional[QWidget] = None,
    project: Optional[str] = None,
    version: Optional[str] = None,
    company: Optional[str] = None,
)

Bases: QStatusBar

Customized QStatusBar class.

The accent line and the border under it are painted along the top, except on the frame (fxstyle.mark_as_frame) or after hide_status_line. add_item puts FXStatusItems on the left, before the message, which never hides them, or on the right, before the company. set_busy(True) runs a line along the same top band, framed or not, so waiting moves no layout.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget. Defaults to None.

None

project

Optional[str]

The project item's text. Defaults to None, hidden.

None

version

Optional[str]

The version item's text. Defaults to None, hidden.

None

company

Optional[str]

The company item's text. Defaults to None, hidden.

None

Attributes:

Name Type Description
icon_label QLabel

The icon label.

message_label QLabel

The message label.

project_label FXStatusItem

The project, plain until set_clickable(True).

version_label FXStatusItem

The version, likewise.

company_label FXStatusItem

The company, likewise.

Methods:

Name Description
add_item

Put item on the bar, after the items already on that side.

clearMessage

Clear the message and its tint.

event

Repaint when fxstyle.mark_as_frame marks or unmarks the bar.

ground

Return the colour the bar is painted now: a tint, or its own.

hideEvent

Stop the busy line's timer while nobody can see it.

hide_status_line

Hide the accent line and the border under it.

is_busy

Return whether the busy line runs.

items

Return every status item on the bar, shown or not.

paintEvent

Paint the bar, then its accent line or busy line along the top.

set_busy

Run the busy line along the top edge, or stop it.

set_status_line_colors

Paint the accent line as a gradient from color_a to color_b.

showEvent

Run the busy line again, if it ran when the bar hid.

showMessage

Display a message in the status bar with a specified severity.

show_status_line

Show the accent line and border, unless the bar is on the frame.

show_tip

Write a hover tip where messages go, after the items.

tint

Return the colour a message tints the bar now, or None.

Methods:

add_item
add_item(item: FXStatusItem, side: str = 'left') -> None

Put item on the bar, after the items already on that side.

Parameters:

Name Type Description Default
item
FXStatusItem

The item to add.

required
side
str

"left", before the message, or "right", before the company.

'left'

Raises:

Type Description
ValueError

side is neither "left" nor "right".

clearMessage
clearMessage()

Clear the message and its tint.

event
event(event: QEvent) -> bool

Repaint when fxstyle.mark_as_frame marks or unmarks the bar.

ground
ground() -> str

Return the colour the bar is painted now: a tint, or its own.

hideEvent
hideEvent(event) -> None

Stop the busy line's timer while nobody can see it.

hide_status_line
hide_status_line() -> None

Hide the accent line and the border under it.

is_busy
is_busy() -> bool

Return whether the busy line runs.

items
items() -> List[FXStatusItem]

Return every status item on the bar, shown or not.

paintEvent
paintEvent(event) -> None

Paint the bar, then its accent line or busy line along the top.

set_busy
set_busy(busy: bool) -> None

Run the busy line along the top edge, or stop it.

set_status_line_colors
set_status_line_colors(color_a: str, color_b: str) -> None

Paint the accent line as a gradient from color_a to color_b.

showEvent
showEvent(event) -> None

Run the busy line again, if it ran when the bar hid.

showMessage
showMessage(
    message: str,
    severity_type: int = INFO,
    duration: float = 2.5,
    time: bool = True,
    logger: Optional[Logger] = None,
    set_color: bool = True,
)

Display a message in the status bar with a specified severity.

Parameters:

Name Type Description Default
message
str

The message to be displayed.

required
severity_type
int

The severity level of the message. Should be one of CRITICAL, ERROR, WARNING, SUCCESS, INFO, or DEBUG. Defaults to INFO.

INFO
duration
float

The duration in seconds for which the message should be displayed. Defaults to2.5.

2.5
time
bool

Whether to display the current time before the message. Defaults to True.

True
logger
Logger

A logger object to log the message. Defaults to None.

None
set_color
bool

Whether to tint the bar in the severity's colors until the message goes. Defaults to True.

True

Examples:

To display a critical error message with a red background

>>> self.showMessage(
...     "Critical error occurred!",
...     severity_type=fxwidgets.CRITICAL,
...     duration=5,
...     logger=my_logger,
... )
show_status_line
show_status_line() -> None

Show the accent line and border, unless the bar is on the frame.

show_tip
show_tip(tip: str) -> None

Write a hover tip where messages go, after the items.

FXMainWindow routes Qt's status tips here; an empty tip gives a message still standing back.

tint
tint() -> Optional[str]

Return the colour a message tints the bar now, or None.

FXStatusDot

FXStatusDot(parent: Optional[QWidget] = None, diameter: int = 8)

Bases: QWidget

A filled circle in a feedback colour, or grey for no state.

Grey rather than a colour for off: every feedback colour is saturated, and a coloured dot reads as a state, not its absence.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

diameter

int

The circle's size in pixels.

8
Signals

clicked: A left-button release landed on the dot.

Examples:

>>> dot = FXStatusDot()
>>> dot.set_feedback("success", "Recording")

Methods:

Name Description
color

Return the colour the dot paints in now.

mouseReleaseEvent

Emit clicked on a left-button release.

paintEvent

Fill one antialiased circle, inset half a pixel so no edge is cut.

set_feedback

Show feedback key ("success", "warning", ...); None for off.

Methods:

color
color() -> QColor

Return the colour the dot paints in now.

mouseReleaseEvent
mouseReleaseEvent(event) -> None

Emit clicked on a left-button release.

paintEvent
paintEvent(event) -> None

Fill one antialiased circle, inset half a pixel so no edge is cut.

set_feedback
set_feedback(key: Optional[str], tooltip: str = '') -> None

Show feedback key ("success", "warning", ...); None for off.

An unknown key shows as off. Repaints only on a change, so a timer may call this constantly.

FXStatusItem

FXStatusItem(
    text: str = "",
    icon: Optional[str] = None,
    parent: Optional[QWidget] = None,
    clickable: bool = True,
)

Bases: QToolButton

An icon and a word on a status bar, flat, lit when it is clickable.

Painted against the bar as the bar is painted at that moment, a message's tint included, so its ink always reads. Hidden while it has no text.

Parameters:

Name Type Description Default

text

str

The word shown. Defaults to "".

''

icon

Optional[str]

An fxicons icon name. Defaults to None.

None

parent

Optional[QWidget]

Parent widget. Defaults to None.

None

clickable

bool

Whether a click does something; otherwise plain text that takes no mouse. Defaults to True.

True

Examples:

>>> item = FXStatusItem("3", "warning")
>>> window.statusBar().add_item(item)
>>> item.clicked.connect(show_log)

Methods:

Name Description
ground

Return the colour the item is drawn on now.

ink

Return the word's colour on the ground the item is drawn on now.

minimumSizeHint

Return sizeHint: an item is never squeezed.

paintEvent

Paint the hover fill, the icon and the word against the bar.

setText

Show text; an item with none hides.

set_clickable

Make a click do something, or make the item plain text.

set_tip

Say what the item is and what its click does.

show_state

Show text beside icon, muted or in a feedback tone.

sizeHint

Return the icon, the word and the side padding.

Methods:

ground
ground() -> str

Return the colour the item is drawn on now.

ink
ink() -> str

Return the word's colour on the ground the item is drawn on now.

minimumSizeHint
minimumSizeHint() -> QSize

Return sizeHint: an item is never squeezed.

paintEvent
paintEvent(event) -> None

Paint the hover fill, the icon and the word against the bar.

setText
setText(text: str) -> None

Show text; an item with none hides.

set_clickable
set_clickable(clickable: bool) -> None

Make a click do something, or make the item plain text.

set_tip
set_tip(title: str, body: str = '', keys: str = '') -> None

Say what the item is and what its click does.

show_state
show_state(text: str, icon: str, muted: bool = False, tone: str = '') -> None

Show text beside icon, muted or in a feedback tone.

Parameters:

Name Type Description Default
text
str

The word shown.

required
icon
str

An fxicons icon name.

required
muted
bool

Whether the word takes the muted ink.

False
tone
str

A feedback level ("error", "warning", ...) for the icon, or "" for the word's ink.

''
sizeHint
sizeHint() -> QSize

Return the icon, the word and the side padding.

FXSystemTray

FXSystemTray(
    parent: Optional[QObject] = None, icon: Optional[Union[str, QIcon]] = None
)

Bases: QSystemTrayIcon

A tray icon whose menu opens on a left click too, ending in Quit.

Parameters:

Name Type Description Default

parent

Optional[QObject]

The parent object. Defaults to None.

None

icon

Optional[Union[str, QIcon]]

The tray icon: a path to an image, or a QIcon. Defaults to fxgui's own logo.

None

Attributes:

Name Type Description
quit_action QAction

Quits an FXApplication; a DCC host keeps running.

Examples:

>>> app = FXApplication()
>>> tray = FXSystemTray()
>>> menu = tray.contextMenu()
>>> menu.insertAction(tray.quit_action, QAction("Set Project", menu))
>>> tray.show()
>>> app.exec()

Methods:

Name Description
quit

Quit the application, unless it is a host fxgui does not own.

Methods:

quit
quit() -> None

Quit the application, unless it is a host fxgui does not own.

FXTagChip

FXTagChip(text: str, parent: Optional[QWidget] = None, removable: bool = True)

Bases: QFrame

A single removable tag chip.

Parameters:

Name Type Description Default

text

str

The tag text.

required

parent

Optional[QWidget]

Parent widget.

None

removable

bool

Whether the chip can be removed.

True
Signals

removed: Emitted when the remove button is clicked.

Methods:

Name Description
text

Return the tag text.

Methods:

text
text() -> str

Return the tag text.

FXTagInput

FXTagInput(
    parent: Optional[QWidget] = None,
    placeholder: str = "Add tag and press Enter...",
    max_tags: int = 0,
    allow_duplicates: bool = False,
)

Bases: QWidget

A field whose Enter turns the text into a chip; a chip's x removes it.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

placeholder

str

Placeholder text for the input field.

'Add tag and press Enter...'

max_tags

int

Maximum number of tags allowed (0 = unlimited).

0

allow_duplicates

bool

Whether duplicate tags are allowed.

False
Signals

tags_changed: Emitted when tags are added or removed. tag_added: Emitted when a single tag is added. tag_removed: Emitted when a single tag is removed.

Examples:

>>> tag_input = FXTagInput(placeholder="Add tags...")
>>> tag_input.tags_changed.connect(lambda tags: print(f"Tags: {tags}"))
>>> tag_input.add_tag("python")
>>> tag_input.add_tag("qt")

Methods:

Name Description
add_tag

Add tag; return False for a blank, a duplicate or one too many.

clear_tags

Remove all tags.

remove_tag

Remove the first chip reading tag; return whether one did.

set_tags

Replace the tags, saying tags_changed once.

tags

Return the current tags, in order.

Methods:

add_tag
add_tag(tag: str) -> bool

Add tag; return False for a blank, a duplicate or one too many.

clear_tags
clear_tags() -> None

Remove all tags.

remove_tag
remove_tag(tag: str) -> bool

Remove the first chip reading tag; return whether one did.

set_tags
set_tags(tags: List[str]) -> None

Replace the tags, saying tags_changed once.

tags
tags() -> List[str]

Return the current tags, in order.

FXThreadLine

FXThreadLine(thread: QWidget)

Bases: QWidget

A line over a thread, from a comment's face into each reply's face.

Laid over the thread and blind to the mouse, so it crosses the cards' borders; it follows the thread's size and the faces' moves.

Parameters:

Name Type Description Default

thread

QWidget

The widget holding the comment and its replies.

required

Examples:

>>> line = FXThreadLine(thread)
>>> line.join(comment_avatar, [reply.avatar for reply in replies])

Methods:

Name Description
eventFilter

Follow the thread's size, and a face that moves or hides.

join

Draw the line from under head to each of faces shown.

paintEvent

Draw the line in the theme's border colour.

path

Return the line: down from the head, an elbow into each face.

Methods:

eventFilter
eventFilter(watched: QObject, event: QEvent) -> bool

Follow the thread's size, and a face that moves or hides.

join
join(head: QWidget, faces: Sequence[QWidget]) -> None

Draw the line from under head to each of faces shown.

paintEvent
paintEvent(event) -> None

Draw the line in the theme's border colour.

path
path() -> QPainterPath

Return the line: down from the head, an elbow into each face.

FXThumbnailDelegate

FXThumbnailDelegate(parent: Optional[QWidget] = None)

Bases: QStyledItemDelegate

Paint rows as a thumbnail, a title, a description and status marks.

Column 0 is laid out from both edges: the thumbnail (or the decoration icon) at the left, then the title and the description (Markdown, shown as plain text), and the status pill and dot anchored to the right edge with the child count badge under them. The text stops short of all three. A row with a Qt.BackgroundRole is drawn as a card.

Note

Item roles: - Qt.BackgroundRole (QColor, QBrush or token name): the card fill, rounded with a border_light edge. - Qt.DecorationRole (QIcon): the icon of a row without a thumbnail, or an overlay on the thumbnail. - THUMBNAIL_VISIBLE_ROLE (bool), THUMBNAIL_PATH_ROLE (str). - DESCRIPTION_ROLE (str, Markdown). - STATUS_DOT_COLOR_ROLE, STATUS_LABEL_COLOR_ROLE (QColor or token name), STATUS_LABEL_TEXT_ROLE (str). - STATUS_DOT_VISIBLE_ROLE, STATUS_LABEL_VISIBLE_ROLE, CHILD_COUNT_VISIBLE_ROLE (bool). - PICKER_TEXT_ROLE (str), PICKER_CHOICES_ROLE (Sequence[str]), PICKER_UNAVAILABLE_ROLE (Mapping[str, str], a listed choice that cannot be picked, to its reason).

A view that stamps roles of its own on the same items derives them from FIRST_FREE_ROLE.

Note

An element shows when its delegate flag (show_thumbnail, show_status_dot, show_status_label) is True and its per-item visible role is not False.

Note

The right-anchored marks walk left as column 0 narrows. apply_minimum_thumbnail_width(view) stops the column before they reach the thumbnail; sizeHint reports the same floor.

Examples:

>>> tree = QTreeWidget()
>>> tree.setItemDelegate(fxwidgets.FXThumbnailDelegate())
>>> item = QTreeWidgetItem(tree, ["My Item"])
>>> item.setData(0, FXThumbnailDelegate.THUMBNAIL_PATH_ROLE, path)
>>> item.setData(0, FXThumbnailDelegate.DESCRIPTION_ROLE, "**Bold**")
>>> item.setData(0, FXThumbnailDelegate.STATUS_DOT_COLOR_ROLE, "feedback_success_foreground")
>>> item.setData(0, Qt.BackgroundRole, "surface")

Methods:

Name Description
apply_minimum_thumbnail_width

Keep one column from being dragged below what its rows need.

apply_transparent_selection

Hand a view's row fill, selection and hover to the delegate.

editorEvent

Open a row's picker on a click inside its pill.

has_focus_ring

Whether the focus ring is drawn on this cell.

paint

Paint the cell: its fill or card, hover or selection, content, ring.

sizeHint

Return the row's size, measured with the item's own font.

Attributes:

Name Type Description
focus_ring str

Whether the ring outlines the current "row" or "cell".

Attributes

focus_ring property writable
focus_ring: str

Whether the ring outlines the current "row" or "cell".

Methods:

apply_minimum_thumbnail_width classmethod
apply_minimum_thumbnail_width(
    view: QWidget, column: int = 0, floor: int = 0
) -> None

Keep one column from being dragged below what its rows need.

The floor is the thumbnail's span plus the widest status marks the laid-out rows show. setMinimumSectionSize cannot serve: it applies to every section. A second call on the same column replaces the first.

Parameters:

Name Type Description Default
view
QWidget

The tree view whose header is guarded.

required
column
int

The column to guard.

0
floor
int

A width the column never goes below, even when empty.

0

Examples:

>>> tree.setItemDelegate(fxwidgets.FXThumbnailDelegate())
>>> fxwidgets.FXThumbnailDelegate.apply_minimum_thumbnail_width(
...     tree, floor=300
... )
apply_transparent_selection staticmethod
apply_transparent_selection(view: QWidget) -> None

Hand a view's row fill, selection and hover to the delegate.

Marks the view for the registered rule that clears Qt's own highlight, and installs a style that skips the native row panel and focus rect, which Windows 11 draws under the delegate's ring.

Parameters:

Name Type Description Default
view
QWidget

A view painted by FXThumbnailDelegate.

required
editorEvent
editorEvent(event, model, option, index) -> bool

Open a row's picker on a click inside its pill.

Everything else goes to the base class, which toggles the painted check box.

has_focus_ring
has_focus_ring(option: QStyleOptionViewItem, index: QModelIndex) -> bool

Whether the focus ring is drawn on this cell.

State_HasFocus is only set on the view's current cell, so the row is read from the view instead.

Returns:

Type Description
bool

True when focus came by keyboard and the cell sits in the

bool

current row, or is the current cell with focus_ring "cell".

paint
paint(
    painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex
) -> None

Paint the cell: its fill or card, hover or selection, content, ring.

sizeHint
sizeHint(option: QStyleOptionViewItem, index: QModelIndex) -> QSize

Return the row's size, measured with the item's own font.

FXTimelineSlider

FXTimelineSlider(
    parent: Optional[QWidget] = None,
    start_frame: int = 1,
    end_frame: int = 100,
    current_frame: Optional[int] = None,
    fps: float = 24,
    show_controls: bool = True,
    show_spinbox: bool = True,
    show_loop_controls: bool = False,
    show_keyframe_controls: bool = False,
    controls_position: str = "left",
    show_range: bool = True,
    show_fps: bool = True,
    own_clock: bool = True,
)

Bases: QWidget

A timeline/scrubber widget for DCC applications.

  • Keyframe markers and a current frame indicator, with optional playback controls.
  • Keys while the timeline has focus: Home, Left, Space, Right and End; I and O with the in/out controls.
  • Track zoom: the mouse wheel zooms around the cursor, a middle-mouse drag pans, reset_view() restores the full range.
  • Named marker layers (lines or a top strip) and named regions, mapped through the zoomed window. The widget assigns no meaning to a layer.
  • Optional in/out controls (show_loop_controls) that request marking the current frame; the consumer typically calls set_loop_region.
  • Optional keyframe navigation (show_keyframe_controls).
  • A hover line with the hovered frame number.
  • Narrow, the "below" layout drops the go-to-start and go-to-end buttons, then the frame field, so the transport keeps one row.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

start_frame

int

Start frame of the timeline.

1

end_frame

int

End frame of the timeline.

100

current_frame

Optional[int]

Initial current frame.

None

fps

float

Frames per second for playback; fractional rates such as 23.976 play at that rate.

24

show_controls

bool

Whether to show playback controls.

True

show_spinbox

bool

Whether to show the frame spinbox.

True

show_loop_controls

bool

Whether to show the mark-in/mark-out buttons.

False

show_keyframe_controls

bool

Whether to show the previous/next-keyframe navigation buttons.

False

controls_position

str

"left" (one row) or "below" (full-width track on top, the transport centred below, fps far left, consumer extras from add_control_widget() far right).

'left'

show_range

bool

Whether to show the start and end frame fields, and the view fields of the "below" layout; a player's range is fixed.

True

show_fps

bool

Whether to show the frame rate field.

True

own_clock

bool

Whether playback advances the frame. False for a consumer that keeps time itself, such as a movie: play and stop only switch the button and emit, the consumer moves the playhead with set_frame(frame, emit=False), and frame_changed then means the person moved it.

True

Raises:

Type Description
ValueError

controls_position is neither "left" nor "below".

Signals

frame_changed: Emitted when the current frame changes. playback_started: Emitted when playback starts. playback_stopped: Emitted when playback stops. view_changed: Emitted with (first, last) when the visible frame window changes (zoom, pan, or reset). in_point_requested: Mark-in pressed; carries the current frame. out_point_requested: Mark-out pressed; carries the current frame. loop_toggled: Emitted with the new loop playback state.

Examples:

>>> timeline = FXTimelineSlider(start_frame=1, end_frame=100)
>>> timeline.frame_changed.connect(lambda f: print(f"Frame: {f}"))
>>> timeline.add_keyframe(10)
>>> timeline.set_marker_frames(
...     "cached", {2, 3, 4}, "feedback_success_foreground", "strip")
>>> timeline.set_marker_frames("errors", {40, 41}, "#ef4444")
>>> timeline.set_loop_region(20, 60)

Methods:

Name Description
add_control_widget

Append a consumer widget to the right of the controls.

add_keyframe

Mark frame as a keyframe.

clear_keyframes

Remove all keyframe markers.

clear_region

Remove a named region (no-op if absent).

current_frame

Return the current frame.

fps

Return the playback frame rate.

frame_range

Return the frame range as (start, end).

go_to_end

Go to the end frame.

go_to_next_keyframe

Jump to the nearest keyframe after the current frame, if any.

go_to_previous_keyframe

Jump to the nearest keyframe before the current frame, if any.

go_to_start

Go to the start frame.

is_view_zoomed

Return whether the track shows a sub-window of the full range.

keyPressEvent

Run the transport key the buttons' tips name.

loop_playback

Return whether playback wraps to the start at the end.

next_frame

Advance to the next frame.

play

Start playback.

previous_frame

Go to the previous frame.

remove_keyframe

Unmark frame as a keyframe.

remove_markers

Remove a named marker layer (no-op if absent).

reset_view

Restore the track to the full frame range.

resizeEvent

Drop or restore the optional controls for the new width.

set_fps

Set the rate, held to 1-120; fractional rates such as 23.976 hold.

set_frame

Set the frame, clamped; emit says frame_changed.

set_loop_playback

Set whether playback wraps to the start at the end.

set_loop_region

Show the loop in/out range as the bracketed "loop" region.

set_marker_frames

Set (or replace) a named marker layer painted on the track.

set_range

Set the range from start to end, clamping the frame and view.

set_region

Set (or replace) a named frame region painted on the track.

set_view_range

Zoom the track to the [first, last] frame window.

stop

Stop playback.

toggle_playback

Toggle playback state.

track_rect

Return where the track draws its frames, in this widget's pixels.

view_range

Return the visible window as (first, last); the range unzoomed.

zoom_view

Zoom in notches wheel notches (out when negative) about a point.

Methods:

add_control_widget
add_control_widget(widget: QWidget) -> None

Append a consumer widget to the right of the controls.

add_keyframe
add_keyframe(frame: int) -> None

Mark frame as a keyframe.

clear_keyframes
clear_keyframes() -> None

Remove all keyframe markers.

clear_region
clear_region(name: str) -> None

Remove a named region (no-op if absent).

current_frame
current_frame() -> int

Return the current frame.

fps
fps() -> float

Return the playback frame rate.

frame_range
frame_range() -> Tuple[int, int]

Return the frame range as (start, end).

go_to_end
go_to_end() -> None

Go to the end frame.

go_to_next_keyframe
go_to_next_keyframe() -> None

Jump to the nearest keyframe after the current frame, if any.

go_to_previous_keyframe
go_to_previous_keyframe() -> None

Jump to the nearest keyframe before the current frame, if any.

go_to_start
go_to_start() -> None

Go to the start frame.

is_view_zoomed
is_view_zoomed() -> bool

Return whether the track shows a sub-window of the full range.

keyPressEvent
keyPressEvent(event: QKeyEvent) -> None

Run the transport key the buttons' tips name.

loop_playback
loop_playback() -> bool

Return whether playback wraps to the start at the end.

next_frame
next_frame() -> None

Advance to the next frame.

play
play() -> None

Start playback.

previous_frame
previous_frame() -> None

Go to the previous frame.

remove_keyframe
remove_keyframe(frame: int) -> None

Unmark frame as a keyframe.

remove_markers
remove_markers(name: str) -> None

Remove a named marker layer (no-op if absent).

reset_view
reset_view() -> None

Restore the track to the full frame range.

resizeEvent
resizeEvent(event) -> None

Drop or restore the optional controls for the new width.

set_fps
set_fps(fps: float) -> None

Set the rate, held to 1-120; fractional rates such as 23.976 hold.

set_frame
set_frame(frame: int, emit: bool = True) -> None

Set the frame, clamped; emit says frame_changed.

set_loop_playback
set_loop_playback(enabled: bool) -> None

Set whether playback wraps to the start at the end.

set_loop_region
set_loop_region(
    start: Optional[int], end: Optional[int], color: Optional[str] = None
) -> None

Show the loop in/out range as the bracketed "loop" region.

None for either end clears it.

set_marker_frames
set_marker_frames(
    name: str,
    frames: Iterable[int],
    color: Optional[str] = None,
    style: str = "line",
) -> None

Set (or replace) a named marker layer painted on the track.

Parameters:

Name Type Description Default
name
str

Layer identifier; setting the same name replaces it.

required
frames
Iterable[int]

Iterable of frame numbers. Empty removes the layer.

required
color
Optional[str]

A theme token such as "feedback_success_foreground", or any QColor value. Read when painted, so a token follows a theme switch; None is the accent.

None
style
str

"line" for 1px vertical lines at each frame, or "strip" for a translucent band along the top edge with a 1px solid top line over contiguous frame runs.

'line'

Raises:

Type Description
ValueError

style is neither "line" nor "strip".

set_range
set_range(start: int, end: int) -> None

Set the range from start to end, clamping the frame and view.

set_region
set_region(
    name: str,
    start: int,
    end: int,
    color: Optional[str] = None,
    bracket_edges: bool = False,
) -> None

Set (or replace) a named frame region painted on the track.

Parameters:

Name Type Description Default
name
str

Region identifier; setting the same name replaces it.

required
start
int

First frame of the region.

required
end
int

Last frame of the region.

required
color
Optional[str]

A theme token or any QColor value, read when painted; None is the accent.

None
bracket_edges
bool

Draw the edges as [ ] brackets, so a zero-width region still reads as a marker.

False
set_view_range
set_view_range(first: int, last: int) -> None

Zoom the track to the [first, last] frame window.

The window is clamped inside the full range; a window covering the full range (or more) resets the view.

stop
stop() -> None

Stop playback.

toggle_playback
toggle_playback() -> None

Toggle playback state.

track_rect
track_rect() -> QRect

Return where the track draws its frames, in this widget's pixels.

The left edge is the first frame of view_range(), the right edge the last, so another widget can line its own frames up with them.

view_range
view_range() -> Tuple[int, int]

Return the visible window as (first, last); the range unzoomed.

zoom_view
zoom_view(notches: float, about: float = 0.5) -> None

Zoom in notches wheel notches (out when negative) about a point.

Parameters:

Name Type Description Default
about
float

Where the zoom is anchored, as a share of the visible window from its first frame (0) to its last (1).

0.5

FXToggleSwitch

FXToggleSwitch(
    parent: Optional[QWidget] = None,
    on_color: Optional[str] = None,
    off_color: Optional[str] = None,
    thumb_color: Optional[str] = None,
)

Bases: QAbstractButton

An on/off switch that slides, as tall as a push button.

Its edge and thumb read at fxstyle.CONTROL_CONTRAST on every theme; hover, focus and disabled wear the push button's tokens.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

Parent widget.

None

on_color

Optional[str]

A theme token or a colour, when on. Defaults to the accent.

None

off_color

Optional[str]

A token or a colour, when off. Defaults to the sunken surface.

None

thumb_color

Optional[str]

A token or a colour for the thumb. Defaults to the muted text off and the on-accent text on.

None
Signals

toggled: Emitted when the switch state changes.

Examples:

>>> switch = FXToggleSwitch()
>>> switch.toggled.connect(lambda checked: print(f"Switch: {checked}"))
>>> switch.setChecked(True)

Methods:

Name Description
enterEvent

Repaint to show the hover state.

hitButton

Return True if pos is inside the clickable area.

leaveEvent

Repaint to hide the hover state.

minimumSizeHint

Return the minimum size of the switch.

paintEvent

Paint the track, its edge and the thumb.

position

Set the animation position and trigger repaint.

sizeHint

Return the preferred size of the switch.

track_rect

Return the track: the indicator size tall, centred in the widget.

Methods:

enterEvent
enterEvent(event) -> None

Repaint to show the hover state.

hitButton
hitButton(pos)

Return True if pos is inside the clickable area.

leaveEvent
leaveEvent(event) -> None

Repaint to hide the hover state.

minimumSizeHint
minimumSizeHint()

Return the minimum size of the switch.

paintEvent
paintEvent(event) -> None

Paint the track, its edge and the thumb.

position
position(value: float) -> None

Set the animation position and trigger repaint.

sizeHint
sizeHint()

Return the preferred size of the switch.

track_rect
track_rect() -> QRect

Return the track: the indicator size tall, centred in the widget.

FXValidatedLineEdit

FXValidatedLineEdit(
    parent: Optional[QWidget] = None,
    shake_amplitude: int = 4,
    shake_duration: int = 300,
    flash_duration: int = 400,
)

Bases: QLineEdit

A line edit that provides visual feedback when input is rejected.

When a validator rejects input (e.g., typing an invalid character), this widget shakes briefly and flashes a border in the theme's error colour. The flash is painted over the field, so the caller's own stylesheet and text margins are left as they were.

Parameters:

Name Type Description Default

parent

Optional[QWidget]

The parent widget.

None

shake_amplitude

int

Maximum horizontal displacement in pixels.

4

shake_duration

int

Total duration of shake animation in milliseconds.

300

flash_duration

int

Duration of red border flash in milliseconds.

400

Examples:

>>> from qtpy.QtWidgets import QLineEdit
>>> from fxgui.fxwidgets import FXValidatedLineEdit, FXCamelCaseValidator
>>> line_edit = FXValidatedLineEdit()
>>> line_edit.setValidator(FXCamelCaseValidator())
>>> line_edit.setPlaceholderText("camelCase only")

Methods:

Name Description
keyPressEvent

Shake when a typed character changed nothing: it was rejected.

paintEvent

Paint the field, then the rejection flash over its border.

Methods:

keyPressEvent
keyPressEvent(event: QKeyEvent) -> None

Shake when a typed character changed nothing: it was rejected.

paintEvent
paintEvent(event) -> None

Paint the field, then the rejection flash over its border.

Functions:

align_labels

align_labels(*forms: QFormLayout) -> None

Give the labels of every form in forms one right-aligned column.

Qt shares no label column across form layouts.

apply_tip

apply_tip(target, title: str, body: str = '', shortcut: str = '') -> None

Set a rich tooltip on target, plus a markup-free status tip.

The tooltip is rebuilt each time it shows, in the theme in force.

Parameters:

Name Type Description Default

target

A widget, an action, or an item already in its list, tree or table widget; a tree item gets the tip on every column.

required

title

str

What the control is, in a couple of words.

required

body

str

What the control does. Defaults to "".

''

shortcut

str

A Qt key sequence, such as "Ctrl+S". Defaults to "".

''

Raises:

Type Description
ValueError

target is an item not yet added to a view.

Examples:

>>> apply_tip(
...     button,
...     "Save",
...     "Write the scene to disk",
...     "Ctrl+S",
... )
Note

The status tip carries the same words without markup. Qt shows it in the window's status bar on hover, which is where a person looks for "what is this" before a tooltip has had time to appear. The title and body also become the accessible name and description; a later call replaces them, but never a name set by hand.

code_color

code_color(token: str) -> QColor

Return the colour code highlighting gives token in the current theme.

Parameters:

Name Type Description Default

token

str

A Pygments token name, such as "String", "Number" or "Name.Function"; one the style leaves uncoloured takes its parent's colour, else the theme's text colour.

required

Examples:

>>> code_color("String").isValid()
True

fix_wrapped_heights

fix_wrapped_heights(widget: QWidget) -> None

Give every word-wrapped label under widget the height its width needs.

Qt loses a label's height-for-width a few layouts deep and clips its last lines. Call after the labels have their width, and again from the holder's resizeEvent.

grab_screen_region

grab_screen_region(window: QWidget) -> Optional[QPixmap]

Let the user drag out a region of window's screen; None on Escape.

window is hidden for the grab and shown again afterwards, whatever happens. Closing the last window is kept from quitting the application meanwhile: with window hidden, the overlay is the last.

Parameters:

Name Type Description Default

window

QWidget

The window to take out of the picture.

required

Returns:

Type Description
Optional[QPixmap]

The region as a pixmap, or None when cancelled or no screen exists.

keycap

keycap(keys: str) -> str

Render a keyboard shortcut as rich text, one keycap per key.

Parameters:

Name Type Description Default

keys

str

A Qt key sequence, such as "Ctrl+S", "F5" or "Ctrl+K, Ctrl+S".

required

Returns:

Name Type Description
str str

HTML for the keycaps, or an empty string when keys is empty.

Examples:

>>> button.setToolTip(f"Save {keycap('Ctrl+S')}")
Note

The HTML holds the current theme's colours; a keycap on a window is an FXKeycap.

tip

tip(title: str, body: str = '', shortcut: str = '') -> str

Build the HTML for a rich tooltip.

Parameters:

Name Type Description Default

title

str

What the control is, in a couple of words. Sentence case, no trailing period, it is a label and not a sentence.

required

body

str

What the control does, or why it is unavailable; a newline breaks the line. Defaults to "".

''

shortcut

str

A Qt key sequence, such as "Ctrl+S". Defaults to "".

''

Returns:

Name Type Description
str str

HTML to hand to setToolTip. An empty string when all three arguments are empty, so a caller can pass a missing value through without producing an empty floating box.

Examples:

>>> tip("", "", "")
''
>>> button.setToolTip(
...     tip("Save", "Write the scene to disk", "Ctrl+S")
... )
Note

The HTML holds the current theme's colours: call it when the tip shows, as a model's data(ToolTipRole) does, or use apply_tip. Every caller string is HTML-escaped, so a path or a name holding & or < reaches the user as text instead of corrupting the markup. Qt ignores max-width and applies a table width as a fixed width, so there is no width cap: the tooltip wraps itself, up to 440 px.