Welcome to Flexx’s documentation!

Flexx is a pure Python toolkit for creating graphical user interfaces (GUI’s), that uses web technology for its rendering. Apps are written purely in Python; The PScript transpiler generates the necessary JavaScript on the fly.

You can use Flexx to create (cross platform) desktop applications, web applications, and export an app to a standalone HTML document. It also works in the Jupyter notebook.

The docs are on Readthedocs, the code is on Github, and there is a demo server. Once you’ve got started, the most important page is probably the Widget reference.

Contents

Getting started

Installation

  • pip install flexx
  • conda install flexx -c conda-forge
  • Old school: python setup.py install
  • Clone the repo and add the root dir to your PYTHONPATH (developer mode)

When using Pip or Conda, the dependencies will be installed automatically.

Dependencies

Being pure Python and cross platform, Flexx should work (almost) anywhere where there’s Python and a browser. Flexx is written for Python 3.5+ and also works on Pypy.

Flexx further depends on the following packages (all are pure Python, and the latter three are projects under the flexxui umbrella):

Supported browsers

Flexx aims to support all modern browsers, including Firefox, Chrome and Edge. Internet Explorer version 10 and up should work, but some things may be flaky.

To run apps that look like desktop apps, we recommend having Firefox or nw.js installed.

Current status

Since version 0.5 (September 2018), Flexx is in beta status; some parts of the API may change, but we do care about backwards compatibility.

Guide

Widgets basics

If you’re interested in Flexx, the first thing that you probably want to do is create a UI. So let’s see how that works, and talk about components, events and reactions later.

Your first widget

The Widget class is the base class of all other ui classes. On itself it does not do or show much. What you’ll typically do, is subclass it to create a new widget that contains ui elements:

from flexx import flx

class Example(flx.Widget):

    def init(self):
        flx.Button(text='hello')
        flx.Button(text='world')

The above is usually not the layout that you want. Therefore there are layout widgets which distribute the space among its children in a more sensible manner. Like the HBox:

from flexx import flx

class Example(flx.Widget):

    def init(self):
        with flx.HBox():
            flx.Button(text='hello', flex=1)
            flx.Button(text='world', flex=2)

The HBox and Button are all widgets too. The example widgets that we created above are also refered to as “compound widgets”; widgets that contain other widgets. This is the most used way to create new UI elements.

The init method

In the above example one can see the use of the init() method, which is a common use in Flexx. It is generally better to use it instead of __init__(), because Flexx calls it at a very approproate time in the initialization process. For example, when init() is called, the corresponding widget is the default parent.

Further, the init() gets the positional instantiation arguments: creating a component Person("john", 32) matches def init(self, name, age).

Structuring widgets

Flexx comes with it’s own layout system. (Therefore you should generally not use CSS for widget layout, though you can very well use CSS inside a widget).

Any widget class can also be used as a context manager. Within the context, that widget is the default parent; any widget that is created in that context and that does not specify a parent will have that widget as a parent. (This mechanism is thread-safe.) This allows for a style of writing that clearly shows the structure of your app:

from flexx import flx

class Example(flx.Widget):

    def init(self):
        with flx.HSplit():
            flx.Button(text='foo')
            with flx.VBox():
                flx.Widget(style='background:red;', flex=1)
                flx.Widget(style='background:blue;', flex=1)
Turning a widget into an app

To create an actual app from a widget, simply wrap it into an App. You can then launch() it as a desktop app, serve() it as a web app, dump() the assets, export() it as a standalone HTML document, or even publish() it online (experimental). Later in this guide we dive deeper into the different ways that you can run your app.

from flexx import flx

class Example(flx.Widget):
    def init(self):
        flx.Label(text='hello world')

app = flx.App(Example)
app.export('example.html', link=0)  # Export to single file

To actually show the app, use launch:

app.launch('browser')  # show it now in a browser
flx.run()  # enter the mainloop
Using widgets the Python way

In the above examples, we’ve used the “classic” way to build applications from basic components. Flexx provides a variety of layout widgets as well as leaf widgets (i.e. controls), see the list of widget classes.

Further, we’ve created high-level widgets by subclassing the flx.Widget class. These classes operate in JavaScript, because they are what we call JsComponent’s, more on that later. Effectively, we are able to show the widgets live inside the guide itself. However, if you are developing a desktop app, consider subclassing from PyWidget instead: this will make that your widgets operatate in Python instead of JavaScript. We talk more about this in the next page of the guide.

Using widgets the web way

An approach that might be more familiar for web developers, and which is inspired by frameworks such as React is to build custom widgets using html elements. If you’re used to Python and the below looks odd to you, don’t worry, you don’t need it:

from flexx import flx

class Example(flx.Widget):

    name = flx.StringProp('John Doe', settable=True)
    age =  flx.IntProp(22, settable=True)

    @flx.action
    def increase_age(self):
        self._mutate_age(self.age + 1)

    def _create_dom(self):
        # Use this method to create a root element for this widget.
        # If you just want a <div> you don't have to implement this.
        return flx.create_element('div')  # the default is <div>

    def _render_dom(self):
        # Use this to determine the content. This method may return a
        # string, a list of virtual nodes, or a single virtual node
        # (which must match the type produced in _create_dom()).
        return [flx.create_element('span', {},
                    'Hello', flx.create_element('b', {}, self.name), '! '),
                flx.create_element('span', {},
                    'I happen to know that your age is %i.' % self.age),
                flx.create_element('br'),
                flx.create_element('button', {'onclick': self.increase_age},
                    'Next year ...')
                ]

The _render_dom() method is called from an implicit reaction. This means that when any properties that are accessed during this function change, the function is automatically called again. This thus provides a declerative way to define the appearance of a widget using HTML elements.

Above, the third argument in create_element() is a string, but this may also be a list of dicts (create_element() returns a dict).

Widgets are components

Widgets are what we call “components”, which are a central part of the event system. They are what allows widgets to have properties and react to things happening in other parts of the application. But let’s not get ahead of ourselves; the event system is dicsussed in the next chapter.

For the moment, it’s enough to know that the Widget class is kind of JsComponent. This means that these widgets live in JavaScript: when their actions and methods are called, they run in JavaScript. But the cool thing is that you can still use these objects in Python, by setting their properties, invoking their actions, and reacting to their state. This is possible because of so-called proxy objects.

We mentioned earlier that the PyWidget can be used to create widgets that live in Python: these are a kind of PyComponent: their actions and methods are executed in Python. And yes, they can be used from JS by setting properties, invoking action and reacting to state.

Being able to write components (and widgets) that operate either in Python or JavaScript is a very powerful feature of Flexx. However, it can easily be a source of confusion. Therefore it’s good to understand the difference between these kinds of classes.

PyComponent and JsComponent

A Flexx application consists of components that exist in either Python or JavaScript, and which can communicate with each-other in a variety of ways.

The PyComponent and JsComponent classes derive from the Component class (which is a topic of the next chapter). The most important things to know about PyComponent and JsComponent:

  • They are both associated with a Session.
  • They have an id attribute that is unique within their session, and a uid attribute that is globally unique.
  • They live (i.e. their methods run) in Python and JavaScript, respectively.
  • A PyComponent can only be instantiated in Python, a JsComponent can be instantiated in both Python and JavaScript.
  • A PyComponent always has a corresponding proxy object in JavaScript.
  • A JsComponent may have a proxy object in Python; these proxy objects are created automatically when Python references the component.

In practice, you’ll use PyComponents to implement Python-side behavior, and JsComponents (e.g. Widgets) for the behavior in JavaScript. Flexx allows a variety of ways by which you can tie Python and JS together, but this can be a pitfall. It’s important to think well about what parts of your app operate in JavaScript and what in Python. Patterns which help you do this are discussed later in the guide.

(And the plain Component class? It can be used (both in Python and JS), but is unaware of anything “on the other side”. It’s use in Flexx is therefore limited.)

Proxy components

The proxy components allow the “other side” to inspect properties, invoke actions and connect to events. The real component is aware of what events the proxy reacts to, and will only communicate these events.

The example below may be a bit much to digest. Don’t worry about that. In most cases things should just work.

from flexx import flx

class Person(flx.JsComponent):  # Lives in Js
    name = flx.StringProp(settable=True)
    age = flx.IntProp(settable=True)

    @flx.action
    def increase_age(self):
        self._mutate_age(self.age + 1)

class PersonDatabase(flx.PyComponent):  # Lives in Python
    persons = flx.ListProp()

    @flx.action
    def add_person(self, name, age):
        with self:  # new components need a session
            p = Person(name=name, age=age)
        self._mutate_persons([p], 'insert', 99999)

    @flx.action
    def new_year(self):
        for p in self.persons:
            p.increase_age()

In the above code, the Person objects live in JavaScript, while a database object that keeps a list of them lives in Python. In practice, the Person components will e.g. have a visual representation in the browser. The database could also have been a JsComponent, but let’s assume that we need it in Python because it synchronizes to a mysql database or something.

We can observe that the add_person action (which executes in Python) instantiates new Person objects. Actually, it instantiates proxy objects that automatically get corresponding (real) Person objects in JavaScript. The new_year action executes in Python, which in turn invokes the increase_age action of each person, which execute in JavaScript.

Actions and events cross the boundary

It’s important to realize that actions of a component can be invoked from anywhere. In the above example, Person.set_name("Guido") can be called from Python (e.g. by the PersonDatabase).

Similarly, you can use reactions to listen for changes on components, no matter whether these components live in Python or JavaScript. As an example, let’s implement a personcounter (reactions are covered later in this guide):

class PersonCounter(flx.JsComponent):

    def init(self, db):
        self.db = db
        # now we can call self.db.add_person() from JavaScript!

    @flx.reaction
    def _count(self):
        print("There are", len(self.db.persons), "persons")

# To instantiate (e.g. inside PersonDatabase.init())
PersonCounter(database)

# Note that we can also invoke the db's actions from here!
The root component and active components

Another useful feature is that each component has a root attribute that holds a reference to the component representing the root of the application. E.g. if the root is a PersonDatabase, all JsComponent objects have a reference to (a proxy of) this database.

Further, when a component is used as a context manager, it becomes an “active component”. We’ve already seen how this is used to structure child widgets. Sometimes you may want to know which components are active, which you can do with loop.get_active_component and loop.get_active_components.

The event system

The event system consists of components, properties, events, and reactions. They let different components of an application react to each-other and to user input.

In short:

  • The components (e.g. widgets) form the units of which an application is build.
  • Each component has properties to reflect the state of the component.
  • Properties can only be mutated by actions. Calling (i.e. invoking) an action will not apply the action at once; actions are processed in batches.
  • When properties are modified (i.e. the state is changed), corresponding reactions will be invoked. The reactions are processed when all pending actions are done. This means that during processing reactions, the state never changes, which is a great thing to rely on!
  • Reactions can also react to events generated by emitters, such as mouse events.
  • The event loop object is responsible for scheduling actions and reactions. In Python it intergrates with Python’s own asyncio loop. In JavaScript it makes use of the JavaScript scheduling mechanics.

The asynchronous nature of actions combined with the fact that the state does not change during processing reactions, makes it easy to reason about cause and effect. The information flows in one direction. This concept was gratefully taken from modern frameworks such as React/Flux and Veux.

https://docs.google.com/drawings/d/e/2PACX-1vSHp4iha6CTgjsQ52x77gn0hqQP4lZD-bcaVeCfRKhyMVtaLeuX5wpbgUGaIE0Sce_kBT9mqrfEgQxB/pub?w=503

One might argue that the information flow is still circular, because there is an arrow going from reactions to actions. This is true, but note that actions invoked from reactions are not directly executed; they are pended and will be executed only after all reactions are done.

Relation to other parts of Flexx

This event system and its Component class form the basis for app.PyComponent, app.JsComponent and the UI system in flexx.ui. It can be used in both Python and JavaScript and works exactly the same in both languages.

Other than that, this is a generic event system that could drive any system that is based on asyncio.

Event object

An event is something that has occurred at a certain moment in time, such as the mouse being pressed down or a property changing its value. In Flexx, events are represented with dictionary objects that provide information about the event (such as what button was pressed, or the old and new value of a property). A custom Dict class is used that inherits from dict but allows attribute access, e.g. ev.button as an alternative to ev['button'].

Each event object has at least two attributes: source, a reference to the component object emitting the event, and type, a string indicating the type of the event.

The Component class

The Component class provides a base class for objects that have properties, actions, reactions and emitters. You can create your own components like so:

class MyObject(flx.Component):
    ...  # attributes/properties/actions/reactions/emitters go here

    def init(self):
        super().init()
        ...

It is common to implement the init() method of the component class. It gets automatically called by the component, at a moment when all properties have been initialized, but no events have been emitted yet. This is a good time to further initialize the component, and/or to instantiate sub components. One rarely needs to implement the __init__() method.

When the init() is called, the component is the currently “active” component, which can be used to e.g. descrive a hierarchy of objects, as is done with widgets. It also implies that mutations are allowed and that actions on the component itself have a direct effect (invoking actions of other components is still asynchronous though).

Let’s look at a real working widget example and break it down. It contains a property, an action, and a few reactions:

from flexx import flx

class Example(flx.Widget):

    counter = flx.IntProp(3, settable=True)

    def init(self):
        super().init()

        with flx.HBox():
            self.but1 = flx.Button(text='reset')
            self.but2 = flx.Button(text='increase')
            self.label = flx.Label(text='', flex=1)  # take all remaining space

    @flx.action
    def increase(self):
        self._mutate_counter(self.counter + 1)

    @flx.reaction('but1.pointer_click')
    def but1_clicked(self, *events):
        self.set_counter(0)

    @flx.reaction('but2.pointer_click')
    def but2_clicked(self, *events):
        self.increase(0)

    @flx.reaction
    def update_label(self, *events):
        self.label.set_text('count is ' + str(self.counter))

We will now take a closer look at properties and actions. Reactions are so cool that they’ve got their own chapter :)

Properties represent state

In the widget example above, we can see an int property. There are a handful of different property types. For example:

class MyObject(flx.Component):

    foo = flx.AnyProp(8, settable=True, doc='can have any value')
    bar = flx.IntProp()

Properties accept one positional arguments to set the default value. If not given, a sensible default value is used that depends on the type of property. Docs can be added using the doc argument. Note that properties are readonly: they can can only be mutated by actions. The foo property (as well as the counter property) is marked as settable, which will automatically create a set_foo() action.

Property values can be initialized when a component is created (also non-settable properties):

c = MyComponent(foo=42)

One can also set the initial value of a property to a function object. This creates an auto-reaction that sets the property, and makes it possible to hook things up in a very concise manner. In the example below, the label text will be automatically updated when the username property changes:

flx.Label(flex=1, text=lambda: 'count is ' + str(self.counter))

An event is emitted every time that a property changes. This event has attributes old_value and new_value (except for in-place array mutations, as explained below). At initialization, a component sends out an event for each property, in which old_value and new_value will be the same.

Attributes

Component classes can also have Attributes, which are read-only (usually static) non-observable values (e.g. JsComponent.id).

Local properties

Regular methods of a JsComponent are only available in JavaScript. On the other hand, all properties are available on the proxy object as well. This may not always be useful. It is possible to create properties that are local to JavaScript (or to Python in a PyComponent) using LocalProperty. An alternative may be to use Attribute; these are also local to JavaScript/Python.

Actions can mutate properties

In the widget example above, we can see the definition of the increase() action. Actions are needed because they are the only place where properties can be mutated.

class Example(flx.Widget):

    counter = flx.IntProp(3, settable=True)

    ...

    @flx.action
    def increase(self):
        self._mutate_counter(self.counter + 1)

You may wonder why the example’s reaction does not simply do self.set_counter(self.counter + 1). The reason is that actions are asynchronous; invoking an action does not perform it directly. Therefore invoking set_counter() twice will simply apply the last value. Note though, that when an action is called from another action, it is performed directly.

Actions can have any number of (positional) arguments, and always returns the component itself, which allows chainging action invokations, e.g. t.scale(3).translate(3, 4).

Mutations are done via the _mutate method, or by the auto-generated _mutate_xx() methods. Mutations can only be done from an action. Trying to do so otherwise will result in an error. This may seem limiting at first, but it greatly helps keeping it easy to reason about information flowing through your application, even as it scales.

Mutations to array-like properties

The above shows the simple and most common use of mutations. For list properties, mutations can also be done in-place:

from flexx import flx

class Example(flx.Widget):

    items = flx.ListProp(settable=True)

    def init(self):
        super().init()

        with flx.HBox():
            self.but1 = flx.Button(text='reset')
            self.but2 = flx.Button(text='add')
            flx.Label(flex=1, wrap=2, text=lambda: repr(self.items))

    @flx.action
    def add_item(self, item):
        self._mutate_items([item], 'insert', len(self.items))

    @flx.reaction('but1.pointer_click')
    def but1_clicked(self, *events):
        self.set_items([])

    @flx.reaction('but2.pointer_click')
    def but2_clicked(self, *events):
        self.add_item(int(time()))

