Box

The box layout classes provide a simple mechanism to horizontally or vertically stack child widgets. The BoxLayout (and HBox and VBox) are intended for laying out leaf content taking into account the natural size of the child widgets. The BoxPanel (and HBoxPanel and VBoxPanel) are intended for higher-level layout. Instead of the “natural” size of a widget, the widgets base_size property is used as the “reference” size.

In chosing between these two kinds of layouts, one could ask oneself whether the layout can be replaced by a SplitPanel. If it can, use a BoxPanel.

Example for BoxLayout:

from flexx import ui

class Example(ui.Widget):
    def init(self):
        with ui.BoxLayout(orientation='v'):

            ui.Label(text='Flex 0 0 0')
            with ui.HBox(flex=0):
                self.b1 = ui.Button(text='Hola', flex=0)
                self.b2 = ui.Button(text='Hello world', flex=0)
                self.b3 = ui.Button(text='Foo bar', flex=0)

            ui.Label(text='Flex 1 0 3')
            with ui.HBox(flex=0):
                self.b1 = ui.Button(text='Hola', flex=1)
                self.b2 = ui.Button(text='Hello world', flex=0)
                self.b3 = ui.Button(text='Foo bar', flex=3)

            ui.Label(text='padding 10 (around layout)')
            with ui.HBox(flex=0, padding=10):
                self.b1 = ui.Button(text='Hola', flex=1)
                self.b2 = ui.Button(text='Hello world', flex=1)
                self.b3 = ui.Button(text='Foo bar', flex=1)

            ui.Label(text='spacing 10 (inter-widget)')
            with ui.HBox(flex=0, spacing=10):
                self.b1 = ui.Button(text='Hola', flex=1)
                self.b2 = ui.Button(text='Hello world', flex=1)
                self.b3 = ui.Button(text='Foo bar', flex=1)

            ui.Widget(flex=1)
            ui.Label(text='Note the spacer Widget above')
open in new tab

A similar example using a BoxPanel:

from flexx import ui

class Example(ui.Widget):
    def init(self):
        with ui.VBoxPanel():

            ui.Label(text='Flex 0 0 0', style='')
            with ui.HBoxPanel(flex=0):
                self.b1 = ui.Button(text='Hola', flex=0)
                self.b2 = ui.Button(text='Hello world', flex=0)
                self.b3 = ui.Button(text='Foo bar', flex=0)

            ui.Label(text='Flex 1 0 3')
            with ui.HBoxPanel(flex=0):
                self.b1 = ui.Button(text='Hola', flex=1)
                self.b2 = ui.Button(text='Hello world', flex=0)
                self.b3 = ui.Button(text='Foo bar', flex=3)

            ui.Label(text='spacing 10 (inter-widget)')
            with ui.HBoxPanel(flex=0, spacing=20):
                self.b1 = ui.Button(text='Hola', flex=1)
                self.b2 = ui.Button(text='Hello world', flex=1)
                self.b3 = ui.Button(text='Foo bar', flex=1)

            ui.Widget(flex=1)
open in new tab

Interactive BoxLayout example:

from flexx import ui, event

class Example(ui.HBox):
    def init(self):
        self.b1 = ui.Button(text='Horizontal', flex=0)
        self.b2 = ui.Button(text='Vertical', flex=1)
        self.b3 = ui.Button(text='Horizontal reversed', flex=2)
        self.b4 = ui.Button(text='Vertical reversed', flex=3)

    class JS:

        @event.connect('b1.mouse_down')
        def _to_horizontal(self, *events):
            self.orientation = 'h'

        @event.connect('b2.mouse_down')
        def _to_vertical(self, *events):
            self.orientation = 'v'

        @event.connect('b3.mouse_down')
        def _to_horizontal_rev(self, *events):
            self.orientation = 'hr'

        @event.connect('b4.mouse_down')
        def _to_vertical_r(self, *events):
            self.orientation = 'vr'
open in new tab

A classic high level layout:

from flexx import ui


class Content(ui.Widget):
    def init(self):
            # Here we use BoxLayout, because we care about natural size

            with ui.HBox():
                ui.Widget(flex=1)  # spacer
                ui.Button(text='hello')
                ui.Widget(flex=1)  # spacer


class SideWidget(ui.Label):
    CSS = '.flx-SideWidget {background: #aaf; border: 2px solid black;}'


class Example(ui.Widget):

    def init(self):
        # Here we use BoxPanel, because we define high-level layout

        with ui.VBoxPanel():
            SideWidget(text='Header', flex=0, base_size=100)
            with ui.HBoxPanel(flex=1):
                SideWidget(text='Left', flex=0, base_size=100)
                Content(flex=1)
                SideWidget(text='Right', flex=0, base_size=100)
            SideWidget(text='Bottom', flex=0, base_size=100)
open in new tab


class flexx.ui.layouts._box.BaseBoxLayout(*init_args, **kwargs)

Inherits from: Layout

Base class for BoxLayout and BoxPanel.

orientation

property – The orientation of the child widgets. ‘h’ or ‘v’. Default horizontal. The items can also be reversed using ‘hr’ and ‘vr’.

spacing

property – The space between two child elements (in pixels)

class flexx.ui.BoxLayout(*init_args, **kwargs)

Inherits from: BaseBoxLayout

Layout to distribute space for widgets horizontally or vertically.

This layout implements CSS flexbox. The reference size of each child widget is based on its natural size (e.g. a button’s natural size depends on its text). Further, the minimum and maximum size (set via styling) are taken into account. Extra space is divided according to the flex property of the child widgets.

Also see VBox and HBox for shorthands.

padding

property – The empty space around the layout (in pixels).

class flexx.ui.BoxPanel(*init_args, **kwargs)

Inherits from: BaseBoxLayout

Layout to distribute space for widgets horizontally or vertically.

This layout is implemented using absolute positioning. The reference size of each child widget is based on its base_size property. When this value is zero, an attempt is made to measure the natural size of the children, but this is not very reliable. Further, the minimum and maximum size (set via styling) are taken into account. Extra space is divided according to the flex property of the child widgets.

The BoxPanel differs from the BoxLayout in that the natural size of widgets is not taken into account. It is therefore more suited for high-level layout or for child widgets that do not have a natural size.

Also see VBoxPanel and HBoxPanel for shorthands.

class flexx.ui.HBox(*init_args, **kwargs)

Inherits from: BoxLayout

BoxLayout with horizontal layout. Consider using HBoxPanel if you’re using this for high-level layout.

class flexx.ui.HBoxPanel(*init_args, **kwargs)

Inherits from: BoxPanel

BoxPanel with horizontal layout. Consider using HBox if you’re using this for low-level layout and the children have a “natural” size.

class flexx.ui.VBox(*init_args, **kwargs)

Inherits from: BoxLayout

BoxLayout with vertical layout. Consider using VBoxPanel if you’re using this for high-level layout.

class flexx.ui.VBoxPanel(*init_args, **kwargs)

Inherits from: BoxPanel

BoxPanel with vertical layout. Consider using VBox if you’re using this for low-level layout and the children have a “natural” size.