Migrate from 0.4 to 0.5
| Migrate from 0.3.1 to 0.4 | Migrate | Migrate from 0.5 to 0.5.1 |
This document contains a migration guide for users of PyMT 0.4 who want to update their PyMT installation to version 0.5. Many changes have been introduced and we've been working hard to improve PyMT. In some places, this unfortunately means some changes to the API (since we're not at version 1.0 yet). To help our beloved users with the migration, this document tries to list all possible things that one might have to change, depending on the situation.
In this document
Configuration File Changes
show_eventstatshas been removed- New
jitter_distanceandjitter_ignore_devicestokens to suppres jittery touches. - New
[widgets]section to control default configuration for specific widgetslist_trigger_distance(MTList widget): Defines the maximum distance a touch might move the list so that the touch events are still sent to the children.list_friction(MTList widget): Defines friction for the list movement. The higher the friction, the more difficult the list is scrolled.list_friction_bound(MTList widget): Defines friction for the case when the user scrolls the list to the left/right/top/bottom boundary.keyboard_type(MTVkeyboard widget): Can be "real" or "virtual". If "real", no virtual keyboard will be shown by default. You can still use your hardware keyboard.
You can check our DevGuide for more details about the new tokens.
CSS and cssutils removal
Our CSS parser has been rewritten from scratch. We're not using cssutils anymore. Parsing is now faster. The parser is dumb and less error-checks are performed. If you experience any issues with CSS, feel free to open an issue!
Events and weakref / weakmethod
PyMT now uses weak references for:
- id <-> widget map
- clock event callbacks
- widget event callbacks
You must be aware of this behavior. If you take this example :
print 'called', dt
getClock().schedule_interval(my_func, .5)
del my_func
- BEFORE: Even if the
delstatement is used, the callback is still called by the clock, because we were keeping a reference tomy_func. - NOW: The function will be really deleted and at the next call, the clock will remove the schedule since the callback does not exist anymore.
The big advantage of this is that your memory is now reclaimed properly.
Safe list iteration
Our old class SafeList() was used to iterate our widget tree and even to remove children while iterating.
We've found that this slowed down the toolkit substantially. After benchmarking, we've come to the conclusion to use
Python's [:] method instead:
for child in self.children.iterate():
pass
# NOW
for child in self.children[:]:
pass
You should do it the same everywhere you're doing a list iteration and modify the list at the same time.
Loader
The Loader has been rewritten and ProxyImage is not changing the image as it did before.
You can check the loaded property on a ProxyImage to know if the image is loaded or not.
OSC
The OSC library API has changed for listening on multiple ports with multiple callbacks:
osc.listen()returns anoscidoscidmust be passed toosc.bind()
Touch
The new Touch-class attributes dxpos and dypos represent the previous position of the touch, and the value is now in the range 0-screenwidth/0-screenheight. (Not from 0-1 as before.)
Widgets
Private attributes
We've started to clean our widgets. Even if it's not finished, some attributes you were using before may be not available anymore.
If the attribute was not designed to be used by another widget, we've prefixed it with _ (that's an underscore).
Double check the documentation about available attributes.
size_hint attribute
The size_hint is used with layout. It defines how the size of your widget will be used or modified by the parent layout.
This attribute works only if the parent of the widget is a Layout object.
Example: Assume that in a BoxLayout with undetermined size, you want to put two widgets:
- First widget should be 75% of the width of the parent
- Second widget should be 25% of the width of the parent
You can write this:
layout.add_widget(MTButton(label='Part 1', size=(.75, 1)))
layout.add_widget(MTButton(label='Part 2', size=(.25, 1)))
size_hint is by default:
(None, None)for all MTWidgets(1, 1)for all MTAbstractLayouts
Drawing
Every widget is now able to draw its own background (i.e., drawRectangle(widget.pos, widget.size)). But it's deactivated by default for the majority of widgets.
For example, if you want to draw the background of a MTWidget, you can activate it with CSS like so:
draw-background: 1;
}
Collision behavior
The function collide_point() now returns False if the widget is not visible.
Lambda properties
The internal implementation of some of our classes' properties has changed in order to increase performance. This means, however, that now you cannot just redefine a setter or getter, you need to also redefine the property:
def _get_x(self):
return self.x
def _set_x(self, x):
self._x = x
x = property(_get_x, _set_x)
class B(A):
def _set_x(self, x):
print 'here', x
super(B, self)._set_x(x)
x = property(A._get_x, _set_x) # This is the important line that redefines the property
These changes have been applied to BaseObject, MTWidget and also to other classes like Touch.
UI
Layouts
Our layouts have been rewritten. If you use it, you may experience some issues. Ensure that:
- You're calling the
on_update()of the layout object. - You don't forget the new
size_hintattribute, which defaults to(1, 1)for layouts. - You checked the layout documentation twice.
- You checked all the examples about layout usage twice.
MTScatter
Scatter has been rewritten from scratch. OpenGL is not used for the internal calculation anymore. We are now using our own transformation library and numpy.
transform_matis now deprecated. Usetransform_glto get the GL matrix of the current transformationMTScatterWidgethas been renamed toMTScatter. Use of the old name is deprecated.
Check MTScatter for more information.
MTLabel / MTButton
MTLabel has been rewritten from scratch. It's now using the same attributes as the Label core object. Refer to the documentation of |Core Label to see how to control the label rendering. Since MTButton is based on MTLabel, the same applies essay structure here.
MTButton
The event on_release is no longer fired if the touch didn't collide with the button when the up-event was dispatched.
XMLWidget
XMLWidget has its own "id to widget" map. If you have id= in your XML, it will be removed. You can use xml.getById(<id>) instead.
We also introduce the method autoconnect(). See this example:
<MTBoxLayout>
<MTButton label='"BUTTON 1"' id='"button1"'/>
<MTButton label='"BUTTON 2"' id='"button2"'/>
</MTBoxLayout
We have 2 buttons, identified by the ids button1 and button2. The autoconnect(<object>) will explore the current object for methods to connect to: "on_" + widget id + event name.
See this Python source:
class MyCustomWidget(MTBoxLayout):
def __init__(self, **kwargs):
super(MyCustomWidget, self).__init__(**kwargs)
xmltext = open('widgets.xml', 'r').read()
xml = XMLWidget(xml=xmltext)
self.add_widget(xml.root())
xml.autoconnect(self)
def on_button1_release(self, *largs):
print 'button1 released'
def on_button2_touch_down(self, touch):
print 'got touch from button 2', touch
You can check XMLWidget for more details about the new tokens.
Deprecated widgets and functions
- MTKineticList is deprecated. You should replace it with the new MTList widget.
- MTScatterWidget was renamed to MTScatter and the old name is deprecated
- MTForm* is removed
- The Matrix class is removed
- draw_gradient from MTWindow is removed
- event stats is removed