This allows more fine-grained control over state updates, which can also be handled by reactions in much more efficient ways. The types of mutations are ‘set’ (the default), ‘insert’, ‘replace’, and ‘remove’. In the latter, the provided value is the number of elements to remove. For the others it must be a list of elements to set/insert/replace at the specified index.

Emitters create events

Emitters make it easy to generate events. Similar to actions, they are created with a decorator.

# Somewhere in the Flexx codebase:
class Widget(JsComponent):

    ...

    @flx.emitter
    def key_down(self, e):
        """ Event emitted when a key is pressed down while this
        widget has focus.
        ...
        """
        return self._create_key_event(e)

Emitters can have any number of arguments and should return a dictionary, which will get emitted as an event, with the event type matching the name of the emitter.

Note that stricly speaking emitters are not necessary as Component.emit() can be used to generate an event. However, they provide a mechanism to generate an event based on certain input data, and also document the events that a component may emit.

Reactions

Reactions are used to react to events and changes in properties, using an underlying handler function:

from flexx import flx

class Example(flx.Widget):

    def init(self):
        super().init()
        with flx.VBox():
            with flx.HBox():
                self.firstname = flx.LineEdit(placeholder_text='First name')
                self.lastname = flx.LineEdit(placeholder_text='Last name')
            with flx.HBox():
                self.but = flx.Button(text='Reset')
                self.label = flx.Label(flex=1)

    @flx.reaction('firstname.text', 'lastname.text')
    def greet(self, *events):
        self.label.set_text('hi ' + self.firstname.text + ' ' + self.lastname.text)

    @flx.reaction('but.pointer_click')
    def reset(self, *events):
        self.label.set_text('')

This example demonstrates multiple concepts. Firstly, the reactions are connected via connection-strings that specify the types of the event; in this case the greet() reaction is connected to “firstname.text” and “lastname.text”, and reset() is connected to the event-type “pointer_click” event of the button. One can see how the connection-string is a path, e.g. “sub.subsub.event_type”. This allows for some powerful mechanics, as discussed in the section on dynamism.

One can also see that the reaction-function accepts *events argument. This is because reactions can be passed zero or more events. If a reaction is called manually (e.g. ob.handle_foo()) it will have zero events. When called by the event system, it will have at least 1 event. When e.g. a property is set twice, the function will be called just once, but with multiple events. If all events need to be processed individually, use:

@flx.reaction('foo')
def handler(self, *events):
    for ev in events:
        ...

In most cases, you will connect to events that are known beforehand, like those corresponding to properties and emitters. If you connect to an event that is not known Flexx will display a warning. Prepend an exclamation mark (e.g. '!foo') to suppress such warnings.

Greedy and automatic reactions

Each reaction operates in a certain “mode”. In mode “normal” (the default), the event system ensures that all events are handled in the order that they were emitted. This is often the most sensible approach, but this implies that a reaction can be called multiple times during a single event loop iteration, with other reactions called in between to ensure the consisten event order.

If it is preferred that all events targeted at a reaction are handled with a single call to that reaction, it can be set to mode “greedy”. Cases where this makes sense is when all related events must be processed simultenously, or simply when performance matters a lot and order matters less.

@flx.reaction('foo', mode='greedy')
def handler(self, *events):
    ...

Reactions with mode “auto” are automatically triggered when any of the properties that the reaction uses is changed. Such reactions can be created by specifying the mode argument, or simply by creating a reaction with zero connections strings. We refer to such reactions as “auto reactions” or “implicit reactions”.

This is a very convenient feature, but it has more overhead than a normal reaction, and should therefore probably be avoided when a lot of properties are accessed, or when the used properties change very often. It’s hard to tell exactly when it starts to significantly hurt performance, but “often” is probably around hundreds and “often around 100 times per second. Just keep this in mind and do your own benchmarks when needed.

from flexx import flx

class Example(flx.Widget):

    def init(self):
        super().init()
        with flx.VBox():
            with flx.HBox():
                self.slider1 = flx.Slider(flex=1)
                self.slider2 = flx.Slider(flex=1)
            self.label = flx.Label(flex=1)

    @flx.reaction
    def slders_combined(self):
        self.label.set_text('{:.2f}'.format(self.slider1.value + self.slider2.value))

A similar useful feature is to assign a property (at initialization) using a function. In such a case, the function is turned into an implicit reaction. This can be convenient to easily connect different parts of an app.

from flexx import flx

class Example(flx.Widget):

    def init(self):
        super().init()
        with flx.VBox():
            with flx.HBox():
                self.slider1 = flx.Slider(flex=1)
                self.slider2 = flx.Slider(flex=1)
            self.label = flx.Label(flex=1, text=lambda:'{:.2f}'.format(self.slider1.value * self.slider2.value))
Reacting to in-place mutations

In-place mutations to lists or arrays can be reacted to by processing the events one by one:

class MyComponent(flx.Component):

    @flx.reaction('other.items')
    def track_array(self, *events):
        for ev in events:
            if ev.mutation == 'set':
                self.items[:] = ev.objects
            elif ev.mutation == 'insert':
                self.items[ev.index:ev.index] = ev.objects
            elif ev.mutation == 'remove':
                self.items[ev.index:ev.index+ev.objects] = []  # objects is int here
            elif ev.mutation == 'replace':
                self.items[ev.index:ev.index+len(ev.objects)] = ev.objects
            else:
                assert False, 'we cover all mutations'

For convenience, the mutation can also be “replicated” using the flx.mutate_array() and flx.mutate_dict() functions.

Connection string labels

Connection strings can have labels to infuence the order by which reactions are called, and provide a means to disconnect specific (groups of) handlers at once.

class MyObject(flx.Component):

    @flx.reaction('foo')
    def given_foo_handler(*events):
            ...

    @flx.reaction('foo:aa')
    def my_foo_handler(*events):
        # This one is called first: 'aa' < 'given_f...'
        ...

When an event is emitted, any connected reactions are scheduled in the order of a key, which is the label if present, and otherwise the name of the name of the reaction.

The label can also be used in the disconnect() method:

@h.reaction('foo:mylabel')
def handle_foo(*events):
    ...

...

h.disconnect('foo:mylabel')  # don't need reference to handle_foo
Dynamism

Dynamism is a concept that allows one to connect to events for which the source can change. In the example below, we connect to the click event of a list of buttons, which keeps working even as that list changes.

from flexx import flx

class Example(flx.Widget):

    def init(self):
        super().init()
        with flx.VBox():
            with flx.HBox():
                self.but = flx.Button(text='add')
                self.label = flx.Label(flex=1)
            with flx.HBox() as self.box:
                flx.Button(text='x')

    @flx.reaction('but.pointer_click')
    def add_widget(self, *events):
        flx.Button(parent=self.box, text='x')

    @flx.reaction('box.children*.pointer_click')
    def a_button_was_pressed(self, *events):
        ev = events[-1]  # only care about last event
        self.label.set_text(ev.source.id + ' was pressed')

The a_button_was_pressed gets invoked when any of the buttons inside box is clicked. When the box’s children changes, the reaction is automatically reconnected. Note that in some cases you might also want to connect to changes of the box.children property itself.

The above works because box.children is a property. The reaction would still work if it would connect to widgets in a regular list, but it would not be dynamic.

Implicit dynamism

Implicit reactions are also dynamic, maybe even more so! In the example below, the reaction accesses the children property, thus it will be called whenever that property changes. It also connects to the visible event of all children, and to the foo event of all children that are visible.

from flexx import flx

class Example(flx.Widget):

    def init(self):
        super().init()
        with flx.VBox():
            with flx.HBox():
                self.but = flx.Button(text='add')
                self.label = flx.Label(flex=1)
            with flx.HBox() as self.box:
                flx.CheckBox()

    @flx.reaction('but.pointer_click')
    def add_widget(self, *events):
        flx.CheckBox(parent=self.box)

    @flx.reaction
    def a_button_was_pressed(self):
        ids = []
        for checkbox in self.box.children:
            if checkbox.checked:
                ids.append(checkbox.id)
        self.label.set_text('checked: ' + ', '.join(ids))

This mechanism is powerful, but one can see how it can potentially access (and thus connect to) many properties, especially if the reaction calls other functions that access more properties. As mentioned before, keep in mind that implicit reactions have more overhead, which scales with the number of properties that are accessed.

PScript, modules, and scope

In this guide, we’ve already seen several examples wherer we write Python code that runs in JavaScript. This is done by transpiling the Python code to JavaScript using a tool called PScript, which is a spin-off of the Flexx project.

The compilation of Python code to JavaScript happens automatically, at the moment that a JsComponent gets defined (i.e. imported). Flexx is aware of the classes that the browsers needs to know about and sends the corresponding code when needed. Therefore it’s possible to dynamically import or create new classes and use them.

PScript is almost Python

PScript is syntactically compatible with Python, so you can write it inside any Python module. PScript also feels a lot like Python, and it will probably get better in the future, but sometimes the JavaScript shines through. Thinks to watch out for:

  • Accessing a nonexisting attribute will return undefined instead of raising an AttributeError.
  • Keys in a dictionary are implicitly converted to strings.
  • Classes must start with a captial letter, functions must not. This is simply good practice in Python, but PScript needs it to tell classes apart from functions.
  • A function can accept keyword arguments if it has a **kwargs parameter or named arguments after *args. Passing keywords to a function that does not handle keyword arguments might result in confusing errors.

Things you can do, which you cannot do in Python:

  • Access elements in a dict as attributes (e.g. d.foo instead of d[“foo”]).
  • Implicitly convert values to sting by adding them to a string.
  • Divide by zero (results in inf).

Read more on http://pscript.readthedocs.io/.

Scope

In Flexx, it’s easy to possible to define PyComponents and JsComponents in the same module. For the purpose of clarity, it’s probably good to avoid this for larger applications.

Inside the methods of a JsComponent you can make use of plain Python functions and classes that are defined in the same module, provided that these (and their dependencies) can be transpiled by PScript. Similarly you can make use of objects defined or imported in the module. These can be integers, lists, dicts (and any combination thereof), as long as it can be JSON-serialized.

For every Python module that defines code that is used in JS, a corresponding JS module is created. Flexx detects what variable names are used in the JS code, but not declared in it, and tries to find the corresponding object in the module. You can even import functions/classes from other modules.

from flexx import flx

from foo import func1

def func2():
    ...

info = {'x': 1, 'y': 2}

class MyComponent(flx.JsComponent):

    @flx.reaction('some.event')
    def handler(self, *events):
        func1(info)
        func2()

In the code above, Flexx will include the definition of func2 and info in the same module that defines MyComponent, and include func1 in the JS module foo. If MyComponent would not use these functions, neither definition would be included in the JavaScript module.

A useful feature is that the RawJS class from PScript can be used in modules to define objects in JS:

from flexx import flx

my_js_object = RawJS('window.something.get_some_object()')

class MyComponent(flx.JsComponent):

    @flx.reaction('some.event')
    def handler(self, *events):
        my_js_object.bar()

One can also assign __pscript__ = True to a module to make Flexx transpile a module as a whole. A downside is that (at the moment) such modules cannot use import.

Handling assets and data

Asset management

When writing code that relies on a certain JS or CSS library, that library can be loaded in the client by associating it with the module that needs it. Flexx will then automatically (and only) load it when code from that module is used in JS. Flexx itself uses this mechanism is some widgets e.g. for Leaflet maps or the CodeMirror editor.

# Associate asset
flx.assets.associate_asset(__name__, 'mydep.js', js_code)

# Sometimes a more lightweight *remote* asset is prefered
flx.assets.associate_asset(__name__, 'http://some.cdn/lib.css')

# Create component (or Widget) that needs the asset at the client
class MyComponent(flx.JsComponent):
    ....

It is also possible to provide assets that are not automatically loaded on the main app page, e.g. for sub-pages or web workers:

# Register asset
asset_url = flx.assets.add_shared_asset('mydep.js', js_code)
Data management

Data can be provided per session or shared between sessions:

# Add session-specific data. You need to call this inside a PyComponent
# and use the link in the JS component that needs the data.
link = my_component.session.add_data('some_name.png', binary_blob)

# Add shared data. This can be called at the module level.
link = flx.assets.add_shared_data('some_name.png', binary_blob)

Note that it is also possible to send data from Python to JS via an action invokation (the data is send over the websocket in this case). The latter also works for numpy arrays.

Sensible usage patterns

This chapter discusses some patterns that can be adopted to structure your applications. Which kind of pattern(s) make sense depends on the use-case and personal preference. Also, don’t be dogmatic, these are only intended to give a sensible direction.

The observer pattern

The idea of the observer pattern is that observers keep track of (the state of) other objects, and that these objects themselves are agnostic about what it’s tracked by. For example, in a music player, instead of writing code to update the window-title inside the function that starts a song, there would be a concept of a “current song”, and the window would listen for changes to the current song to update the title when it changes.

This is a pattern worth following in almost all sceneario’s. Flexx reaction system was designed to make this as natural as possible. This idea is also at the core of the next pattern.

Use of a central data store

When one part of your application needs to react to something in another part of your application, it is possible to create a reaction that connects to the event in question directly. However, as your app grows, this can start to feel like spaghetti.

It might be better to define a central place that represents the state of the application, e.g. on the root component, or on a separate object that can easily be accessed from the root component. In this way, all parts of your application stay self-contained and can be updated/replaced without the need for changes in other places of the application.

from flexx import flx

class UserInput(flx.Widget):

    def init(self):
        with flx.VBox():
            self.edit = flx.LineEdit(placeholder_text='Your name')
            flx.Widget(flex=1)

    @flx.reaction('edit.user_done')
    def update_user(self, *events):
        self.root.store.set_username(self.edit.text)

class SomeInfoWidget(flx.Widget):

    def init(self):
        with flx.FormLayout():
            flx.Label(title='name:', text=lambda: self.root.store.username)
            flx.Widget(flex=1)

class Store(flx.JsComponent):

    username = flx.StringProp(settable=True)

class Example(flx.Widget):

    store = flx.ComponentProp()

    def init(self):

        # Create our store instance
        self._mutate_store(Store())

        # Imagine this being a large application with many sub-widgets,
        # and the UserInput and SomeInfoWidget being used somewhere inside it.
        with flx.HSplit():
            UserInput()
            flx.Widget(style='background:#eee;')
            SomeInfoWidget()
Lean towards Python

If your application is a Python app that just happens to use Flexx instead of Qt, you may try to stay in Python-land as much as possible by making use of PyWidget and PyComponent.

We repeat the above example, but now most of the logic will happen in Python. (The result will be nearly the same, but if we’d display it on this page it would not be interactive, because there is no Python.)

from flexx import flx

class UserInput(flx.PyWidget):

    def init(self):
        with flx.VBox():
            self.edit = flx.LineEdit(placeholder_text='Your name')
            flx.Widget(flex=1)

    @flx.reaction('edit.user_done')
    def update_user(self, *events):
        self.root.store.set_username(self.edit.text)

class SomeInfoWidget(flx.PyWidget):

    def init(self):
        with flx.FormLayout():
            self.label = flx.Label(title='name:')
            flx.Widget(flex=1)

    @flx.reaction
    def update_label(self):
        self.label.set_text(self.root.store.username)

class Store(flx.PyComponent):

    username = flx.StringProp(settable=True)

class Example(flx.PyWidget):

    store = flx.ComponentProp()

    def init(self):

        # Create our store instance
        self._mutate_store(Store())

        # Imagine this being a large application with many sub-widgets,
        # and the UserInput and SomeInfoWidget being used somewhere inside it.
        with flx.HSplit():
            UserInput()
            flx.Widget(style='background:#eee;')
            SomeInfoWidget()
Only JS

If you want to be able to publish your app to the web as a static page, you will need to base it completely on JsComponents.

For web apps that serve many users and/or is a long-running process, it is recommended to use Flexx to build the JS-only front-end, and implement the back-end using a classic http framework (such as aiohttp, flask, asgineer, etc.). The next chapter goes into detail how to do this.

Clear separation

If your use-case falls somewhere in between the two above patterns, you’ll use more of a mix of PyComponents and JsComponents.

In general, it is good to clearly separate the Python logic from the JavaScript logic. E.g. by implementing the whole UI using widgets and JsComponents, and implementing the “business logic” using one or more PyComponents.

Ways to run a Flexx app

Run as a desktop app

During development, and when creating a web app, you will want to use launch():

app = flx.App(MainComponent)
app.launch('app')  # to run as a desktop app
# app.launch('browser')  # to open in the browser
flx.run()  # mainloop will exit when the app is closed
Flexx in Jupyter

Flexx can be used interactively from the Jupyter notebook. Use flx.init_notebook() which will inject the necessary JS and CSS. Also use %gui asyncio to enable the Flexx event system. Simple widgets (e.g. buttons) will display just fine, but for other widgets you might want to use SomeWidget(minsize=300) to specify a minimum size.

