Sizing Behaviors¶
morphui.uix.behaviors.sizing
¶
Comprehensive sizing behaviors for Kivy widgets.
This module provides all size-related functionality through three main behaviors: - Size bounds/constraints (minimum and maximum size limits) - Interactive resizing (drag to resize with mouse) - Auto-sizing (content-driven automatic sizing)
The sizing behaviors support: - Lower and upper bound size constraints - Edge and corner resizing with visual feedback - Automatic sizing based on content and children - Cursor changes and hover effects for resize - Aspect ratio preservation - Event system for resize and auto-size operations
MorphSizeBoundsBehavior(**kwargs)
¶
Bases: EventDispatcher
A behavior that provides size constraint functionality.
This behavior adds lower and upper bound properties for constraining widget dimensions. It automatically resolves these bounds considering the widget's inherent minimum and maximum dimensions, providing a clean interface for size constraint enforcement.
Features
- Lower Bounds: Minimum size constraints with fallback to inherent minimums
- Upper Bounds: Maximum size constraints with infinity fallback
- Automatic Resolution: Computed properties handle constraint logic
- Flexible Configuration: Disable constraints with negative values
Properties
- :attr:
size_lower_bound: Minimum width and height constraints - :attr:
size_upper_bound: Maximum width and height constraints - :attr:
_resolved_size_lower_bound: Computed lower bounds (read-only) - :attr:
_resolved_size_upper_bound: Computed upper bounds (read-only)
Examples:
Basic size-constrained widget:
from kivy.uix.widget import Widget
from morphui.uix.behaviors.sizing import MorphSizeBoundsBehavior
class ConstrainedWidget(MorphSizeBoundsBehavior, Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
# Set minimum size to 100x50, maximum size to 500x300
self.size_lower_bound = [100, 50]
self.size_upper_bound = [500, 300]
def constrain_size(self, new_size):
from morphui.utils import clamp
width = clamp(new_size[0],
self._resolved_size_lower_bound[0],
self._resolved_size_upper_bound[0])
height = clamp(new_size[1],
self._resolved_size_lower_bound[1],
self._resolved_size_upper_bound[1])
return (width, height)
Using with negative values to disable constraints:
# Only constrain width, not height
widget.size_lower_bound = [100, -1] # Min width 100, no min height
widget.size_upper_bound = [500, -1] # Max width 500, no max height
size_lower_bound = VariableListProperty([-1, -1], length=2)
class-attribute
instance-attribute
¶
Lower bound size constraints [width, height].
Prevents the widget from being resized smaller than these dimensions. Useful for maintaining usability and preventing widgets from becoming too small to interact with. Use [0, 0] to disable minimum size constraints. If a negative value is specified for a dimension, the widget's inherent minimum size will be used.
:attr:size_lower_bound is a :class:~kivy.properties.VariableListProperty
and defaults to [-1, -1].
size_upper_bound = VariableListProperty([-1, -1], length=2)
class-attribute
instance-attribute
¶
Upper bound size constraints [width, height].
Prevents the widget from being resized larger than these dimensions. Use [-1, -1] to disable maximum size constraints.
:attr:size_upper_bound is a :class:~kivy.properties.VariableListProperty
and defaults to [-1, -1].
constrain_size(size)
¶
Apply size bounds constraints to a given size.
This convenience method applies both lower and upper bound constraints to a size tuple, returning the constrained dimensions.
| PARAMETER | DESCRIPTION |
|---|---|
size
|
The size to constrain (width, height)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Tuple[float, float]
|
The constrained size (width, height) |
Examples:
MorphAutoSizingBehavior(**kwargs)
¶
Bases: EventDispatcher
Behavior for automatic widget sizing based on content.
This behavior provides three boolean properties that enable automatic sizing of widgets based on their content and children. It can automatically adjust width, height, or both dimensions to fit the minimum required size.
Features
- Auto Width: Automatically adjust width to fit content
- Auto Height: Automatically adjust height to fit content
- Combined Auto Size: Automatically adjust both dimensions
- Text Integration: Special handling for text-based widgets
- Content Adaptation: Adapts to minimum/maximum size constraints
Properties
- :attr:
auto_width: Enable automatic width adjustment - :attr:
auto_height: Enable automatic height adjustment - :attr:
auto_size: Enable both width and height adjustment
Examples:
Auto-sizing label:
from kivy.uix.label import Label
from morphui.uix.behaviors.sizing import MorphAutoSizingBehavior
class AutoLabel(MorphAutoSizingBehavior, Label):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.auto_size = True # Adjust both width and height
Auto-width button:
from kivy.uix.button import Button
from morphui.uix.behaviors.sizing import MorphAutoSizingBehavior
class AutoButton(MorphAutoSizingBehavior, Button):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.auto_width = True # Only adjust width
auto_width = BooleanProperty(False)
class-attribute
instance-attribute
¶
Automatically adjust widget width to minimum required size.
When True, the widget's width will be automatically calculated and set to the minimum size required to accommodate all its content and children. This is useful for creating widgets that adapt their width based on their packed content, such as buttons that resize based on text length or containers that fit their child widgets.
:attr:auto_width is a :class:~kivy.properties.BooleanProperty
and defaults to False.
auto_height = BooleanProperty(False)
class-attribute
instance-attribute
¶
Automatically adjust widget height to minimum required size.
When True, the widget's height will be automatically calculated and set to the minimum size required to accommodate all its content and children. This is useful for creating widgets that adapt their height based on their packed content, such as labels that resize based on text height or containers that fit their child widgets vertically.
:attr:auto_height is a :class:~kivy.properties.BooleanProperty
and defaults to False.
auto_size = AliasProperty(_get_auto_size, _set_auto_size, bind=('auto_width', 'auto_height'))
class-attribute
instance-attribute
¶
Automatically adjust both width and height to minimum required size.
When True, both the widget's width and height will be automatically calculated and set to the minimum size required to accommodate all its content and children. This is useful for creating widgets that fully adapt their size based on their packed content.
Note that setting :attr:auto_size to True will set both
:attr:auto_width and :attr:auto_height to True. Conversely,
setting :attr:auto_size to False will set both :attr:auto_width
and :attr:auto_height to False. You can also set :attr:auto_size
to a tuple of two booleans to independently control width and
height.
:attr:auto_size is a :class:~kivy.properties.AliasProperty and
defaults to (False, False).
has_text_layout
property
¶
Check if the widget uses Kivy's text layout system.
Returns True if the widget has both texture_size and
text_size attributes, which is the case for text-based
widgets like Label. Used to decide whether to measure and
constrain text dimensions during auto sizing.
apply_auto_sizing(auto_width, auto_height)
¶
Enforce auto sizing based on provided flags. This will not change the property values, but will apply the sizing adjustments as if the properties were set.
This method is responsible for applying the appropriate sizing
adjustments to the widget based on the provided flags. It stores
the original size and size_hint before making any changes,
allowing for restoration when auto sizing is disabled. It uses
:attr:texture_size if available, otherwise falls back to
:attr:minimum_width and :attr:minimum_height.
| PARAMETER | DESCRIPTION |
|---|---|
auto_width
|
Whether to apply auto width sizing.
TYPE:
|
auto_height
|
Whether to apply auto height sizing.
TYPE:
|
Notes
For text-based widgets, :attr:text_size is temporarily set to
(None, None) to allow the texture to update to its natural
(unconstrained) size before applying the new dimensions. This
prevents a previously set text_size from wrapping longer text
before we have a chance to measure the natural width.
refresh_auto_sizing()
¶
Re-apply the current auto sizing settings.
This method can be called to refresh the auto sizing behavior,
for example after dynamic changes to the widget that may affect
sizing. It re-applies the sizing adjustments based on the current
values of :attr:auto_width and :attr:auto_height.
This method preserves the original size and size_hint before re-applying the sizing adjustments, ensuring that the widget can return to its original size if needed.
on_auto_size_updated(*args)
¶
Event fired after auto sizing has been applied or refreshed.
This event can be used to perform additional actions after the
widget's size has been adjusted based on its content. It is
triggered at the end of the :meth:apply_auto_sizing method.
MorphResizeBehavior(**kwargs)
¶
Bases: MorphSizeBoundsBehavior, MorphHoverEnhancedBehavior, MorphOverlayLayerBehavior
A behavior that enables widgets to be resized by dragging edges and corners.
This behavior combines size bounds, enhanced hover detection, and overlay layer functionality to provide interactive resizing capabilities. It automatically detects when the mouse is over resizable edges or corners and provides visual feedback through edge highlighting and cursor changes.
Features
- Edge Resizing: Resize by dragging left, right, top, or bottom edges
- Corner Resizing: Resize diagonally by dragging corners
- Visual Feedback: Highlighted edges and appropriate cursor changes
- Size Constraints: Minimum and maximum size limits via inheritance
- Aspect Ratio: Optional aspect ratio preservation
- Animation: Smooth transitions for visual feedback
- Events: Comprehensive event system for resize operations
Events
- :meth:
on_resize_start: Fired when resize operation begins - :meth:
on_resize_progress: Fired during resize (real-time updates) - :meth:
on_resize_end: Fired when resize operation completes
Properties
- :attr:
resize_enabled: Enable/disable resize functionality - :attr:
resizable_edges: List of edges that can be resized - :attr:
size_lower_bound: Minimum width and height constraints (inherited) - :attr:
size_upper_bound: Maximum width and height constraints (inherited) - :attr:
preserve_aspect_ratio: Whether to maintain aspect ratio
Examples:
Basic resizable widget:
from kivy.uix.widget import Widget
from morphui.uix.behaviors.sizing import MorphResizeBehavior
class ResizableWidget(MorphResizeBehavior, Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.size = (200, 150)
self.pos = (100, 100)
# Set size constraints
self.size_lower_bound = [50, 50]
self.size_upper_bound = [400, 300]
def on_resize_start(self, edge_or_corner):
print(f"Starting resize from {edge_or_corner}")
def on_resize_end(self, edge_or_corner):
print(f"Finished resizing")
Resizable widget with aspect ratio preservation:
class AspectResizableWidget(MorphResizeBehavior, Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.preserve_aspect_ratio = True
self.size_lower_bound = [100, 75] # 4:3 ratio minimum
resize_enabled = BooleanProperty(True)
class-attribute
instance-attribute
¶
Enable or disable resize functionality.
When set to False, the widget will not respond to resize operations, but hover detection and visual feedback will still work. This is useful for temporarily disabling resize while maintaining visual consistency.
:attr:resize_enabled is a :class:~kivy.properties.BooleanProperty
and defaults to True.
resizable_edges = ListProperty(NAME.EDGES)
class-attribute
instance-attribute
¶
List of edges that can be used for resizing.
Controls which edges of the widget can be dragged to resize. Can contain any combination of 'left', 'right', 'top', 'bottom'. Corner resizing is automatically enabled when two adjacent edges are both resizable.
:attr:resizable_edges is a :class:~kivy.properties.ListProperty
and defaults to all edges (left, right, top, bottom).
preserve_aspect_ratio = BooleanProperty(False)
class-attribute
instance-attribute
¶
Whether to preserve the widget's aspect ratio during resize.
When True, the widget will maintain its width-to-height ratio during resize operations. This is particularly useful for images, video players, or other content where aspect ratio is important.
:attr:preserve_aspect_ratio is a :class:~kivy.properties.BooleanProperty
and defaults to False.
resizing = BooleanProperty(False)
class-attribute
instance-attribute
¶
Indicates whether a resize operation is currently in progress.
This property is True while the user is actively dragging an edge or
corner to resize the widget, and False otherwise. It can be used to
conditionally change behavior or appearance during resize
operations. For example, you might want to disable certain
interactions while resizing is happening.
The :class:morphui.uix.behaviors.states.MorphStateBehavior
listens to this property and so does the
:class:morphui.uix.behaviors.layer.MorphOverlayLayerBehavior.
:attr:resizing is a :class:~kivy.properties.BooleanProperty
and defaults to False.
resize_edge_or_corner
property
¶
The edge or corner currently being used for resize operation (read-only).
This property is set when a resize operation starts and cleared when it ends. It indicates which edge ('left', 'right', 'top', 'bottom') or corner ('top-left', 'top-right', 'bottom-left', 'bottom-right') is being dragged to resize the widget. If no resize operation is in progress, this will be None.
hovered_resizable_edges
property
¶
List of currently hovered edges that are resizable.
Only edges present in :attr:resizable_edges will be included.
If resize is disabled, this will always be an empty list.
hovered_resizable_corner
property
¶
Currently hovered corner if it is resizable, else None.
on_touch_down(touch)
¶
Handle touch down events for resize operations.
This method initiates a resize operation if the touch occurs over a resizable edge or corner. It sets up the necessary state for the resize operation to proceed.
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if touch was handled for resize |
on_touch_move(touch)
¶
Handle touch move events during resize operations.
This method updates the size and position of the widget being resized based on the current mouse position. It applies size constraints and dispatches the appropriate resize event.
| PARAMETER | DESCRIPTION |
|---|---|
touch
|
Touch event
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if touch was handled for resize |
on_touch_up(touch)
¶
Handle touch up events to end resize operations.
This method finalizes the resize operation, resets state, and dispatches the resize end event.
| PARAMETER | DESCRIPTION |
|---|---|
touch
|
Touch event
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if touch was handled for resize |
on_resize_start(edge_or_corner)
¶
Event fired when a resize operation starts.
This event is dispatched when the user starts dragging an edge or corner to resize the widget. Override this method to add custom behavior at the start of resize operations.
| PARAMETER | DESCRIPTION |
|---|---|
edge_or_corner
|
The edge or corner being used for resize ('left', 'right', 'top', 'bottom', or corner names like 'top-left')
TYPE:
|
Examples:
on_resize_progress(edge_or_corner, new_size, new_pos)
¶
Event fired during resize operations with new dimensions.
This event is dispatched continuously while the user drags to resize the widget. The default implementation applies the new size and position to the widget. Override this method to customize resize behavior or add validation.
| PARAMETER | DESCRIPTION |
|---|---|
edge_or_corner
|
The edge or corner being used for resize
TYPE:
|
new_size
|
New widget size (width, height)
TYPE:
|
new_pos
|
New widget position (x, y)
TYPE:
|
Examples:
on_resize_end(edge_or_corner)
¶
Event fired when a resize operation completes.
This event is dispatched when the user releases the mouse after resizing the widget. Override this method to add custom behavior at the end of resize operations, such as saving the new size or triggering layout updates.
| PARAMETER | DESCRIPTION |
|---|---|
edge_or_corner
|
The edge or corner that was used for resize
TYPE:
|
Examples:
on_leave()
¶
Override parent on_leave to reset cursor.