As of yet, Flexx does not work in JupyterLab.

Serve as a web app

It is possible to serve Flexx apps and allow multiple people to connect. Flexx provides ways to have all connected clients interact with each-other, see e.g. the chatroom and colab-painting examples.

app = flx.App(MainComponent)
app.serve('foo')  # Serve at http://domain.com/foo
app.serve('')  # Serve at http://domain.com/
flx.start()  # Keep serving "forever"

Some details:

Each server process hosts on a single URL (domain+port), but can serve multiple applications (via different paths). Each process uses one tornado IOLoop, and exactly one Tornado Application object. Flexx’ event loop is based on asyncio (Tornado is set up to integrate with asyncio).

When a client connects to the server, it is served an HTML page, which contains the information needed to connect to a websocket. From there, all communication happens over this websocket, including the definition of CSS and JavaScript modules.

The overhead for each connection is larger than that of classic http frameworks, and the complexity of the Python-JS interaction are a potential risk for security issues and memory leaks. For the Flexx demo page we run the server in an auto-restarting Docker container with applied memory limits.

Export to a static web page

Any app can be exported to its raw assets. However, apps that rely on a PyComponent won’t work correctly, obviously. Exporting to a single file won’t work for apps that use session/shared data.

app = flx.App(MainComponent)
app.export('~/myapp/index.html')  # creates a few files
app.export('~/myapp.html', link=0)  # creates a single file
Serve as a proper web app

When creating an app that will run on a long-running server and/or will be accessed by many clients, you may want to implement the server using an http framework such as aiohttp, flask, etc.

You can first dump the assets to a dictionary, which you can then serve using your library of choice. See the serve_with_ examples for complete implementations.

It’s worth noting that if App.serve(), flx.run() and flx.start() are not called, Flexx won’t even import Tornado (and we have a test to make sure that it stays that way). This makes it feasible to generate the client-side of a website with Flexx when the server starts up.

app = flx.App(MainComponent)
assets = app.dump('index.html')

...  # serve assets with flask/aiohttp/tornado/vibora/django/...

Debugging

Debugging can be hard. Especially if your app runs partly in Python and partly in JavaScript. Here are some tips that may help.

Be clear about where the offending code is running

This may sound obvious, but it’s important to do this before moving on. Sometimes the bug presents itself due to the interaction between Python and JavaScript. The same rules apply, but you’d have to dig into both ends.

Digging in the Python side

All the normal Python debugging tips apply here. GUI applications run in an event loop, which makes debugging harder. E.g. using breakpoints is not always possible. A strategically placed print() can sometimes help a lot.

It can be worthwhile to run the app in an IDE that can integrate the event loop, so that you can use a Python REPL to inspect an application while it is running. E.g. with Pyzo with asyncio GUI integration.

Digging in the JavaScript side

People unfamiliar with web technology might be hesitant to try and debug using the browser, but you’ll be amazed by how awesome the debugging tools of Firefox and Chrome are!

Firstly, hit the F12 key to pop up the developer console. From here, there are a few things that you can do:

You can run JavaScript commands to inspect and control your app. There is a global flexx object, and you can get access to all components using flexx.s1.instances.xxx. Use autocompletion to select the component you need. You can inspect the component’s properties and invoke its actions.

If the problem is related to appearance, you can activate the element selector and then click on the element on the page to select it. This will allow you to inspect the HTML DOM structure and inspect the CSS of all elements.

End

This concluses the Flexx guide. Have fun!

Reference

Widgets reference

This is a list of all widget classes provided by flexx.ui. The Widget class is the base class of all widgets.

Base widget:

Layouts:

Widgets:

Widget

Provides the base Widget and PyWidget classes.

When subclassing a Widget to create a compound widget (i.e. a widget that contains other widgets), initialize the child widgets inside the init() method. That method is called while the widget is the current widget; any widgets instantiated inside it will automatically become children.

from flexx import flx

class Example(flx.Widget):
    def init(self):
        super().init()

        flx.Button(text='foo')
        flx.Button(text='bar')

One can also use a widget as a context manager (i.e. using the with statement) to create child widgets. This is particularly useful for layout widgets (like HBox).

from flexx import flx

class Example(flx.Widget):
    def init(self):
        super().init()

        with flx.HBox():
            flx.Button(flex=1, text='foo')
            flx.Button(flex=2, text='bar')

In the above two examples, the newly created classes subclass from Widget and are thus a JsComponent (i.e. operate in JS). This may be what you want if you are aiming for a UI that can be exported for the web. If, however, you are developing a desktop application, consider subclassing from PyWidget instead, which will make your widget operate in Python.

It is also possible to create custom low-level widgets by implementing _render_dom(), resulting in a declarative “react-like” (but less Pythonic) approach. It returns a virtual DOM that is used to update/replace the real browser DOM.

from flexx import flx

class Example(flx.Widget):

    count = flx.IntProp()

    def _render_dom(self):
        # This method automatically gets called when any of the used
        # properties (only count, in this case) changes.
        return flx.create_element('div', {},
            flx.create_element('button',
                               {'onclick': self.increase_count},
                               '+'),
            flx.create_element('span',
                               {'style.background': '#afa'},
                               str(self.count)),
            )

    @flx.action
    def increase_count(self):
        self._mutate_count(self.count + 1)

flexx.ui.create_element(type, props=None, *children)

Convenience function to create a dictionary to represent a virtual DOM node. Intended for use inside Widget._render_dom().

The content of the widget may be given as a series/list of child nodes (virtual or real), and strings. Strings are converted to text nodes. To insert raw HTML, use the innerHTML prop, but be careful not to include user-defined text, as this may introduce openings for XSS attacks.

The returned dictionary has three fields: type, props, children.

class flexx.ui.PyWidget(*args, **kwargs)

Inherits from: PyComponent

A base class that can be used to create compound widgets that operate in Python. This enables an approach for building GUI’s in a Pythonic way: by only using JS components (actual widgets) all code that you write can be Python code.

Internally, objects of this class create a sub-widget (a flx.Widget instance). When the object is used as a context manager, the sub-widget will also become active. Further, this class gets attributes for all the sub-widget’s properties, actions, and emitters. In effect, this class can be used like a normal flx.Widget (but in Python).

JS

alias of PyWidget

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

Inherits from: JsComponent

Base widget class (a Component in JS wrapping an HTML element).

When subclassing a Widget, it is recommended to not implement the __init__() method, but instead implement init() for compound (higher-level) widgets, and _create_dom() for low-level widgets.

Widgets can be styled using CSS by implementing a string class attribute named CSS. A widget’s node has a CSS-class-name corresponding to its Python class (and its base classes), following the scheme flx-WidgetClassName.

All widgets have a node and outernode attribute (only accessible in JavaScript), representing the DOM element(s) that represent the widget. For most types of widgets, node is equal to outernode. For the Widget class, this is simply a <div> element. If you don’t understand what this is about, don’t worry; you won’t need it unless you are creating your own low-level widgets. See _create_dom() for details.

When implementing your own widget class, the class attribute DEFAULT_MIN_SIZE can be set to specify a sensible minimum size.

properties: capture_mouse, children, container, css_class, flex, icon, maxsize, minsize, minsize_from_children, parent, size, tabindex, title

emitters: key_down, key_press, key_up, pointer_cancel, pointer_click, pointer_double_click, pointer_down, pointer_move, pointer_up, pointer_wheel

actions: apply_style, check_real_size, set_capture_mouse, set_container, set_css_class, set_flex, set_icon, set_maxsize, set_minsize, set_minsize_from_children, set_parent, set_tabindex, set_title

methods: _create_dom, _render_dom, dispose, init

_create_dom()

Create DOM node(s) for this widget.

This method must return two (real or virtual) DOM nodes which will be available as self.outernode and self.node respectively. If a single node is given, it is used for both values. These attributes must remain unchanged throughout the lifetime of a widget. This method can be overloaded in subclasses.

Most widgets have the same value for node and outernode. However, in some cases it helps to distinguish between the semantic “actual node” and a wrapper. E.g. Flexx uses it to properly layout the CanvasWidget and TreeItem. Internally, Flexx uses the node attribute for tab-index, and binding to mouse/touch/scroll/key events. If your outernode already semantically represents your widget, you should probably just use that.

_render_dom()

Update the content of the DOM for this widget.

This method must return a DOM structure consisting of (a mix of) virtual nodes, real nodes and strings. The widget will use this structure to update the real DOM in a relatively efficient manner (new nodes are only (re)created if needed). The root element must match the type of this widget’s outernode. This method may also return a list to apply as the root node’s children.

Note that this method is called from an implicit reaction: it will auto-connect to any properties that are accessed. Combined with the above, this allows for a very declarative way to write widgets.

Virtual nodes are represented as dicts with fields “type”, “props” and “children”. Children is a list consisting of real dom nodes, virtual nodes, and strings. Strings are converted to TextNode (XSS safe). The create_element() function makes it easy to create virtual nodes.

The default _render_dom() method simply places the outer node of the child widgets as the content of this DOM node, while preserving nodes that do not represent a widget. Overload as needed.

apply_style(style)

action – Apply CSS style to this widget object. e.g. "background: #f00; color: #0f0;". If the given value is a dict, its key-value pairs are converted to a CSS style string.

Initial styling can also be given in a property-like fashion: MyWidget(style='background:red;')

For static styling it is often better to define a CSS class attribute and/or use css_class.

capture_mouse

IntProp – To what extend the mouse is “captured”.

  • If 0, the mouse is not captured, and move events are only emitted when the mouse is pressed down (not recommended).
  • If 1 (default) the mouse is captured when pressed down, so move and up events are received also when the mouse is outside the widget.
  • If 2, move events are also emitted when the mouse is not pressed down and inside the widget.
check_real_size()

action – Check whether the current size has changed. It should usually not be necessary to invoke this action, since a widget does so by itself, but it some situations the widget may not be aware of possible size changes.

children

LocalProperty – The child widgets of this widget. This property is not settable and only present in JavaScript.

container

StringProp – The id of the DOM element that contains this widget if parent is None. Use ‘body’ to make this widget the root.

css_class

StringProp – The extra CSS class name to asign to the DOM element. Spaces can be used to delimit multiple names. Note that the DOM element already has a css class-name corresponding to its class (e.g. ‘flx-Widget) and all its superclasses.

dispose()

Overloaded version of dispose() that disposes any child widgets.

flex

FloatPairProp – How much space this widget takes (relative to the other widgets) when contained in a flexible layout such as HBox, HFix, HSplit or FormLayout. A flex of 0 means to take the minimum size. Flex is a two-element tuple, but both values can be specified at once by specifying a scalar.

icon

LocalProperty – The icon for this widget. This is used is some widgets classes, and is used as the app’s icon if this is the main widget. It is settable from Python, but only present in JavaScript.

init()

Overload this to initialize a custom widget. It’s preferred to use this instead of __init__(), because it gets called at a better moment in the instantiation of the widget.

This method receives any positional arguments that were passed to the constructor. When called, this widget is the current parent.

key_down(e)

emitter – Event emitted when a key is pressed down while this widget has focus. A key event has the following attributes:

  • key: the character corresponding to the key being pressed, or
    a key name like “Escape”, “Alt”, “Enter”.
  • modifiers: list of strings “Alt”, “Shift”, “Ctrl”, “Meta” for
    modifier keys pressed down at the time of the event.

A browser may associate certain actions with certain key presses. If this browser action is unwanted, it can be disabled by overloading this emitter:

@event.emitter
def key_down(self, e):
    # Prevent browser's default reaction to function keys
    ev = super().key_press(e)
    if ev.key.startswith('F'):
        e.preventDefault()
    return ev
key_press(e)

emitter – Event emitted when a key is released after pressing down, in theory. In contast to key_down, this event does not fire for the pressing of modifier keys, and some browsers will also not fire for the arrow keys, backspace, etc. See key_down for details.

key_up(e)

emitter – Event emitted when a key is released while this widget has focus. See key_down for details.

maxsize

FloatPairProp – The user-defined maximum size (width, height) of this widget in pixels. Note that using “max-width” or “max-height” in apply_style(). (and in the style kwarg) also set this property. Maximum sizes set in CSS are ignored.

minsize

FloatPairProp – The user-defined minimum size (width, height) of this widget in pixels. The default value differs per widget (Widget.DEFAULT_MIN_SIZE). Note that using “min-width” or “min-height” in apply_style(). (and in the style kwarg) also set this property. Minimum sizes set in CSS are ignored.

minsize_from_children

BoolProp – Whether the children are taken into account to calculate this widget’s size constraints. Default True: both the minsize of this widget and the size constraints of its children (plus spacing and padding for layout widgets) are used to calculate the size constraints for this widget.

Set to False to prevent the content in this widget to affect the parent’s layout, e.g. to allow fully collapsing this widget when the parent is a splitter. If this widget has a lot of content, you may want to combine with style='overflow-y: auto'.

parent

ComponentProp – The parent widget, or None if it has no parent. Setting this property will update the “children” property of the old and new parent.

pointer_cancel(e)

emitter – Event emitted when the mouse/touch is lost, e.g. the window becomes inactive during a drag. This only seem to work well for touch events in most browsers.

See pointer_down() for a description of the event object.

pointer_click(e)

emitter – Event emitted when mouse-button/touchpad/screen is clicked.

See pointer_down() for a description of the event object.

pointer_double_click(e)

emitter – Event emitted when mouse-button/touchpad/screen is double-clicked.

See pointer_down() for a description of the event object.

pointer_down(e)

emitter – Event emitted when mouse-button/touchpad/screen is pressed.

All pointer events have the following attributes:

  • pos: the pointer position, in pixels, relative to this widget
  • page_pos: the pointer position relative to the page
  • button: what mouse button the event is about, 1, 2, 3 are left, right,
    middle, respectively. 0 indicates no button.
  • buttons: what buttons were pressed at the time of the event.
  • modifiers: list of strings “Alt”, “Shift”, “Ctrl”, “Meta” for
    modifier keys pressed down at the time of the event.
  • touches: a dictionary that maps touch_id’s to (x, y, force) tuples.
    For mouse events touch_id is -1 and force is 1.

A note about the relation with JavaScript events: although the name might suggest that this makes use of JS pointer events, this is not the case; Flexx captures both mouse events and touch events and exposes both as its own “pointer event”. In effect, it works better on mobile devices, and has multi-touch support.

pointer_move(e)

emitter – Event fired when the mouse or a touch is moved.

See pointer_down for details.

pointer_up(e)

emitter – Event emitted when mouse-button/touchpad/screen is released.

See pointer_down() for a description of the event object.

pointer_wheel(e)

emitter – Event emitted when the mouse wheel is used.

See pointer_down() for a description of the event object. Additional event attributes:

  • hscroll: amount of scrolling in horizontal direction
  • vscroll: amount of scrolling in vertical direction
set_capture_mouse(*val)

action – Setter for the ‘capture_mouse’ property.

set_container(*val)

action – Setter for the ‘container’ property.

set_css_class(*val)

action – Setter for the ‘css_class’ property.

set_flex(*val)

action – Setter for the ‘flex’ property.

set_icon(val)

action – Set the icon for this widget. This is used is some widgets classes, and is used as the app’s icon if this is the main widget. It is settable from Python, but the property is not available in Python.

Can be a url, a relative url to a shared asset, or a base64 encoded image. In the future this may also support names in icon packs like FontAwesome.

set_maxsize(*val)

action – Setter for the ‘maxsize’ property.

set_minsize(*val)

action – Setter for the ‘minsize’ property.

set_minsize_from_children(*val)

action – Setter for the ‘minsize_from_children’ property.

set_parent(parent, pos=None)

action – Set the parent widget (can be None). This action also mutates the childen of the old and new parent.

set_tabindex(*val)

action – Setter for the ‘tabindex’ property.

set_title(*val)

action – Setter for the ‘title’ property.

size

FloatPairProp – The actual size of the widget (readonly). Flexx tries to keep this value up-to-date, but in e.g. a box layout, a change in a Button’s text can change the size of sibling widgets.

tabindex

IntProp – The index used to determine widget order when the user iterates through the widgets using tab. This also determines whether a widget is able to receive key events. Flexx automatically sets this property when it should emit key events. Effect of possible values on underlying DOM element:

  • -2: element cannot have focus unless its a special element like
    a link or form control (default).
  • -1: element can have focus, but is not reachable via tab.
  • 0: element can have focus, and is reachable via tab in the order
    at which the element is defined.
  • 1 and up: element can have focus, and the tab-order is determined
    by the value of tabindex.
title

StringProp – The string title of this widget. This is used to mark the widget in e.g. a tab layout or form layout, and is used as the app’s title if this is the main widget.

FormLayout

Layout a series of (input) widgets in a form. Example:

from flexx import ui

class Example(ui.Widget):
    def init(self):
        with ui.FormLayout():
            self.b1 = ui.LineEdit(title='Name:')
            self.b2 = ui.LineEdit(title="Age:")
            self.b3 = ui.LineEdit(title="Favorite color:")
            ui.Widget(flex=1)  # Spacing

Also see examples: themed_form.py.


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

Inherits from: Layout

A layout widget that vertically alligns its child widgets in a form. A label is placed to the left of each widget (based on the widget’s title).

The node of this widget is a <div>, which lays out it’s child widgets and their labels using CSS grid.

JS

alias of FormLayout

Grid layout.

Layout a series of widgets in a grid. The grid has a specified number of columns. Example:

from flexx import flx

class Example(flx.Widget):
    def init(self):
        with flx.HSplit():
            with flx.GridLayout(ncolumns=3):
                flx.Button(text='A')
                flx.Button(text='B')
                flx.Button(text='C')
                flx.Button(text='D')
                flx.Button(text='E')
                flx.Button(text='F')

            with flx.GridLayout(ncolumns=2):
                flx.Button(text='A', flex=(1, 1))  # Set flex for 1st row and col
                flx.Button(text='B', flex=(2, 1))  # Set flex for 2nd col
                flx.Button(text='C', flex=(1, 1))  # Set flex for 2nd row
                flx.Button(text='D')
                flx.Button(text='E', flex=(1, 2))  # Set flex for 3d row
                flx.Button(text='F')

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

Inherits from: Layout

A layout widget that places its children in a grid with a certain number of columns. The flex values of the children in the first row determine the sizing of the columns. The flex values of the first child of each row determine the sizing of the rows.

The node of this widget is a <div>, which lays out it’s child widgets and their labels using CSS grid.

properties: ncolumns

actions: set_ncolumns

ncolumns

IntProp – The number of columns of the grid.

set_ncolumns(*val)

action – Setter for the ‘ncolumns’ property.

HVLayout

The HVLayout and its subclasses provide a simple mechanism to horizontally or vertically stack child widgets. This can be done in different modes: box mode is suited for aligning content where natural size matters. The fix mode and split mode are more suited for high-level layout. See the HVLayout class for details.

Interactive Box layout example:

from flexx import app, event, ui

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)

    @event.reaction('b1.pointer_down')
    def _to_horizontal(self, *events):
        self.set_orientation('h')

    @event.reaction('b2.pointer_down')
    def _to_vertical(self, *events):
        self.set_orientation('v')

    @event.reaction('b3.pointer_down')
    def _to_horizontal_rev(self, *events):
        self.set_orientation('hr')

    @event.reaction('b4.pointer_down')
    def _to_vertical_r(self, *events):
        self.set_orientation('vr')

Also see examples: app_layout.py, splitters.py, box_vs_fix_layout.py, mondriaan.py.


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

Inherits from: Layout

A layout widget to distribute child widgets horizontally or vertically.

This is a versatile layout class which can operate in different orientations (horizontal, vertical, reversed), and in different modes:

In ‘fix’ mode, all available space is simply distributed corresponding to the children’s flex values. This can be convenient to e.g. split a layout in two halves.

In ‘box’ mode, each widget gets at least its natural size (if available), and any additional space is distributed corresponding to the children’s flex values. This is convenient for low-level layout of widgets, e.g. to align one or more buttons. It is common to use flex values of zero to give widgets just the size that they needs and use an empty widget with a flex of 1 to fill up any remaining space. This mode is based on CSS flexbox.

In ‘split’ mode, all available space is initially distributed corresponding to the children’s flex values. The splitters between the child widgets can be dragged by the user and positioned via an action. This is useful to give the user more control over the (high-level) layout.

In all modes, the layout is constrained by the minimum and maximum size of the child widgets (as set via style/CSS). Note that flexbox (and thus box mode) may not honour min/max sizes of widgets in child layouts.

Note that widgets with a flex value of zero may collapse if used inside a fix/split layout, or in a box layout but lacking a natural size. This can be resolved by assigning a minimum width/height to the widget. The exception is if all child widgets have a flex value of zero, in which case the available space is divided equally.

The node of this widget is a <div>. The outer nodes of the child widgets are layed-out using JavaScript of CSS, depending on the mode.

Also see the convenience classes: HFix, VFix, HBox, VBox, HSplit, VSplit.

properties: mode, orientation, padding, spacing, splitter_positions

emitters: user_splitter_positions

actions: set_from_flex_values, set_mode, set_orientation, set_padding, set_spacing, set_splitter_positions

mode

EnumProp – The mode in which this layout operates:

  • ‘BOX’: (default) each widget gets at least its natural size, and additional space is distributed corresponding to the flex values.
  • ‘FIX’: all available space is distributed corresponding to the flex values.
  • ‘SPLIT’: available space is initially distributed correspondong to the flex values, and can be modified by the user by dragging the splitters.
orientation

OrientationProp – The orientation of the child widgets. ‘h’ or ‘v’ for horizontal and vertical, or their reversed variants ‘hr’ and ‘vr’. Settable with values: 0, 1, ‘h’, ‘v’, ‘hr’, ‘vr’, ‘horizontal’, ‘vertical’, ‘left-to-right’, ‘right-to-left’, ‘top-to-bottom’, ‘bottom-to-top’ (insensitive to case and use of dashes).

padding

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

set_from_flex_values()

action – Set the divider positions corresponding to the children’s flex values. Only has a visual effect in split-mode.

set_mode(*val)

action – Setter for the ‘mode’ property.

set_orientation(*val)

action – Setter for the ‘orientation’ property.

set_padding(*val)

action – Setter for the ‘padding’ property.

set_spacing(*val)

action – Setter for the ‘spacing’ property.

set_splitter_positions(*positions)

action – Set relative splitter posisions (None or values between 0 and 1). Only usable in split-mode.

spacing

FloatProp – The space between two child elements (in pixels).

splitter_positions

LocalProperty – The preferred relative positions of the splitters. The actual positions are subject to minsize and maxsize constraints (and natural sizes for box-mode).

user_splitter_positions(*positions)

emitter – Event emitted when the splitter is positioned by the user. The event has a positions attribute.

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

Inherits from: HVLayout

Horizontal layout that tries to give each widget its natural size and distributes any remaining space corresponding to the widget’s flex values. (I.e. an HVLayout with orientation ‘h’ and mode ‘box’.)

JS

alias of HBox

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

Inherits from: HVLayout

Horizontal layout that distributes the available space corresponding to the widget’s flex values. (I.e. an HVLayout with orientation ‘h’ and mode ‘fix’.)

JS

alias of HFix

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

Inherits from: HVLayout

Horizontal layout that initially distributes the available space corresponding to the widget’s flex values, and has draggable splitters. By default, this layout has a slightly larger spacing between the widgets. (I.e. an HVLayout with orientation ‘h’ and mode ‘split’.)

JS

alias of HSplit

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

Inherits from: HVLayout

Vertical layout that tries to give each widget its natural size and distributes any remaining space corresponding to the widget’s flex values. (I.e. an HVLayout with orientation ‘v’ and mode ‘box’.)

JS

alias of VBox

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

Inherits from: HVLayout

Vertical layout that distributes the available space corresponding to the widget’s flex values. (I.e. an HVLayout with orientation ‘v’ and mode ‘fix’.)

JS

alias of VFix

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

Inherits from: HVLayout

Vertical layout that initially distributes the available space corresponding to the widget’s flex values, and has draggable splitters. By default, this layout has a slightly larger spacing between the widgets. (I.e. an HVLayout with orientation ‘v’ and mode ‘split’.)

JS

alias of VSplit

Layout

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

Inherits from: Widget

Abstract class for widgets that layout their child widgets.

JS

alias of Layout

PinboardLayout

Free positioning (absolute or relative) of child widgets. Example:

from flexx import app, ui

class Example(ui.Widget):

    def init(self):

        with ui.PinboardLayout():
            self.b1 = ui.Button(text='Stuck at (20, 20)',
                                style='left:20px; top:20px;')
            self.b2 = ui.Button(text='Dynamic at (30%, 30%)',
                                style='left:30%; top:30%; height:100px;')
            self.b3 = ui.Button(text='Dynamic at (50%, 70%)',
                                style='left:50%; top:70%;')

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

Inherits from: Layout

Unconstrained absolute and relative positioning of child widgets.

This simply places child widgets using CSS “position: absolute”. Use CSS “left” and “top” to position the widget (using a “px” or “%” suffix). Optionally “width”, “height”, “right” and “bottom” can also be used.

The node of this widget is a <div>.

JS

alias of PinboardLayout

StackLayout

Show only one child at any time. Example:

from flexx import app, event, ui

class Example(ui.Widget):

    def init(self):
        with ui.HBox():
            with ui.VBox():
                self.buta = ui.Button(text='red')
                self.butb = ui.Button(text='green')
                self.butc = ui.Button(text='blue')
                ui.Widget(flex=1)  # space filler
            with ui.StackLayout(flex=1) as self.stack:
                self.buta.w = ui.Widget(style='background:#a00;')
                self.butb.w = ui.Widget(style='background:#0a0;')
                self.butc.w = ui.Widget(style='background:#00a;')

    @event.reaction('buta.pointer_down', 'butb.pointer_down', 'butc.pointer_down')
    def _stacked_current(self, *events):
        button = events[-1].source
        self.stack.set_current(button.w)

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

Inherits from: Layout

A layout widget which shows only one of its children at a time.

The node of this widget is a <div>.

properties: current

actions: set_current

current

ComponentProp – The currently shown widget (or None).

set_current(current)

action – Setter for current widget. Can also set using an integer index.

TabLayout

A StackLayout subclass that uses tabs to let the user select a child widget.

Example:

from flexx import app, ui

class Example(ui.Widget):
    def init(self):
        with ui.TabLayout() as self.t:
            self.a = ui.Widget(title='red', style='background:#a00;')
            self.b = ui.Widget(title='green', style='background:#0a0;')
            self.c = ui.Widget(title='blue', style='background:#00a;')

Also see examples: demo.py.


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

Inherits from: StackLayout

A StackLayout which provides a tabbar for selecting the current widget. The title of each child widget is used for the tab label.

The node of this widget is a <div>. The visible child widget fills the entire area of this element, except for a small area at the top where the tab-bar is shown.

emitters: user_current

user_current(current)

emitter – Event emitted when the user selects a tab. Can be used to distinguish user-invoked from programatically-invoked tab changes. Has old_value and new_value attributes.

Filebrowser

class flexx.ui.FileBrowserWidget(*args, **kwargs)

Inherits from: PyWidget

A PyWidget to browse the file system. Experimental. This could be the basis for a file open/save dialog.

properties: path

methods: selected, set_path

path

StringProp – The currectly shown directory (settable). Defaults to the user directory.

selected

emitter – Emitter that fires when the user selects a file. The emitted event has a “filename” attribute.

set_path

action – Set the current path. If an invalid directory is given, the path is not changed. The given path can be absolute, or relative to the current path.

BokehWidget

Show Bokeh plots in Flexx. Example:

import numpy as np
from bokeh.plotting import figure
from flexx import app, event, ui

x = np.linspace(0, 6, 50)

p1 = figure()
p1.line(x, np.sin(x))

p2 = figure()
p2.line(x, np.cos(x))

class Example(app.PyComponent):
    def init(self):
        with ui.HSplit():
            ui.BokehWidget.from_plot(p1)
            ui.BokehWidget.from_plot(p2)

Also see examples: bokehdemo.py.


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

Inherits from: Widget

A widget that shows a Bokeh plot object.

For Bokeh 0.12 and up. The plot’s sizing_mode property is set to stretch_both unless it was set to something other than fixed. Other responsive modes are ‘scale_width’, ‘scale_height’ and ‘scale_both`, which all keep aspect ratio while being responsive in a certain direction.

This widget is, like all widgets, a JsComponent; it lives in the browser, while the Bokeh plot is a Python object. Therefore we cannot simply use a property to set the plot. Use ui.BokehWidget.from_plot(plot) to instantiate the widget from Python.

attributes: plot

actions: set_plot_components

plot

attribute – The JS-side of the Bokeh plot object.

set_plot_components(d)

action – Set the plot using its script/html components.

Button classes

Simple example:

b = ui.Button(text="Push me")

Also see examples: buttons.py.


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

Inherits from: Widget

Abstract button class.

properties: checked, disabled, text

emitters: user_checked

actions: set_checked, set_disabled, set_text

checked

BoolProp – Whether the button is checked.

disabled

BoolProp – Whether the button is disabled.

set_checked(*val)

action – Setter for the ‘checked’ property.

set_disabled(*val)

action – Setter for the ‘disabled’ property.

set_text(*val)

action – Setter for the ‘text’ property.

text

StringProp – The text on the button.

user_checked(checked)

emitter – Event emitted when the user (un)checks this button. Has old_value and new_value attributes.

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

Inherits from: BaseButton

A push button.

The node of this widget is a <button>.

JS

alias of Button

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

Inherits from: BaseButton

A checkbox button.

The outernode of this widget is a <label>, and the node a checkbox <input>.

JS

alias of CheckBox

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

Inherits from: BaseButton

A radio button. Of any group of radio buttons that share the same parent, only one can be active.

The outernode of this widget is a <label>, and the node a radio <input>.

emitters: pointer_click

pointer_click(e)

emitter – This method is called on JS a click event. We first update the checked properties, and then emit the Flexx click event. That way, one can connect to the click event and have an up-to-date checked props (even on Py).

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

Inherits from: BaseButton

A button that can be toggled. It behaves like a checkbox, while looking more like a regular button.

The node of this widget is a <button>.

JS

alias of ToggleButton

CanvasWidget

The canvas can be used for specialized graphics of many sorts. It can provide either a WebGL context or a 2d context as in the example below:

from flexx import app, event, ui

class Example(ui.CanvasWidget):

    def init(self):
        super().init()
        self.ctx = self.node.getContext('2d')
        self.set_capture_mouse(1)
        self._last_pos = (0, 0)

    @event.reaction('pointer_move')
    def on_move(self, *events):
        for ev in events:
            self.ctx.beginPath()
            self.ctx.strokeStyle = '#080'
            self.ctx.lineWidth = 3
            self.ctx.lineCap = 'round'
            self.ctx.moveTo(*self._last_pos)
            self.ctx.lineTo(*ev.pos)
            self.ctx.stroke()
            self._last_pos = ev.pos

    @event.reaction('pointer_down')
    def on_down(self, *events):
        self._last_pos = events[-1].pos

Also see example: drawing.py, splines.py.


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

Inherits from: Widget

A widget that provides an HTML5 canvas. The canvas is scaled with the available space. Use self.node.getContext('2d') or self.node.getContext('webgl') in the init() method to get a contex to perform the actual drawing.

The node of this widget is a <canvas> wrapped in a <div> (the outernode) to handle sizing.

properties: capture_wheel

actions: set_capture_wheel

capture_wheel

BoolProp – Whether the wheel event is “captured”, i.e. not propagated to result into scrolling of the parent widget (or page). If True, if no scrolling must have been performed outside of the widget for about half a second in order for the widget to capture scroll events.

set_capture_wheel(*val)

action – Setter for the ‘capture_wheel’ property.

ColorSelectWidget
from flexx import event, ui

class Example(ui.Widget):

    def init(self):
        self.c = ui.ColorSelectWidget()

    @event.reaction
    def _color_changed(self):
        self.node.style.background = self.c.color.hex

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

Inherits from: Widget

A widget used to select a color.

The node of this widget is an <input> element of type color. This is supported at least on Firefox and Chrome, but not on IE.

properties: color, disabled

emitters: user_color

actions: set_color, set_disabled

color

ColorProp – The currently selected color.

disabled

BoolProp – Whether the color select is disabled.

set_color(*val)

action – Setter for the ‘color’ property.

set_disabled(*val)

action – Setter for the ‘disabled’ property.

user_color(color)

emitter – Event emitted when the user changes the color. Has old_value and new_value attributes.

Dropdown widgets
from flexx import app, event, ui

class Example(ui.Widget):

    def init(self):
        self.combo = ui.ComboBox(editable=True,
                                 options=('foo', 'bar', 'spaaaaaaaaam', 'eggs'))
        self.label = ui.Label()

    @event.reaction
    def update_label(self):
        text = 'Combobox text: ' + self.combo.text
        if self.combo.selected_index is not None:
            text += ' (index %i)' % self.combo.selected_index
        self.label.set_text(text)

Also see examples: control_with_keys.py.


class flexx.ui.widgets._dropdown.BaseDropdown(*init_args, **kwargs)

Inherits from: Widget

Base class for drop-down-like widgets.

actions: expand

expand()

action – Expand the dropdown and give it focus, so that it can be used with the up/down keys.

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

Inherits from: BaseDropdown

The Combobox is a combination of a button and a popup list, optionally with an editable text. It can be used to select among a set of options in a more compact manner than a TreeWidget would. Optionally, the text of the combobox can be edited.

It is generally good practive to react to user_selected to detect user interaction, and react to text, selected_key or selected_index to keep track of all kinds of (incl. programatic) interaction .

When the combobox is expanded, the arrow keys can be used to select an item, and it can be made current by pressing Enter or spacebar. Escape can be used to collapse the combobox.

The node of this widget is a <span> with some child elements and quite a bit of CSS for rendering.

properties: editable, options, placeholder_text, selected_index, selected_key, text

emitters: user_selected

actions: set_editable, set_options, set_placeholder_text, set_selected_index, set_selected_key, set_text

editable

BoolProp – Whether the combobox’s text is editable.

options

TupleProp – A list of tuples (key, text) representing the options. Both keys and texts are converted to strings if they are not already. For items that are given as a string, the key and text are the same. If a dict is given, it is transformed to key-text pairs.

placeholder_text

StringProp – The placeholder text to display in editable mode.

selected_index

IntProp – The currently selected item index. Can be -1 if no item has been selected or when the text was changed manually (if editable). Can also be programatically set.

selected_key

StringProp – The currently selected item key. Can be ‘’ if no item has been selected or when the text was changed manually (if editable). Can also be programatically set.

set_editable(*val)

action – Setter for the ‘editable’ property.

set_options(options)

action – set_options

set_placeholder_text(*val)

action – Setter for the ‘placeholder_text’ property.

set_selected_index(index)

action – set_selected_index

set_selected_key(key)

action – set_selected_key

set_text(*val)

action – Setter for the ‘text’ property.

text

StringProp – The text displayed on the widget. This property is set when an item is selected from the dropdown menu. When editable, the text is also set when the text is edited by the user. This property is settable programatically regardless of the value of editable.

user_selected(index)

emitter – Event emitted when the user selects an item using the mouse or keyboard. The event has attributes index, key and text.

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

Inherits from: BaseDropdown

A dropdown widget that shows its children when expanded. This can be used to e.g. make a collapsable tree widget. Some styling may be required for the child widget to be sized appropriately.

Note: This widget is currently broken, because pointer events do not work in the contained widget (at least on Firefox).

properties: text

actions: set_text

set_text(*val)

action – Setter for the ‘text’ property.

text

StringProp – The text displayed on the dropdown widget.

GroupWidget

Visually group a collection of input widgets. Example:

from flexx import app, event, ui

class Example(ui.GroupWidget):
    def init(self):
        self.set_title('A silly panel')
        with ui.VBox():
            self.progress = ui.ProgressBar(min=0, max=9,
                                           text='Clicked {value} times')
            self.but = ui.Button(text='click me')

    @event.reaction('but.pointer_down')
    def _button_pressed(self, *events):
        self.progress.set_value(self.progress.value + 1)

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

Inherits from: Widget

Widget to collect widgets in a named group. It does not provide a layout. This is similar to a QGroupBox or an HTML fieldset.

The node of this widget is a <fieldset>.

JS

alias of GroupWidget

IFrame
with ui.HSplit():
    ui.IFrame(url='bsdf.io')
    ui.IFrame(url='http://flexx.readthedocs.io')
    # Note: the rtd page does not seem to load on Firefox 57.04

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

Inherits from: Widget

An iframe element, i.e. a container to show web-content. Note that some websites do not allow themselves to be rendered in a cross-source iframe.

The node of this widget is a <iframe>.

properties: url

actions: set_url

set_url(*val)

action – Setter for the ‘url’ property.

url

StringProp – The url to show. ‘http://’ is automatically prepended if the url does not have ‘://’ in it.

Label
from flexx import app, event, ui

class Example(ui.Widget):

    def init(self):
        with ui.HBox():
            self.but = ui.Button(text='Push me')
            self.label = ui.Label(flex=1, wrap=True, text='This is a label. ')

    @event.reaction('but.pointer_down')
    def _add_label_text(self, *events):
        self.label.set_text(self.label.text + 'Yes it is. ')

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

Inherits from: Widget

Widget to show text/html.

The node of this widget is a <div> with CSS word-wrap and white-space set appropriately.

properties: html, text, wrap

actions: set_html, set_text, set_wrap

html

StringProp – The html shown in the label.

Warning: there is a risk of introducing openings for XSS attacks when html is introduced that you do not control (e.g. from user input).

set_html(html)

action – Setter for the html property. Use with care.

set_text(text)

action – Setter for the text property.

set_wrap(*val)

action – Setter for the ‘wrap’ property.

text

StringProp – The text shown in the label (HTML is shown verbatim).

wrap

IntProp – Whether the content is allowed to be wrapped on multiple lines. Set to 0/False for no wrap (default), 1/True for word-wrap, 2 for character wrap.

Lineedit

The LineEdit and MultiLineEdit widgets provide a way for the user to input text.

from flexx import app, event, ui

class Example(ui.Widget):

    def init(self):
        with ui.VBox():
            self.line = ui.LineEdit(placeholder_text='type here')
            self.l1 = ui.Label(html='<i>when user changes text</i>')
            self.l2 = ui.Label(html='<i>when unfocusing or hitting enter </i>')
            self.l3 = ui.Label(html='<i>when submitting (hitting enter)</i>')
            ui.Widget(flex=1)

    @event.reaction('line.user_text')
    def when_user_changes_text(self, *events):
        self.l1.set_text('user_text: ' + self.line.text)

    @event.reaction('line.user_done')
    def when_user_is_done_changing_text(self, *events):
        self.l2.set_text('user_done: ' + self.line.text)

    @event.reaction('line.submit')
    def when_user_submits_text(self, *events):
        self.l3.set_text('submit: ' + self.line.text)

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

Inherits from: Widget

An input widget to edit a line of text.

The node of this widget is a text <input>.

properties: autocomp, disabled, password_mode, placeholder_text, text

emitters: submit, user_done, user_text

actions: set_autocomp, set_disabled, set_password_mode, set_placeholder_text, set_text

autocomp

TupleProp – A tuple/list of strings for autocompletion. Might not work in all browsers.

disabled

BoolProp – Whether the line edit is disabled.

password_mode

BoolProp – Whether the insered text should be hidden.

placeholder_text

StringProp – The placeholder text (shown when the text is an empty string).

set_autocomp(*val)

action – Setter for the ‘autocomp’ property.

set_disabled(*val)

action – Setter for the ‘disabled’ property.

set_password_mode(*val)

action – Setter for the ‘password_mode’ property.

set_placeholder_text(*val)

action – Setter for the ‘placeholder_text’ property.

set_text(*val)

action – Setter for the ‘text’ property.

submit()

emitter – Event emitted when the user strikes the enter or return key (but not when losing focus). Has old_value and new_value attributes (which are the same).

text

StringProp – The current text of the line edit. Settable. If this is an empty string, the placeholder_text is displayed instead.

user_done()

emitter – Event emitted when the user is done editing the text, either by moving the focus elsewhere, or by hitting enter. Has old_value and new_value attributes (which are the same).

user_text(text)

emitter – Event emitted when the user edits the text. Has old_value and new_value attributes.

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

Inherits from: Widget

An input widget to edit multiple lines of text.

The node of this widget is a <textarea>.

properties: text

emitters: user_done, user_text

actions: set_text

set_text(*val)

action – Setter for the ‘text’ property.

text

StringProp – The current text of the multi-line edit. Settable. If this is an empty string, the placeholder_text is displayed instead.

user_done()

emitter – Event emitted when the user is done editing the text by moving the focus elsewhere. Has old_value and new_value attributes (which are the same).

user_text(text)

emitter – Event emitted when the user edits the text. Has old_value and new_value attributes.

Media widgets
from flexx import ui

class Example(ui.Widget):

    def init(self):
        with ui.HSplit():
            url = 'http://www.w3schools.com/tags/mov_bbb.mp4'
            ui.VideoWidget(source=url)
            ui.YoutubeWidget(source='RG1P8MQS1cU')
            with ui.VBox():
                stretch = ui.CheckBox(text='Stretch')
                ui.ImageWidget(flex=1, stretch=lambda:stretch.checked,
                                source='http://github.com/fluidicon.png')

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

Inherits from: Widget

Display an image from a url.

The node of this widget is an <img> wrapped in a <div> (the outernode) to handle sizing.

properties: source, stretch

actions: set_source, set_stretch

set_source(*val)

action – Setter for the ‘source’ property.

set_stretch(*val)

action – Setter for the ‘stretch’ property.

source

StringProp – The source of the image, This can be anything that an HTML img element supports.

stretch

BoolProp – Whether the image should stretch to fill all available space, or maintain its aspect ratio (default).

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

Inherits from: Widget

Display a video from a url.

The node of this widget is a <video>.

properties: source

actions: set_source

set_source(*val)

action – Setter for the ‘source’ property.

source

StringProp – The source of the video. This must be a url of a resource on the web.

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

Inherits from: Widget

Display a Youtube video.

The node of this widget is a <div> containing an <iframe> that loads the youtube page.

properties: source

actions: set_source

set_source(*val)

action – Setter for the ‘source’ property.

source

StringProp – The source of the video represented as the Youtube id.

Plotly

Simple example:

# Define data. This can also be generated with the plotly Python library
data = [{'type': 'bar',
         'x': ['giraffes', 'orangutans', 'monkeys'],
         'y': [20, 14, 23]}]

# Show
p = ui.PlotlyWidget(data=data)

Also see examples: plotly_gdp.py.


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

Inherits from: Widget

A widget that shows a Plotly visualization.

properties: config, data, layout

actions: set_config, set_data, set_layout

config

DictProp – The config for the plot.

data

ListProp – The data (list of dicts) that describes the plot. This can e.g. be the output of the Python plotly API call.

layout

DictProp – The layout dict to style the plot.

set_config(*val)

action – Setter for the ‘config’ property.

set_data(*val)

action – Setter for the ‘data’ property.

set_layout(*val)

action – Setter for the ‘layout’ property.

PlotWidget

The plot widget provides rudimentary plotting functionality, mostly to demonstrate how plots can be embedded in a Flexx GUI. It may be sufficient for simple cases, but don’t expect it to ever support log-plotting, legends, and other fancy stuff. For real plotting, see e.g. BokehWidget. There might also be a Plotly widget at some point.

Simple example:

p = ui.PlotWidget(xdata=range(5), ydata=[1,3,4,2,5],
                  line_width=4, line_color='red', marker_color='',
                  minsize=200)

Also see examples: sine.py, twente.py, monitor.py.


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

Inherits from: CanvasWidget

Widget to show a plot of x vs y values. Enough for simple plotting tasks.

properties: line_color, line_width, marker_color, marker_size, xdata, xlabel, ydata, ylabel, yrange

actions: set_data, set_line_color, set_line_width, set_marker_color, set_marker_size, set_xlabel, set_ylabel, set_yrange

line_color

ColorProp – The color of the line. Set to the empty string to hide the line.

line_width

FloatProp – The width of the line, in pixels.

marker_color

ColorProp – The color of the marker. Set to the empty string to hide the marker.

marker_size

FloatProp – The size of the marker, in pixels.

set_data(xdata, ydata)

action – Set the xdata and ydata.

set_line_color(*val)

action – Setter for the ‘line_color’ property.

set_line_width(*val)

action – Setter for the ‘line_width’ property.

set_marker_color(*val)

action – Setter for the ‘marker_color’ property.

set_marker_size(*val)

action – Setter for the ‘marker_size’ property.

set_xlabel(*val)

action – Setter for the ‘xlabel’ property.

set_ylabel(*val)

action – Setter for the ‘ylabel’ property.

set_yrange(*val)

action – Setter for the ‘yrange’ property.

xdata

TupleProp – A list of values for the x-axis. Set via the set_data() action.

xlabel

StringProp – The label to show on the x-axis.

ydata

TupleProp – A list of values for the y-axis. Set via the set_data() action.

ylabel

StringProp – The label to show on the y-axis.

yrange

FloatPairProp – The range for the y-axis. If (0, 0) (default) it is determined from the data.

ProgressBar

Example:

from flexx import app, event, ui

class Example(ui.Widget):

    def init(self):
        with ui.HBox():
            self.b1 = ui.Button(flex=0, text='Less')
            self.b2 = ui.Button(flex=0, text='More')
            self.prog = ui.ProgressBar(flex=1, value=0.1, text='{percent} done')

    @event.reaction('b1.pointer_down', 'b2.pointer_down')
    def _change_progress(self, *events):
        for ev in events:
            if ev.source is self.b1:
                self.prog.set_value(self.prog.value - 0.1)
            else:
                self.prog.set_value(self.prog.value + 0.1)

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

Inherits from: Widget

A widget to show progress.

The node of this widget is a <div> containing a few HTML elements for rendering.

properties: max, min, text, value

actions: set_max, set_min, set_text, set_value

max

FloatProp – The maximum progress value.

min

FloatProp – The minimum progress value.

set_max(*val)

action – Setter for the ‘max’ property.

set_min(*val)

action – Setter for the ‘min’ property.

set_text(*val)

action – Setter for the ‘text’ property.

set_value(value)

action – set_value

text

StringProp – The label to display on the progress bar. Occurances of “{percent}” are replaced with the current percentage, and “{value}” with the current value.

value

FloatProp – The progress value.

Slider

Simple example:

with flx.VBox():
    flx.Slider(min=10, max=20, value=12)
    flx.RangeSlider(min=10, max=90, value=(20, 60))

Also see examples: sine.py, twente.py, deep_event_connections.py.


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

Inherits from: Widget

An input widget to select a value in a certain range.

The node of this widget is a <div> containing a few HTML elements for rendering. It does not use a <input type='range'> because of its different appearance and behaviour accross browsers.

properties: disabled, max, min, step, text, value

emitters: user_done, user_value

actions: set_disabled, set_max, set_min, set_step, set_text, set_value

disabled

BoolProp – Whether the slider is disabled.

max

FloatProp – The maximum slider value.

min

FloatProp – The minimal slider value.

set_disabled(*val)

action – Setter for the ‘disabled’ property.

set_max(*val)

action – Setter for the ‘max’ property.

set_min(*val)

action – Setter for the ‘min’ property.

set_step(*val)

action – Setter for the ‘step’ property.

set_text(*val)

action – Setter for the ‘text’ property.

set_value(value)

action – set_value

step

FloatProp – The step size for the slider.

text

StringProp – The label to display on the slider during dragging. Occurances of “{percent}” are replaced with the current percentage, and “{value}” with the current value. Default “{value}”.

user_done()

emitter – Event emitted when the user stops manipulating the slider. Has old_value and new_value attributes (which have the same value).

user_value(value)

emitter – Event emitted when the user manipulates the slider. Has old_value and new_value attributes.

value

FloatProp – The current slider value.

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

Inherits from: Slider

An input widget to select a range (i.e having two handles instead of one).

The node of this widget is a <div> containing a few HTML elements for rendering.

properties: value

actions: set_value

set_value(*value)

action – Set the RangeSlider’s value. Can be called using set_value([val1, val2]) or set_value(val1, val2).

value

FloatPairProp – The current slider value as a two-tuple.

TreeWidget

A TreeWidget can contain TreeItems, which in turn can contain TreeItems to construct a tree.

from flexx import app, ui

class Example(ui.Widget):

    def init(self):

        with ui.TreeWidget(max_selected=2):

            for t in ['foo', 'bar', 'spam', 'eggs']:
                ui.TreeItem(text=t, checked=True)

Also see examples: tree.py, control_with_keys.py.


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

Inherits from: Widget

An item to put in a TreeWidget. This widget should only be used inside a TreeWidget or another TreeItem.

Items are collapsable/expandable if their collapsed property is set to True or False (i.e. not None), or if they have sub items. Items are checkable if their checked property is set to True or False (i.e. not None). Items are selectable depending on the selection policy defined by TreeWidget.max_selected.

If needed, the _render_title() and _render_text() methods can be overloaded to display items in richer ways. See the documentation of Widget._render_dom() for details.

The outernode of this widget is a <li> (a list-item in the tree or parent item’s <ul>. The node of this widget is a <span> that represents the row for this item (but not its children).

properties: checked, collapsed, selected, text, title, visible

emitters: user_checked, user_collapsed, user_selected

actions: set_checked, set_collapsed, set_parent, set_selected, set_text, set_visible

checked

TriStateProp – Whether this item is checked (i.e. has its checkbox set). The value can be None, True or False. None (the default) means that the item is not checkable.

collapsed

TriStateProp – Whether this item is expanded (i.e. shows its children). The value can be None, True or False. None (the default) means that the item is not collapsable (unless it has sub items).

selected

BoolProp – Whether this item is selected. Depending on the TreeWidget’s policy (max_selected), this can be set/unset on clicking the item.

set_checked(*val)

action – Setter for the ‘checked’ property.

set_collapsed(*val)

action – Setter for the ‘collapsed’ property.

set_parent(parent, pos=None)

action – set_parent

set_selected(*val)

action – Setter for the ‘selected’ property.

set_text(*val)

action – Setter for the ‘text’ property.

set_visible(*val)

action – Setter for the ‘visible’ property.

text

StringProp – The text for this item. Can be used in combination with title to obtain two columns.

title

StringProp – The title for this item that appears before the text. Intended for display of key-value pairs. If a title is given, the text is positioned in a second (virtual) column of the tree widget.

user_checked(checked)

emitter – Event emitted when the user (un)checks this item. Has old_value and new_value attributes.

user_collapsed(collapsed)

emitter – Event emitted when the user (un)collapses this item. Has old_value and new_value attributes.

user_selected(selected)

emitter – Event emitted when the user (un)selects this item. Has old_value and new_value attributes. One can call this emitter directly to emulate a user-selection, but note that this bypasses the max_selected policy.

visible

BoolProp – Whether this item (and its sub items) is visible.

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

Inherits from: Widget

A Widget that can be used to structure information in a list or a tree. It’s items are represented by its children, which may only be TreeItem objects. Sub items can be created by instantiating TreeItems in the context of another TreeItem.

When the items in the tree have no sub-items themselves, the TreeWidget is in “list mode”. Otherwise, items can be collapsed/expanded etc.

The node of this widget is a <div> with some child elements and quite a bit of CSS for rendering.

Style

This widget can be fully styled using CSS, using the following CSS classes:

  • flx-listmode is set on the widget’s node if no items have sub items.

Style classes for a TreeItem’s elements:

  • flx-TreeItem indicates the row of an item (its text, icon, and checkbox).
  • flx-TreeItem > collapsebut the element used to collapse/expand an item.
  • flx-TreeItem > checkbut the element used to check/uncheck an item.
  • flx-TreeItem > text the element that contains the text of the item.
  • flx-TreeItem > title the element that contains the title of the item.

Style classes applied to the TreeItem, corresponding to its properties:

  • visible-true and visible-false indicate visibility.
  • selected-true and selected-false indicate selection state.
  • checked-true, checked-false and checked-null indicate checked state, with the null variant indicating not-checkable.
  • collapsed-true, collapsed-false and collapsed-null indicate collapse state, with the null variant indicating not-collapsable.

properties: max_selected

actions: set_max_selected

methods: get_all_items, highlight_get, highlight_hide, highlight_show, highlight_show_item, highlight_toggle_checked, highlight_toggle_selected

get_all_items()

Get a flat list of all TreeItem instances in this Tree (including sub children and sub-sub children, etc.), in the order that they are shown in the tree.

highlight_get()

Get the “current” item. This is the currently highlighted item if there is one. Otherwise it can be the last highlighted item or the last clicked item.

highlight_hide()

Stop highlighting the “current” item.

highlight_show(step=0)

Highlight the “current” item, optionally moving step items.

highlight_show_item(item)

Highlight the given item.

highlight_toggle_checked()

Convenience method to toggle the “checked” property of the current item.

highlight_toggle_selected()

Convenience method to toggle the “selected” property of the current item.

max_selected

IntProp – The maximum number of selected items:

  • If 0 (default) there is no selection.
  • If 1, there can be one selected item.
  • If > 1, up to this number of items can be selected by clicking them.
  • If -1, any number of items can be selected by holding Ctrl or Shift.
set_max_selected(*val)

action – Setter for the ‘max_selected’ property.

App reference

Wrapping a Component into an Application
class flexx.app.App(cls, *args, **kwargs)

Specification of a Flexx app.

Strictly speaking, this is a container for a PyComponent/JsComponent class plus the args and kwargs that it is to be instantiated with.

Parameters:
  • cls (Component) – the PyComponent or JsComponent class (e.g. Widget) that represents this app.
  • args – positional arguments used to instantiate the class (and received in its init() method).
  • kwargs – keyword arguments used to initialize the component’s properties.
cls

The Component class that is the basis of this app.

dump(fname=None, link=2)

Get a dictionary of web assets that statically represents the app.

The returned dict contains at least one html file. Any session-specific or shared data is also included. If link is 2/3, all shared assets are included too (and the main document links to them). A link value of 0/1 may be prefered for performance or ease of distribution, but with link 2/3 debugging is easier and multiple apps can share common assets.

When a process only dumps/exports an app, no server is started. Tornado is not even imported (we have a test for this). This makes it possible to use Flexx to dump an app and then serve it with any tool one likes.

Parameters:
  • fname (str, optional) – the name of the main html asset. If not given or None, the name of the component class is used. Must end in .html/.htm/.hta.
  • link (int) –

    whether to link (JS and CSS) assets or embed them: A values of 0/1 is recommended for single (and standalone) apps, while multiple apps can share common assets by using 2/3.

    • 0: all assets are embedded into the main html document.
    • 1: normal assets are embedded, remote assets remain remote.
    • 2: all assets are linked (as separate files). Default.
    • 3: normal assets are linked, remote assets remain remote.
Returns:

A collection of assets.

Return type:

dict

export(filename, link=2, overwrite=True)

Export this app to a static website.

Also see dump(). An app that contains no data, can be exported to a single html document by setting link to 0.

Parameters:
  • filename (str) – Path to write the HTML document to. If the filename ends with .hta, a Windows HTML Application is created. If a directory is given, the app is exported to appname.html in that directory.
  • link (int) –

    whether to link (JS and CSS) assets or embed them:

    • 0: all assets are embedded into the main html document.
    • 1: normal assets are embedded, remote assets remain remote.
    • 2: all assets are linked (as separate files). Default.
    • 3: normal assets are linked, remote assets remain remote.
  • overwrite (bool, optional) – if True (default) will overwrite files that already exist. Otherwise existing files are skipped. The latter makes it possible to efficiently export a series of apps to the same directory and have them share common assets.
freeze(dirname, launch='firefox-app', excludes=('numpy', ), includes=())

Create an executable that can be distributed as a standalone desktop application. This process (known as “freezing”) requires PyInstaller.

Note: this method is experimental. See https://flexx.readthedocs.io/en/stable/freeze.html for more information.

Parameters:
  • dirname (str) – Path to generate the executable in. Some temporary files and directories will be created during the freezing process. The actual executable will be placed in “dist/app_name”, where app_name is the (lowercase) name of the application class.
  • launch (str) – The argument to use for the call to flx.launch(). If set to None, flx.serve() will be used instead, and you will be responsible for connecting a browser.
  • excludes (list) – A list of module names to exclude during freezing. By default Numpy is excluded because PyInstaller detects it even though Flexx does not use it. Override this if you do use Numpy.
  • includes (list) – A list of module name to include during freezing.
is_served

Whether this app is already registered by the app manager.

launch(runtime=None, **runtime_kwargs)

Launch this app as a desktop app in the given runtime. See https://webruntime.readthedocs.io for details.

Parameters:
  • runtime (str) – the runtime to launch the application in. Default ‘app or browser’.
  • runtime_kwargs – kwargs to pass to the webruntime.launch function. A few names are passed to runtime kwargs if not already present (‘title’ and ‘icon’).
Returns:

an instance of the given class.

Return type:

Component

name

The name of the app, i.e. the url path that this app is served at.

publish(name, token, url=None)

Publish this app as static HTML on the web.

This is an experimental feature! We will try to keep your app published, but make no guarantees. We reserve the right to remove apps or shut down the web server completely.

Parameters:
  • name (str) – The name by which to publish this app. Must be unique within the scope of the published site.
  • token (str) – a secret token. This is stored at the target website. Subsequent publications of the same app name must have the same token.
  • url (str) – The url to POST the app to. If None (default), the default Flexx live website url will be used.
serve(name=None)

Start serving this app.

This registers the given class with the internal app manager. The app can be loaded via ‘http://hostname:port/name’.

Parameters:name (str, optional) – the relative URL path to serve the app on. If this is '' (the empty string), this will be the main app. If not given or None, the name of the component class is used.
url

The url to acces this app. This raises an error if serve() has not been called yet or if Flexx’ server is not yet running.

flexx.app.serve(cls, name=None, properties=None)

Shorthand for app.App(cls).serve(name).

flexx.app.launch(cls, runtime=None, properties=None, **runtime_kwargs)

Shorthand for app.App(cls).launch(runtime, **runtime_kwargs).

flexx.app.export(cls, filename, properties=None, **kwargs)

Shorthand for app.App(cls).export(filename, ...).

The Component classes
class flexx.app.BaseAppComponent(*init_args, **property_values)

Inherits from Component

Abstract class for Component classes that can be “shared” between Python and JavaScript. The concrete implementations are:

  • The PyComponent class, which operates in Python, but has a proxy object in JavaSript to which properties are synced and from which actions can be invoked.
  • The JsComponent class, which operates in JavaScript, but can have a proxy object in Python to which properties are synced and from which actions can be invoked.
  • The StubComponent class, which represents a component class that is somewhere else, perhaps in another session. It does not have any properties, nor actions. But it can be “moved around”.
root

attribute – The component that represents the root of the application. Alias for session.app.

session

attribute – The session to which this component belongs. The component id is unique within its session.

uid

attribute – A unique identifier for this component; a combination of the session and component id’s.

class flexx.app.PyComponent(*init_args, **property_values)

Inherits from BaseAppComponent

Base component class that operates in Python, but is accessible in JavaScript, where its properties and events can be observed, and actions can be invoked.

PyComponents can only be instantiated in Python, and always have a corresponding proxy object in JS. PyComponents can be disposed only from Python. Disposal also happens if the Python garbage collector collects a PyComponent.

JS

alias of PyComponent

class flexx.app.JsComponent(*init_args, **kwargs)

Inherits from BaseAppComponent

Base component class that operates in JavaScript, but is accessible in Python, where its properties and events can be observed, and actions can be invoked.

JsComponents can be instantiated from both JavaScript and Python. A corresponding proxy component is not necessarily present in Python. It is created automatically when needed (e.g. when referenced by a property). A JsComponent can be explicitly disposed from both Python and JavaScript. When the Python garbage collector collects a JsComponent (or really, the proxy thereof), only the Python side proxy is disposed; the JsComponent in JS itself will be unaffected. Make sure to call dispose() when needed!

JS

alias of JsComponent

class flexx.app.StubComponent(session, id)

Class to represent stub proxy components to take the place of components that do not belong to the current session, or that do not exist for whatever reason. These objects cannot really be used, but they can be moved around.

flexx.app.get_component_classes()

Get a list of all known PyComponent and JsComponent subclasses.

class flexx.app.LocalProperty(*args, doc='', settable=False)

A generic property that is only present at the local side of the component, i.e. not at the proxy. Intended for properties that the other side should not care about, and/or for wich syncing would be problematic, e.g. for performance or because it contains components that we want to keep local.

Session and Assets

An asset is represented using an Asset object that defines its sources, dependencies, etc. Assets can be specific to the session or shared across sessions. The AssetStore provides all shared assets for clients connected to the current process. The global store is at flexx.app.assets. The session object handles the connection between Python and JavaScript, and it allows adding client-side assets, which for instance makes it easy to create extensions based on existing JS libraries.

class flexx.app.Asset(name, source=None)

Class to represent an asset (JS or CSS) to be included on the page. Users will typically use app.assets.add_shared_asset(), see the corresponding docs for details.

name

The (file) name of this asset.

remote

Whether the asset is remote (client will load it from elsewhere). If True, the source specifies the URL.

source

The source for this asset. Can be str, URL or callable.

to_html(path='{}', link=3)

Get HTML element tag to include in the document.

Parameters:
  • path (str) – the path of this asset, in which ‘{}’ can be used as a placeholder for the asset name.
  • link (int) –

    whether to link to this asset:

    • 0: the asset is embedded.
    • 1: normal assets are embedded, remote assets remain remote.
    • 2: the asset is linked (and served by our server).
    • 3: (default) normal assets are linked, remote assets remain remote.
to_string()

Get the string code for this asset. Even for remote assets.

class flexx.app._assetstore.AssetStore

Provider of shared assets (CSS, JavaScript) and data (images, etc.). Keeps track of JSModules and makes them available via asset bundles. The global asset store object can be found at flexx.app.assets. Assets and data in the asset store can be used by all sessions. Each session object also keeps track of data.

Assets with additional JS or CSS to load can be used simply by creating/importing them in a module that defines the JsComponent class that needs the asset.

add_shared_asset(asset_name, source=None)

Add an asset to the store so that the client can load it from the server. Users typically only need this to provide an asset without loading it in the main page, e.g. when the asset is loaded by a secondary page, a web worker, or AJAX.

Parameters:
  • name (str) – the asset name, e.g. ‘foo.js’ or ‘bar.css’. Can contain slashes to emulate a file system. e.g. ‘spam/foo.js’. If a URL is given, both name and source are implicitly set (and its a remote asset).
  • source (str, function) –

    the source for this asset. Can be:

    • The source code.
    • A URL (str starting with ‘http://’ or ‘https://’), making this a “remote asset”. Note that App.export() provides control over how (remote) assets are handled.
    • A funcion that should return the source code, and which is called only when the asset is used. This allows defining assets without causing side effects when they’re not used.
Returns:

the (relative) url at which the asset can be retrieved.

Return type:

str

add_shared_data(name, data)

Add data to serve to the client (e.g. images), which is shared between sessions. It is an error to add data with a name that is already registered. See Session.add_data() to set data per-session and use actions to send data to JsComponent objects directly.

Parameters:
  • name (str) – the name of the data, e.g. ‘icon.png’.
  • data (bytes) – the data blob.
Returns:

the (relative) url at which the data can be retrieved.

Return type:

str

associate_asset(mod_name, asset_name, source=None)

Associate an asset with the given module. The assets will be loaded when the module that it is associated with is used by JavaScript. Multiple assets can be associated with a module, and an asset can be associated with multiple modules.

The intended usage is to write the following inside a module that needs the asset: app.assets.associate_asset(__name__, ...).

Parameters:
  • mod_name (str) – The name of the module to associate the asset with.
  • asset_name (str) – The name of the asset to associate. Can be an already registered asset, or a new asset.
  • source (str, callable, optional) – The source for a new asset. See add_shared_asset() for details. It is an error to supply a source if the asset_name is already registered.
Returns:

the (relative) url at which the asset can be retrieved.

Return type:

str

get_asset(name)

Get the asset instance corresponding to the given name or None if it not known.

get_asset_names()

Get a list of all asset names.

get_associated_assets(mod_name)

Get the names of the assets associated with the given module name. Sorted by instantiation time.

get_data(name)

Get the data (as bytes) corresponding to the given name or None if it not known.

get_data_names()

Get a list of all data names.

modules

The JSModule objects known to the asset store. Each module corresponds to a Python module.

update_modules()

Collect and update the JSModule instances that correspond to Python modules that define Component classes. Any newly created modules get added to all corresponding assets bundles (creating them if needed).

It is safe (and pretty fast) to call this more than once since only missing modules are added. This gets called automatically by the Session object.

class flexx.app.Session(app_name, store=None, request=None)

A connection between Python and the client runtime (JavaScript).

The session is what holds together the app widget, the web runtime, and the websocket instance that connects to it.

Responsibilities:

  • Send messages to the client and process messages received by the client.
  • Keep track of PyComponent instances used by the session.
  • Keep track of JsComponent instances associated with the session.
  • Ensure that the client has all the module definitions it needs.
add_data(name, data)

Add data to serve to the client (e.g. images), specific to this session. Returns the link at which the data can be retrieved. Note that actions can be used to send (binary) data directly to the client (over the websocket).

Parameters:
  • name (str) – the name of the data, e.g. ‘icon.png’. If data has already been set on this name, it is overwritten.
  • data (bytes) – the data blob.
Returns:

the (relative) url at which the data can be retrieved.

Return type:

str

app

The root PyComponent or JsComponent instance that represents the app.

app_name

The name of the application that this session represents.

assets_to_ignore

The set of names of assets that should not be pushed to the client, e.g. because they are already present on the page. Add names to this set to prevent them from being loaded.

call_after_roundtrip(callback, *args)

A variant of call_soon() that calls a callback after a py-js roundrip. This can be convenient to delay an action until after other things have settled down.

close()

Close the session: close websocket, close runtime, dispose app.

co_eval(js)

Coroutine to evaluate JS in the client, wait for the result, and then return it. It is recomended to use this method only for testing purposes.

co_roundtrip()

Coroutine to wait for one Py-JS-Py roundtrip.

get_component_instance(id)

Get PyComponent or JsComponent instance that is associated with this session and has the corresponding id. The returned value can be None if it does not exist, and a returned component can be disposed.

Gets the value of the cookie with the given name, else default. Note that cookies only really work for web apps.

get_data(name)

Get the data corresponding to the given name. This can be data local to the session, or global data. Returns None if data by that name is unknown.

get_data_names()

Get a list of names of the data provided by this session.

id

The unique identifier of this session.

keep_alive(ob, iters=1)

Keep an object alive for a certain amount of time, expressed in Python-JS ping roundtrips. This is intended for making JsComponent (i.e. proxy components) survice the time between instantiation triggered from JS and their attachement to a property, though any type of object can be given.

present_modules

The set of module names that is (currently) available at the client.

remove_data(name)

Remove the data associated with the given name. If you need this, consider using actions instead. Note that data is automatically released when the session is closed.

request

The tornado request that was at the origin of this session.

runtime

The runtime that is rendering this app instance. Can be None if the client is a browser.

send_command(*command)

Send a command to the other side. Commands consists of at least one argument (a string representing the type of command).

Sets the given cookie name/value with the given options. Set value to None to clear. The cookie value is secured using flexx.config.cookie_secret; don’t forget to set that config value in your server. Additional keyword arguments are set on the Cookie.Morsel directly.

status

The status of this session. The lifecycle for each session is:

  • status 1: pending
  • status 2: connected
  • status 0: closed

Event reference

Component
class flexx.event.Component(*init_args, **property_values)

The base component class.

Components have attributes to represent static values, properties to represent state, actions that can mutate properties, and reactions that react to events such as property changes.

Initial values of properties can be provided by passing them as keyword arguments.

Subclasses can use Property (or one of its subclasses) to define properties, and the action, reaction, and emitter decorators to create actions, reactions. and emitters, respectively.

class MyComponent(event.Component):

    foo = event.FloatProp(7, settable=True)
    spam = event.Attribute()

    @event.action
    def inrease_foo(self):
        self._mutate_foo(self.foo + 1)

    @event.reaction('foo')
    def on_foo(self, *events):
        print('foo was set to', self.foo)

    @event.reaction('bar')
    def on_bar(self, *events):
        for ev in events:
            print('bar event was emitted')

    @event.emitter
    def bar(self, v):
        return dict(value=v)  # the event to emit
_comp_apply_property_values(values)

Apply given property values, prefer using a setter, mutate otherwise.

_comp_init_property_values(property_values)

Initialize property values, combining given kwargs (in order) and default values.

_comp_init_reactions()

Create our own reactions. These will immediately connect.

_comp_stop_capturing_events()

Stop capturing events and flush the captured events. This gets scheduled to be called asap after initialization. But components created in our init() go first.

_mutate(prop_name, value, mutation='set', index=-1)

Mutate a property. Can only be called from an action.

Each Component class will also have an auto-generated mutator function for each property: e.g. property foo can be mutated with c._mutate('foo', ..) or c._mutate_foo(..).

Parameters:
  • prop_name (str) – the name of the property being mutated.
  • value – the new value, or the partial value for partial mutations.
  • mutation (str) – the kind of mutation to apply. Default is ‘set’. Partial mutations to list-like properties can be applied by using ‘insert’, ‘remove’, or ‘replace’. If other than ‘set’, index must be specified, and >= 0. If ‘remove’, then value must be an int specifying the number of items to remove.
  • index – the index at which to insert, remove or replace items. Must be an int for list properties.

The ‘replace’ mutation also supports multidensional (numpy) arrays. In this case value can be an ndarray to patch the data with, and index a tuple of elements.

_registered_reactions_hook()

This method is called when the reactions change, can be overloaded in subclasses. The original method returns a list of event types for which there is at least one registered reaction. Overloaded methods should return this list too.

disconnect(type, reaction=None)

Disconnect reactions.

Parameters:
  • type (str) – the type for which to disconnect any reactions. Can include the label to only disconnect reactions that were registered with that label.
  • reaction (optional) – the reaction object to disconnect. If given, only this reaction is removed.
dispose()

Use this to dispose of the object to prevent memory leaks. Make all subscribed reactions forget about this object, clear all references to subscribed reactions, and disconnect all reactions defined on this object.

emit(type, info=None)

Generate a new event and dispatch to all event reactions.

Parameters:
  • type (str) – the type of the event. Should not include a label.
  • info (dict) – Optional. Additional information to attach to the event object. Note that the actual event is a Dict object that allows its elements to be accesses as attributes.
get_event_handlers(type)

Get a list of reactions for the given event type. The order is the order in which events are handled: alphabetically by label. Intended mostly for debugging purposes.

Parameters:type (str) – the type of event to get reactions for. Should not include a label.
get_event_types()

Get the known event types for this component. Returns a list of event type names, for which there is a property/emitter or for which any reactions are registered. Sorted alphabetically. Intended mostly for debugging purposes.

id

attribute – The string by which this component is identified.

init()

Initializer method. This method can be overloaded when creating a custom class. It is called with this component as a context manager (i.e. it is the active component), and it receives any positional arguments that were passed to the constructor.

reaction(*connection_strings)

Create a reaction by connecting a function to one or more events of this instance. Can also be used as a decorator. See the reaction decorator, and the intro docs for more information.

flexx.event.mutate_array(array, ev)

Function to mutate a list- or array-like property in-place. Used by Component. The ev must be a dict with elements:

  • mutation: ‘set’, ‘insert’, ‘remove’ or ‘replace’.
  • objects: the values to set/insert/replace, or the number of iterms to remove.
  • index: the (non-negative) index to insert/replace/remove at.
flexx.event.mutate_dict(d, ev)

Function to mutate an dict property in-place. Used by Component. The ev must be a dict with elements:

  • mutation: ‘set’, ‘insert’, ‘remove’ or ‘replace’.
  • objects: the dict to set/insert/replace, or a list if keys to remove.
  • index: not used.
Attributes
class flexx.event.Attribute(doc='')

Attributes are (readonly, and usually static) values associated with Component classes. They expose and document a value without providing means of observing changes like Property does. (The actual value is taken from component._xx, with “xx” the name of the attribute.)

Properties
class flexx.event.Property(*args, doc='', settable=False)

Base property class. Properties are (readonly) attributes associated with Component classes, which can be mutated only by actions. The base Property class can have any value, the subclasses validate/convert the value when it is mutated.

Parameters:
  • initial_value – The initial value for the property. If omitted, a default value is used (specific for the type of property).
  • settable (bool) – If True, a corresponding setter action is automatically created that can be used to set the property. Default False.
  • doc (str) – The documentation string for this property (optional).

Example usage:

class MyComponent(event.Component):

    foo = event.AnyProp(7, doc="A property that can be anything")
    bar = event.StringProp(doc='A property that can only be string')
    spam = event.IntProp(8, settable=True)

>> c = MyComponent()
>> c.set_spam(9)  # use auto-generated setter action

One can also implement custom properties:

class MyCustomProp(event.Property):
    ''' A property that can only be 'a', 'b' or 'c'. '''

    _default = 'a'

    def _validate(self, value, name, data):
        if value not in 'abc':
            raise TypeError('MyCustomProp %r must be "a", "b" or "c".' % name)
        return value
class flexx.event.AnyProp(*args, doc='', settable=False)

A property that can be anything (like Property). Default None.

class flexx.event.BoolProp(*args, doc='', settable=False)

A property who’s values are converted to bool. Default False.

class flexx.event.TriStateProp(*args, doc='', settable=False)

A property who’s values can be False, True and None.

class flexx.event.IntProp(*args, doc='', settable=False)

A propery who’s values are integers. Floats and strings are converted. Default 0.

class flexx.event.FloatProp(*args, doc='', settable=False)

A propery who’s values are floats. Integers and strings are converted. Default 0.0.

class flexx.event.StringProp(*args, doc='', settable=False)

A propery who’s values are strings. Default empty string.

class flexx.event.TupleProp(*args, doc='', settable=False)

A propery who’s values are tuples. In JavaScript the values are Array objects that have some of their methods disabled. Default empty tuple.

class flexx.event.ListProp(*args, doc='', settable=False)

A propery who’s values are lists. Default empty list. The value is always copied upon setting, so one can safely provide an initial list.

Warning: updating the list in-place (e.g. use append()) will not trigger update events! In-place updates can be done via the _mutate method.

class flexx.event.DictProp(*args, doc='', settable=False)

A property who’s values are dicts. Default empty dict. The value is always copied upon setting, so one can safely provide an initial dict.

Warning: updating the dict in-place (e.g. use update()) will not trigger update events! In-place updates can be done via the _mutate method.

class flexx.event.ComponentProp(*args, doc='', settable=False)

A propery who’s values are Component instances or None. Default None.

class flexx.event.FloatPairProp(*args, doc='', settable=False)

A property that represents a pair of float values, which can also be set using a scalar.

class flexx.event.EnumProp(*args, doc='', settable=False)

A property that represents a choice between a fixed set of (string) values.

Useage: foo = EnumProp(['optionA', 'optionB', ...], 'default', ...). If no initial value is provided, the first option is used.

class flexx.event.ColorProp(*args, doc='', settable=False)

A property that represents a color. The value is represented as a (dict-like) object that has the following attributes:

  • t: a 4-element tuple (RGBA) with values between 0 and 1.
  • css: a CSS string in the form ‘rgba(r,g,b,a)’.
  • hex: a hex RGB color in the form ‘#rrggbb’ (no transparency).
  • alpha: a scalar between 0 and 1 indicating the transparency.

The color can be set using:

  • An object as described above.
  • A tuple (length 3 or 4) with floats between 0 and 1.
  • A hex RGB color like ‘#f00’ or ‘#aa7711’.
  • A hex RGBA color like ‘#f002’ or ‘#ff000022’.
  • A CSS string “rgb(…)” or “rgba(…)”
  • Simple Matlab-like names like ‘k’, ‘w’, ‘r’, ‘g’, ‘b’, etc.
  • A few common color names like ‘red’, ‘yellow’, ‘cyan’.
  • Further, string colors can be prefixed with “light”, “lighter”, “dark” and “darker”.
  • Setting to None or “” results in fully transparent black.
Actions
flexx.event.action(func)

Decorator to turn a method of a Component into an Action.

Actions change the state of the application by mutating properties. In fact, properties can only be changed via actions.

Actions are asynchronous and thread-safe. Invoking an action will not apply the changes directly; the action is queued and handled at a later time. The one exception is that when an action is invoked from anoher action, it is handled directly.

Although setting properties directly might seem nice, their use would mean that the state of the application can change while the app is reacting to changes in the state. This might be managable for small applications, but as an app grows this easily results in inconsistencies and bugs. Separating actions (which modify state) and reactions (that react to it) makes apps easier to understand and debug. This is the core idea behind frameworks such as Elm, React and Veux. And Flexx adopts it as well.

Example usage:

class MyComponent(event.Component):

    count = event.IntProp(0)

    @action
    def increase_counter(self):
        self._mutate_count(self.count + 1)  # call mutator function
class flexx.event.Action(ob, func, name, doc)

Action objects are wrappers around Component methods. They take care of queueing action invokations rather than calling the function directly, unless the action is called from another action (in this case it would a direct call). This class should not be instantiated directly; use event.action() instead.

Reactions
flexx.event.reaction(*connection_strings, mode='normal')

Decorator to turn a method of a Component into a Reaction.

A reaction can be connected to multiple event types. Each connection string represents an event type to connect to.

Also see the Component.reaction() method.

class MyObject(event.Component):

    @event.reaction('first_name', 'last_name')
    def greet(self, *events):
        print('hello %s %s' % (self.first_name, self.last_name))

A reaction can operate in a few different modes. By not specifying any connection strings, the mode is “auto”: the reaction will automatically trigger when any of the properties used in the function changes. See get_mode() for details.

Connection string follow the following syntax rules:

  • Connection strings consist of parts separated by dots, thus forming a path. If an element on the path is a property, the connection will automatically reset when that property changes (a.k.a. dynamism, more on this below).
  • Each part can end with one star (‘*’), indicating that the part is a list and that a connection should be made for each item in the list.
  • With two stars, the connection is made recursively, e.g. “children**” connects to “children” and the children’s children, etc.
  • Stripped of ‘*’, each part must be a valid identifier (ASCII).
  • The total string optionally has a label suffix separated by a colon. The label itself may consist of any characters.
  • The string can have a “!” at the very start to suppress warnings for connections to event types that Flexx is not aware of at initialization time (i.e. not corresponding to a property or emitter).

An extreme example could be "!foo.children**.text:mylabel", which connects to the “text” event of the children (and their children, and their children’s children etc.) of the foo attribute. The “!” is common in cases like this to suppress warnings if not all children have a text event/property.

class flexx.event.Reaction(ob, func, mode, connection_strings)

Reaction objects are wrappers around Component methods. They connect to one or more events. This class should not be instantiated directly; use event.reaction() or Component.reaction() instead.

dispose()

Disconnect all connections so that there are no more references to components.

get_connection_info()

Get a list of tuples (name, connection_names), where connection_names is a list of type names (including label) for the made connections.

get_mode()

Get the mode for this reaction:

  • ‘normal’: events are handled in the order that they were emitted. Consequently, there can be multiple calls per event loop iteration if other reactions were triggered as well.
  • ‘greedy’: this reaction receives all its events (since the last event loop iteration) in a single call (even if this breaks the order of events with respect to other reactions). Use this when multiple related events must be handled simultenously (e.g. when syncing properties).
  • ‘auto’: this reaction tracks what properties it uses, and is automatically triggered when any of these properties changes. Like ‘greedy’ there is at most one call per event loop iteration. Reactions with zero connection strings always have mode ‘auto’.

The ‘normal’ mode generally offers the most consistent behaviour. The ‘greedy’ mode allows the event system to make some optimizations. Combined with the fact that there is at most one call per event loop iteration, this can provide higher performance where it matters. Reactions with mode ‘auto’ can be a convenient way to connect things up. Although it allows the event system to make the same optimizations as ‘greedy’, it also needs to reconnect the reaction after each time it is called, which can degregade performance especially if many properties are accessed by the reaction.

get_name()

Get the name of this reaction, usually corresponding to the name of the function that this reaction wraps.

reconnect(index)

(re)connect the index’th connection.

Emitter
flexx.event.emitter(func)

Decorator to turn a method of a Component into an Emitter.

An emitter makes it easy to emit specific events, and is also a placeholder for documenting an event.

class MyObject(event.Component):

   @emitter
   def spam(self, v):
        return dict(value=v)

m = MyObject()
m.spam(42)  # emit the spam event

The method being decorated can have any number of arguments, and should return a dictionary that represents the event to generate. The method’s docstring is used as the emitter’s docstring.

class flexx.event.Emitter(ob, func, name, doc)

Emitter objects are wrappers around Component methods. They take care of emitting an event when called and function as a placeholder for documenting an event. This class should not be instantiated directly; use event.emitter() instead.

Dict
class flexx.event.Dict

A dict in which the items can be get/set as attributes.

This provides a lean way to represent structured data, and works well in combination with autocompletion. Keys can be anything that are otherwise valid keys, but keys that are not valid identifiers or that are methods of the dict class (e.g. ‘items’ or ‘copy’) can only be get/set in the classic way.

Example:

>> d = Dict(foo=3)
>> d.foo
3
>> d['foo'] = 4
>> d.foo
4
>> d.bar = 5
>> d.bar
5
loop
class flexx.event.Loop

The singleton Flexx event loop at flexx.event.loop. This holds the queue of pending calls, actions, and reactions. These are queued separately to realize a consistent one-way data-flow. Further, this object keeps track of (per thread) active components (i.e. the components whose context manager is currently active).

Users typically do not need to be aware of the loop object, as it is used internally by Flexx, though it can be useful during debugging.

This event system integrates with Python’s builtin asyncio system, configurable via Loop.integrate(). This system can run in a separate thread, but there can be only one active flexx event loop per process.

This object can also be used as a context manager; an event loop iteration takes place when the context exits.

add_action_invokation(action, args)

Schedule the handling of an action. Automatically called when an action object is called.

add_reaction_event(reaction, ev)

Schulde the handling of a reaction. Automatically called by components.

call_soon(func, *args)

Arrange for a callback to be called as soon as possible. The callback is called after call_soon() returns, when control returns to the event loop.

This operates as a FIFO queue, callbacks are called in the order in which they are registered. Each callback will be called exactly once.

Any positional arguments after the callback will be passed to the callback when it is called.

This method is thread-safe: the callback will be called in the thread corresponding with the loop. It is therefore actually more similar to asyncio’s call_soon_threadsafe().

Also see asyncio.get_event_loop().call_soon() and asyncio.get_event_loop().call_later().

can_mutate(component=None)

Whether mutations can be done to the given component, and whether invoked actions on the component are applied directly.

get_active_component()

Get the currently “active” component (for this thread), or None.

get_active_components()

Get a tuple that represents the stack of “active” components. Each thread has its own stack. Should only be used directly inside a Component context manager.

has_pending()

Get whether there are any pending actions, reactions, or calls.

integrate(loop=None, reset=True)

Integrate the Flexx event system with the given asyncio event loop (or the default one). Also binds the event system to the current thread.

From this point, any (pending) calls to the iter callback by the previous thread will be ignored.

By calling this without calling reset(), it should be possible to hot-swap the system from one loop (and/or thread) to another (though this is currently not tested).

iter()

Do one event loop iteration; process pending calls, actions and reactions. These tree types of items are each queued in separate queues, and are handled in the aforementioned order.

register_prop_access(component, prop_name)

Register access of a property, to keep track of automatic reactions.

reset()

Reset the loop, purging all pending calls, actions and reactions. This is mainly intended for test-related code.

flexx.util

Flexx’ util module contains utilities that are used internally, some of which can be useful outside of Flexx. Note that most modules in flexx.util are independent; using them does not import any other Flexx modules.

Configuration class

This page documents the Config class. For learning how to configure Flexx, see configuring flexx.

class flexx.util.config.Config(name, *sources, **options)

Class for configuration objects.

A Config object has a set of options, which can be str, int, float, bool, or a tuple of any of the above. Options can be set from different sources:

  • Each option has a default value.
  • From .cfg or .ini files.
  • From strings in ini format.
  • From environment variables.
  • From command-line arguments.
  • By setting the config option directly.
Parameters:
  • name (str) – the name by which to identify this config. This name is used as a prefix in environment variables and command line arguments, and optionally as a section header in .cfg files.
  • *sources – Sources to initialize the option values with. These can be strings in ini format, or .ini or .cfg filenames. If a file is given that does not exist, it is simply ignored. Special prefixes ~/ and ~appdata/ are expanded to the home dir and appdata dir.
  • **options – The options specification: each option consists of a 3-element tuple (default, type, docstring).

Example

config = Config('myconfig', '~appdata/.myconfig.cfg',
                foo=(False, bool, 'Whether to foo'),
                bar=(0.0, float, 'The size of the bar'),
                spam=('1,2,3', [int], 'A tuple of ints'))

With this, options can be set:

  • With an entry foo = 3 in “~appdata/.myconfig.cfg”.
  • With a string "foo = 3" passed at initialization.
  • With an environment variable named MYCONFIG_FOO.
  • With a command line argument --myconfig-foo=3.
  • By doing config.foo = 3, or config['foo'] = 3 in Python.

Notes

  • Option names are case insensitive, except for attribute access and environment variables (the latter must be all uppercase).
  • All values can be set as a Python object or a string; they are automatically converted to the correct type.
  • Each instance gets a docstring that lists all options, so it can easily be used in e.g. Sphynx docs.
load_from_file(filename)

Load config options from a file, as if it was given as a source during initialization. This means that options set via argv, environ or directly will not be influenced.

load_from_string(text, filename='<string>')

Load config options from a string, as if it was given as a source during initialization. This means that options set via argv, environ or directly will not be influenced.

Logging in Flexx

Flexx uses the standard Python logging facilities, but adds functionality, most notably the ability to filter messages by a string or regexp.

flexx.set_log_level(level, match=None)

Set the logging level and match filter

Parameters:
  • level (str, int) – The verbosity of messages to print. If a str, it can be either DEBUG, INFO, WARNING, ERROR, or CRITICAL. Note that these are for convenience and are equivalent to passing in logging.DEBUG, etc.
  • match (str, regexp, None) – String to match. Only those messages that contain match as a substring (and has the appropriate level) will be displayed. Match can also be a compiled regexp.

Notes

If level is DEBUG, the method emitting the log message will be prepended to each log message. Note that if level is DEBUG or if the match option is used, a small overhead is added to each logged message.

class flexx.util.logging.capture_log(level, match=None)

Context manager to capture log messages. Useful for testing. Usage:

with capture_log(level, match) as log:
    ...
# log is a list strings (as they would have appeared in the console)
JavaScript minification
flexx.util.minify.minify(code, remove_whitespace=False)

Very basic minification of JavaScript code. Will likely support more advanced minifcation in the future.

Parameters:
  • code (str) – the JavaScript code to minify.
  • remove_whitespace (bool) – if True, removes all non-functional whitespace. Otherwise remove all trailing whitespace and indents using tabs to preserve space. Default False.

Command line interface

Flexx has a command line interface to perform some simple tasks. Invoke it via python -m flexx. Additional command line arguments can be provided to configure Flexx, see configuring flexx.

Flexx command line interface
  python -m flexx <command> [args]

help            show information on how to use this command.
info            show info on flexx server process corresponding to given port,
log             Start listening to log messages from a server process - STUB
stop            stop the flexx server process corresponding to the given port.
version         print the version number

Configuring Flexx

This page lists the configuration options available to Flexx, implemented via the Config class. Configuration options are read from <appdata>/.flexx.cfg (check flexx.util.config.appdata_dir() for the actual location), and can also be set using environment variables and command line arguments, as explained below. Alternatively, options can be set directly in Python via flexx.config.foo = 3.

flexx.config

Configuration object for flexx

The options below can be set from different sources, and are evaluated in the following order:

  • From the default value.
  • From .cfg or .ini file, or a string in cfg format.
  • From environment variables, e.g. FLEXX_FOO=3.
  • From command-line arguments, e.g. --flexx-foo=3.
  • From setting the config option directly, e.g. config.foo = 3.

Use print(config) to get a summary of the current values and from which sources they were set.

Parameters:
  • browser_stacktrace (bool) – Show server stack traces in browser window (default True)
  • cookie_secret (str) – The secret key to encode cookies. (default ‘flexx_secret’)
  • host_whitelist (str) – Comma separated list of allowed <host>:<port> values to pass cross-origin checks. (default ‘’)
  • hostname (str) – The default hostname to serve apps. (default ‘localhost’)
  • log_level (str) – The log level to use (DEBUG, INFO, WARNING, ERROR) (default ‘info’)
  • port (int) – The default port to serve apps. Zero means auto-select. (default 0)
  • ssl_certfile (str) – The cert file for https server. (default ‘’)
  • ssl_keyfile (str) – The key file for https server. (default ‘’)
  • tornado_debug (bool) – Setting the tornado application debug flag allows autoreload and other debugging features. (default ‘false’)
  • webruntime (str) – The default web runtime to use. Default is “app or browser”. (default ‘’)
  • ws_timeout (int) – If the websocket is idle for this amount of seconds, it is closed. (default 20)

Examples

This page provides a list of examples. Some demonstate a specific application, while others show a tool/technique that is generically useful. In the latter case you can import the widget using e.g. from flexxamples.howtos.editor_cm import CodeEditor.

Note that most examples are written in such a way that they work in the browser (by subclassing Widget). If you are creating a desktop application, you probably want to use PyWidget to create your high-level widgets instead.

About

Release notes

v0.8.0 (26-04-2019)

  • Adds a PyWidget class that can be used as a base class for your high-level widgets. Because it is a PyComponent, this makes it much easier to write apps that fully work in Python (desktop-like apps).
  • The FormLayout uses CSS grid instead of <table>.
  • A new GridLayout widget.
  • A new MultiLineEdit widget.
  • Improvements to docs and guide.
  • Support for freezing Flexx apps to standalone executables (via PyInstaller).

Also see the overview of 0.8 issues and pull request

v0.7.1 (03-12-2018)

  • Improved shutdown behavior (#533).
  • Small fix in App.export (#532).
  • Fix bahevior when navigating back to a Flexx app (#536).

v0.7.0 (02-11-2018)

  • New examples for Openlayers and including local assets (by @ocobacho).
  • Tests, demos and readme are included in the sdist, helping packaging on Linux (by @toddrme2178).
  • Some performance tweaks which should help in larger applications.
  • Add outernode attribute in TreeItem` widget, enabling more powerful subclasses.
  • The Combobox is smarter about the placement of the “dropdown”.
  • A new RangeSlider widget.

Also see the overview of 0.7 issues and pull request

v0.6.2 (04-10-2018)

  • Bugfix in combobox.
  • BSDF check dtype in JS.

v0.6.0 (02-10-2018)

Most notable changes:

  • Add Widget.minsize_from_children property (#497).
  • Update BSDF (data serialization).
  • Widgets van be orphaned upon initialization by setting parent to None (#493)
  • Some internal improvements on the dropdown widget.

Also see the overview of 0.6 issues and pull request

v0.5.0 (13-09-2018)

This release marks the end of the alpha stage of Flexx. Until now, we took the liberty to redesign various parts of Flexx and break the API several times. From now on, we care a lot more about backwards compatibility.

Some highlights of changes from the last release:

  • A major refactoring of the event system.
  • We spun out the PyScript transpiler into the PScript project, as well as the webruntime and dialite project. This means that Flexx itself is focussed on the GUI aspect alone.
  • Added touch support.
  • Dropped the depency on Phosphor.js.
  • A new combined namespace: from flexx import flx.
  • A proper guide in the docs.
  • More examples.

Also see the overview of 0.5 pull request and overview of 0.5 issues corresponding to this release.

v0.4.2 (13-10-2017)

This release was not published to Pypi. It served mainly as a tag right before the big refactoring. There were a lot of improvements, but we felt that the state of Flexx was still very much in flux (no pun intended).

Also see the overview of 0.4.2 pull request and overview of 0.4.2 issues corresponding to this release.

v0.4.1 (10-07-2016)

A few [fixes](https://github.com/flexxui/flexx/milestone/8).

v0.4 (07-07-2016)

A lot of work and major changes compared to the previous release. Most notably:

  • Completely new event system flexx.event replaces flexx.react.
  • System for configure Flexx through config files, env variables and command line arguments.
  • Better logging.
  • More widgets, more examples.
  • Better notebook support.
  • Fixed nasty bug where new profile data was stored on each launch of the XUL runtime.
  • Better support for testing and running Flexx in a separate thread.

Also see the overview of 0.4 pull request and overview of 0.4 issues corresponding to this release.

v0.3.1 (19-02-2016)

A few small fixes, and improvements to distribution. The universal wheel on Pypi for v0.3 did not work on Python 2.7. Flexx now includes a recipe to build a noarch conda package.

Also see the overview of 0.3.1 pull request.

v0.3 (15-02-2016)

The most important changes with respect to the previous release are:

  • Flexx now works on Legacy Python (i.e. Python 2.7). The source code is automatically translated during installation.
  • Improvements to nested FlexLayout on Chrome
  • A command-line tool to stop and get info on running Flexx servers.
  • More tests
  • A new Canvas widget.
  • PyScript uses bound functions for methods and functions without selt/this as first arg.

Also see the overview of 0.3 pull request and overview of 0.3 issues corresponding to this release.

v0.2 (13-10-2015)

We changed a lot, broke API’s, improved things, and probbaly broke other things. Here’s a summary of the most important bits:

  • Set up Travis CI, and added more unit tests.
  • Layout of ui widgets is based on Phosphorjs.
  • Style compliance (and tested on Travis).
  • Refactored PyScript, and made it much more feature complete.
  • PyScript makes use of common ast, and now works on 3.2-3.5, and pypy.
  • We now have a way to include assets (js, css, images).
  • The assets make it possible to e.g. embed a Bokeh plot, or a jQuery widget.

Also see the overview of 0.2 pull request and overview of 0.2 issues corresponding to this release.

v0.1 (27-08-2015)

First release.

Contributing to Flexx

If you like Flexx and want to help out, there’s a few things you can do. First off, feedback; it’s very useful to hear what you like and what you struggle with. Feel free to use the Github issue tracker for this.

You can help by contributing to the documentation, and/or by creating nice examples.

If you would like to help out with the codebase itself, e.g. by fixing bugs, making improvements, or submitting new types of widgets, you probably need to a few extra libraries (don’t worry, it’s ‘nothing fancy):

  • pytest and pytest-cov (get them via conda or pip)
  • flake8 (get it via conda or pip)
  • Nodejs
  • Firefox

We follow the Github workflow:

  • You fork the Github repo and make a clone to your local computer.
  • You update to the latest version: git checkout master && git pull
  • You make a new branch: git checkout -b mywork
  • You make changes to the code and commit these: git commit
  • You push to your fork git push
  • Create a Pull Request from the Github interface.

Freezing Flexx apps

Flexx needs special care when freezing, because it needs access to the Python source code in order to compile it to JavaScript.

The easy way

There is experimental support to make freezing very easy:

from flexx import flx

class Example(flx.Widget):
    def init(self):
        flx.Button(text="Hi there")

if __name__ == "__main__":
    app = flx.App(Example)
    app.freeze("~/Desktop/flexx_apps")
The more explicit way

The above approach does most of the magic behind the scenes. For more control, you can also use a more explicit approach.

First, create a script that represents your application entry point. It is important that this script does not define any new Flexx widgets. It should look something like this:

# Install hook so we we can import modules from source when frozen.
from flexx.util import freeze
freeze.install()

# Run your app as usual
from flexx import flx
from my_module import MyWidget
app = flx.App(MyWidget)
app.launch("firefox-app")
flx.run()

Next, use PyInstaller as usual to create an app directory. Consider using --exclude-module numpy (PyInstaller thinks that Flexx needs Numpy, but this not the case).

Next, copy the source code of the modules that define Flexx widgets. If you run PyInstaller from a script (using PyInstaller.__main__.run()) then you can combine it.

from flexx.util import freeze

freeze.copy_module("flexx", app_dir)  # always
freeze.copy_module("flexxamples", app_dir)  # used something from here?
freeze.copy_module("my_module", app_dir)

That should be it!

Flexx overview

_images/overview.svg

The image above outlines the structure of Flexx. The event module provides a powerful property and event system that makes it easy to connect different parts of your application. Central to the event system is the Component class. The app module runs the server to which the web runtime connects (via a websocket). Further, it extends the Component class into the PyComponent and JsComponent classes. Objects of these classes live in Python and JavaScript respectively, but (can) have a representation on the other side, from which properties can be accessed, and actions be invoked. The ui module defines all widgets (based on JsComponent).

The external webruntime package is used to launch a browser looking like a dektop app. The pscript library is used throughout Flexx to compile Python code to JavaScript.

Motivation

The primary motivation for Flexx is the undeniable fact that the web (i.e. browser technology) has become an increasingly popular method for delivering applications to users, also for (interactive) scientific content.

The purpose of Flexx is to provide a single application framework to create desktop applications and web apps. By making use of browser technology, the library itself can be relatively small and pure Python, making it widely and easily available.

By making use of PScript (Python to JavaScript translation), the entire library is written without (hardly) a line of JavaScript. This makes it easier to develop than if we would have a corresponding “flexx.js” to maintain. Further, it allows users to easily define callback methods that are executed in JavaScript, allowing for higher performance when needed.

Libraries written for Python, but not in Python have a much harder time to survive, because users don’t easily become contributors. This is one of the reasons of the success of e.g. scikit-image, while e.g. Mayavi has a much harder time attracting developers. Since Flexx is written in a combination of Python and PScript, its user community is more likely to take an active role in its development.

Some background on the Flexx event system

Flexx’ event system is quite flexible and designed to cover the needs of a variety of event/messaging mechanisms. But we did not get there in one go.

History

In the early days of Flexx, the event system was based on the ideas of reactive programming, where information supposedly flows through your application. Although this style does have benefits, we found it very unnatural for GUI applications. Therefore we made a major refactoring to build an event system using a more classic property based approach. We build in a bit of asynchronicity to deal with some of the common problems with MVC, and were quite happy. However, as we started building larger applications, the system started showing its limitations. Several months of discussion and design, followed by another several months of coding, resulted in the current event system.

Patterns

This section discusses how the event system relates to some common patterns, and how these can be implemented.

Observer pattern

The idea of the observer pattern is that observers keep track (the state of) of an object, and that an object is agnostic about what it’s tracked by. For example, in a music player, instead of writing code to update the window-title inside the function that starts a song, there would be a concept of a “current song”, and the window would listen for changes to the current song to update the title when it changes.

In flexx.event, a Component object keeps track of its observers (reactions) and notifies them when there are changes. In our music player example, there would be a property “current_song”, and a reaction to take action when it changes.

As is common in the observer pattern, the reactions keep track of the objects that they observe. Therefore both Reaction and Component objects have a dispose() method for cleaning up.

Signals and slots

The Qt GUI toolkit makes use of a mechanism called “signals and slots” as an easy way to connect different components of an application. In flexx.event signals translate to properties and assoctated setter actions, and slots to the reactions that connect to them.

Although signals and slots provide a convenient mechanism, they make it easy to create “spaghetti apps” where the information flows all over the place, which is exactly what frameworks like Flux, Veux and Flexx try to overcome.

Overloadable event handlers

In Qt, the “event system” consists of methods that handles an event, which can be overloaded in subclasses to handle an event differently. In flexx.event, actions and reactions can similarly be re-implemented in subclasses, and these can call the original handler using super() if needed.

Publish-subscribe pattern

In pub-sub, publishers generate messages identified by a ‘topic’, and subscribers can subscribe to such topics. There can be zero or more publishers and zero or more subscribers to any topic.

In flexx.event a Component object can play the role of a broker. Publishers can simply emit events. The event type represents the message topic. Subscribers are represented by handlers.

Indices and tables