Merge branch 'master' of https://github.com/kivy/kivy into use_launcher_for_windows

This commit is contained in:
vernondcole 2013-09-30 14:33:51 +01:00
commit 0d95003066
44 changed files with 345 additions and 211 deletions

View File

@ -59,15 +59,18 @@ to support at least OpenGL 2.0 ES.
Phones
~~~~~~
- HTC HD2 with NexusHD2-ICS-CM9-HWA Rom (CyanogenMod 9.1.0 -stable-leo) Android 4.0.4
- HTC Desire
- HTC Desire Z
- HTC Desire HD (works with no issues when upgraded to 4.x roms, has random bugs with 2.3)
- HTC Desire SV (Kivy apps run, but there are issues running some apps via the
Kivy Launcher)
- LG (Google) Nexus 4
- LG Optimus S
- LG Optimus V
- Motorola Droid 1
- Motorola Droid 2
- Micromax Canvas 2
- Samsung Galaxy S (mostly works, seems to have some weird OpenGL behaviour,
most notably the kivy splash screen doesn't work)
- Samsumg Galaxy Pocket S5300
@ -82,8 +85,8 @@ Phones
Tablets
~~~~~~~
- Asus EeePad Transformer
- Asus (Google) Nexus 7 2013
- Motorola Xoom
- Samsung Galaxy Note 8.0” (N5100)
- Samsung Galaxy Note 10.1 (N8000) (Kivy Launcher does not install)

49
examples/canvas/circle.py Normal file
View File

@ -0,0 +1,49 @@
# this is for testing angle_stop/angle_start
from kivy.app import App
from kivy.lang import Builder
kv = '''
FloatLayout:
BoxLayout:
BoxLayout:
orientation: 'vertical'
Slider:
id: e1
min: -360.
max: 360.
Label:
text: '{}'.format(e1.value)
BoxLayout:
orientation: 'vertical'
Slider:
id: e2
min: -360.
max: 360.
value: 360
Label:
text: '{}'.format(e2.value)
ToggleButton:
id: e3
text: 'Fast algo\\n(width == height)' if self.state == 'normal' else 'Normal algo\\n(width != height)'
FloatLayout
canvas:
Color:
rgb: 1, 1, 1
Ellipse:
pos: 100, 100
size: 200, 201 if e3.state == 'down' else 200
source: 'data/logo/kivy-icon-512.png'
angle_start: e1.value
angle_end: e2.value
'''
class CircleApp(App):
def build(self):
return Builder.load_string(kv)
CircleApp().run()

View File

@ -55,7 +55,7 @@ the first half of size=(800, 800)::
anim = Animation(pos=(80, 10))
anim &= Animation(size=(800, 800), duration=2.)
anim.start(widget)
Repeating animation
-------------------
@ -70,8 +70,8 @@ To set an animation to repeat simply set the :data:`Sequence.repeat` property to
anim = Animation(...) + Animation(...)
anim.repeat = True
anim.start(widget)
For flow control of animations such as stopping and cancelling use the methods
For flow control of animations such as stopping and cancelling use the methods
already in place in the animation module.
'''
@ -418,8 +418,9 @@ class Sequence(Animation):
self.dispatch('on_progress', widget, progress / 2.)
def on_anim2_complete(self, instance, widget):
'''Repeating logic used with boolean variable "repeat". Added version 1.7.1'''
if self.repeat == True:
'''Repeating logic used with boolean variable "repeat". Added version
1.7.1'''
if self.repeat:
self.anim1.start(widget)
else:
self.dispatch('on_complete', widget)

View File

@ -314,7 +314,8 @@ class Atlas(EventDispatcher):
# now that we've figured out where everything goes, make the output
# images and blit the source images to the approriate locations
Logger.info('Atlas: create an {0}x{1} rgba image'.format(size_w, size_h))
Logger.info('Atlas: create an {0}x{1} rgba image'.format(size_w,
size_h))
outimages = [Image.new('RGBA', (size_w, size_h))
for i in range(0, int(numoutimages))]
for fb in fullboxes:

View File

@ -3,7 +3,8 @@ Compatibility module for Python 2.7 and > 3.3
=============================================
'''
__all__ = ('PY2', 'string_types', 'queue', 'iterkeys', 'itervalues', 'iteritems')
__all__ = ('PY2', 'string_types', 'queue', 'iterkeys',
'itervalues', 'iteritems')
import sys
try:

View File

@ -211,8 +211,8 @@ class Gif(object):
print(" " * 6, "Color resolution: %d" % self.color_resolution)
print(" " * 6, "Sort flag: %r" % self.sort_flag)
print(" " * 6, "Global color table flag: %r" % self.color_table_flag)
print(" " * 22, "...size: %d (%d bytes)" % \
(self.global_color_table_size, self.global_color_table_size * 3))
print(" " * 22, "...size: %d (%d bytes)" %
(self.global_color_table_size, self.global_color_table_size * 3))
print("Background color: %d" % self.background_color)
print("Aspect ratio info: %d" % self.aspect_ratio)

View File

@ -26,7 +26,8 @@ class LabelPygame(LabelBase):
if PY2:
try:
return '|'.join([unicode(self.options[x]) for x in
('font_size', 'font_name_r', 'bold', 'italic')])
('font_size', 'font_name_r',
'bold', 'italic')])
except UnicodeDecodeError:
pass
return '|'.join([str(self.options[x]) for x in

View File

@ -11,6 +11,7 @@ from kivy.core.window import WindowBase
from kivy.base import EventLoop
from kivy.lib.vidcore_lite import bcm, egl
class WindowEglRpi(WindowBase):
def create_window(self):
@ -60,13 +61,12 @@ class WindowEglRpi(WindowBase):
self.egl_info = (display, surface, context)
egl.MakeCurrent(display, surface, surface, context)
def close(self):
egl.Terminate(self.egl_info[0])
def flip(self):
egl.SwapBuffers(self.egl_info[0], self.egl_info[1])
def _mainloop(self):
EventLoop.idle()

View File

@ -21,7 +21,7 @@ class OpacityScrollEffect(DampedScrollEffect):
def on_overscroll(self, *args):
if self.target_widget and self.target_widget.height != 0:
alpha = 1.0 - abs(self.overscroll / float(self.target_widget.height))
alpha = (1.0 -
abs(self.overscroll / float(self.target_widget.height)))
self.target_widget.opacity = min(1, alpha)
self.trigger_velocity_update()

View File

@ -130,8 +130,8 @@ def load(extname, version):
searchpath = [bestpath]
else:
# Didn't find a matching extension
raise ImportError("No extension found that satisfies your criteria: "\
+ "('%s', %s)" % (extname, version))
raise ImportError("No extension found that satisfies your criteria: " +
"('%s', %s)" % (extname, version))
file, pathname, desc = imp.find_module(extname, searchpath)
msg = 'Extension found for ' + repr(extname) + ':\n\t' + str(file) + \

View File

@ -89,7 +89,7 @@ class FactoryBase(object):
'''Unregisters the classnames previously registered via the
register method. This allows the same classnames to be re-used in
different contexts.
.. versionadded:: 1.7.1
'''
for classname in classnames:

View File

@ -15,6 +15,7 @@ cdef extern from "math.h":
double sqrt(double) nogil
double pow(double x, double y) nogil
double atan2(double y, double x) nogil
double tan(double) nogil
cdef extern from "stdlib.h":
ctypedef unsigned long size_t

View File

@ -830,10 +830,14 @@ cdef class Ellipse(Rectangle):
cdef int i, angle_dir
cdef float angle_start, angle_end, angle_range
cdef float x, y, angle, rx, ry, ttx, tty, tx, ty, tw, th
cdef float cx, cy, tangetial_factor, radial_factor, fx, fy
cdef vertex_t *vertices = NULL
cdef unsigned short *indices = NULL
cdef int count = self._segments
if self.w == 0 or self.h == 0:
return
tx = tc[0]
ty = tc[1]
tw = tc[4] - tx
@ -856,7 +860,8 @@ cdef class Ellipse(Rectangle):
angle_dir = 1
else:
angle_dir = -1
# rad = deg * (pi / 180), where pi/180 = 0.0174...
# rad = deg * (pi / 180), where pi / 180 = 0.0174...
angle_start = self._angle_start * 0.017453292519943295
angle_end = self._angle_end * 0.017453292519943295
angle_range = abs(angle_end - angle_start) / self._segments
@ -872,17 +877,48 @@ cdef class Ellipse(Rectangle):
vertices[0].t0 = tty
indices[0] = 0
for i in xrange(1, count + 2):
angle = angle_start + (angle_dir * (i - 1) * angle_range)
x = (self.x+rx)+ (rx*sin(angle))
y = (self.y+ry)+ (ry*cos(angle))
ttx = ((x-self.x)/self.w)*tw + tx
tty = ((y-self.y)/self.h)*th + ty
vertices[i].x = x
vertices[i].y = y
vertices[i].s0 = ttx
vertices[i].t0 = tty
indices[i] = i
if rx == ry and self.angle_start == 0 and self.angle_end == 360:
# super fast version
# credits goes to: http://slabode.exofire.net/circle_draw.shtml
# there is few issues with angle, so until fixed, allow this to work
# only on "default" ellipse
tangetial_factor = tan(angle_range)
radial_factor = cos(angle_range)
cx = self.x + rx
cy = self.y + ry
x = rx * sin(angle_start)
y = rx * cos(angle_start)
for i in xrange(1, count + 2):
ttx = ((rx + x) / self.w) * tw + tx
tty = ((ry + y) / self.h) * th + ty
vertices[i].x = cx + x
vertices[i].y = cy + y
vertices[i].s0 = ttx
vertices[i].t0 = tty
indices[i] = i
fx = -y
fy = x
x += fx * tangetial_factor
y += fy * tangetial_factor
x *= radial_factor
y *= radial_factor
else:
for i in xrange(1, count + 2):
angle = angle_start + (angle_dir * (i - 1) * angle_range)
x = (self.x + rx) + (rx * sin(angle))
y = (self.y + ry) + (ry * cos(angle))
ttx = ((x - self.x) / self.w) * tw + tx
tty = ((y - self.y) / self.h) * th + ty
vertices[i].x = x
vertices[i].y = y
vertices[i].s0 = ttx
vertices[i].t0 = tty
indices[i] = i
self.batch.set_data(vertices, count + 2, indices, count + 2)

View File

@ -222,7 +222,8 @@ else:
invert_x = int(bool(drs('invert_x', 0)))
invert_y = int(bool(drs('invert_y', 0)))
def process_as_multitouch(tv_sec, tv_usec, ev_type, ev_code, ev_value):
def process_as_multitouch(tv_sec, tv_usec, ev_type,
ev_code, ev_value):
# sync event
if ev_type == EV_SYN:
if ev_code == SYN_MT_REPORT:
@ -272,11 +273,13 @@ else:
process([point])
elif ev_type == EV_REL:
if ev_code == 0:
point['x'] = min(1., max(0., point['x'] + ev_value / 1000.))
point['x'] = min(1., max(0.,
point['x'] + ev_value / 1000.))
elif ev_code == 1:
point['y'] = min(1., max(0., point['y'] - ev_value / 1000.))
point['y'] = min(1., max(0.,
point['y'] - ev_value / 1000.))
elif ev_type == EV_KEY:
buttons = {
@ -303,7 +306,9 @@ else:
point['_avoid'] = True
def process(points):
actives = [args['id'] for args in points if 'id' in args and not '_avoid' in args]
actives = [args['id']
for args in points
if 'id' in args and not '_avoid' in args]
for args in points:
tid = args['id']
try:

View File

@ -121,7 +121,7 @@ else:
self.provider = 'mtdev'
self.match = None
self.input_path = '/sys/class/input'
self.select_all = True if _is_rpi else False
self.select_all = True if _is_rpi else False
self.use_regex = False
self.args = []

View File

@ -250,7 +250,8 @@ class Tuio2dCurMotionEvent(TuioMotionEvent):
self.sx, self.sy = list(map(float, args[0:2]))
self.profile = ('pos', )
elif len(args) == 5:
self.sx, self.sy, self.X, self.Y, self.m = list(map(float, args[0:5]))
self.sx, self.sy, self.X, self.Y, self.m = list(map(float,
args[0:5]))
self.Y = -self.Y
self.profile = ('pos', 'mov', 'motacc')
else:

View File

@ -1,7 +1,7 @@
'''
Support for WM_PEN messages (Windows platform)
==============================================
'''
'''
__all__ = ('WM_PenProvider', 'WM_Pen')

View File

@ -285,7 +285,7 @@ subclasses.
The syntax look like:
.. code-block:: kv
# Simple inheritance
<NewWidget@Button>:
...
@ -481,7 +481,7 @@ When you are creating a context:
#. you cannot use references other than "root":
.. code-block:: kv
<MyRule>:
Widget:
id: mywidget
@ -492,7 +492,7 @@ When you are creating a context:
#. all the dynamic part will be not understood:
.. code-block:: kv
<MyRule>:
Template:
ctxkey: 'value 1' if root.prop1 else 'value2' # << even if
@ -651,7 +651,7 @@ _delayed_calls = []
# widget is deleted
_handlers = {}
class ProxyApp(object):
# proxy app object
# taken from http://code.activestate.com/recipes/496741-object-proxying/
@ -1225,16 +1225,19 @@ class Parser(object):
return objects, []
def get_proxy(widget):
try:
return widget.proxy_ref
except AttributeError:
return widget
def custom_callback(__kvlang__, idmap, *largs, **kwargs):
idmap['args'] = largs
exec(__kvlang__.co_value, idmap)
def create_handler(iself, element, key, value, rule, idmap, delayed=False):
locals()['__kvlang__'] = rule
@ -1590,7 +1593,8 @@ class BuilderBase(object):
# append the properties and handlers to our final resolution task
if rule.properties:
rctx['set'].append((widget.proxy_ref, list(rule.properties.values())))
rctx['set'].append((widget.proxy_ref,
list(rule.properties.values())))
if rule.handlers:
rctx['hdl'].append((widget.proxy_ref, rule.handlers))

View File

@ -377,7 +377,7 @@ class LoaderBase(object):
def image(self, filename, load_callback=None, post_callback=None, **kwargs):
'''Load a image using the Loader. A ProxyImage is returned with a
loading image. You can use it as follows::
from kivy.app import App
from kivy.uix.image import Image
from kivy.loader import Loader
@ -478,7 +478,7 @@ else:
def stop(self):
self.running = False
self.tasks.join()
self.tasks.join()
class LoaderThreadPool(LoaderBase):
def __init__(self):

View File

@ -29,7 +29,7 @@ Usage
For normal module usage, please see the :mod:`~kivy.modules` documentation.
The Inspector, however, can also be imported and used just like a normal
The Inspector, however, can also be imported and used just like a normal
python module. This has the added advantage of being able to activate and
deactivate the module programmatically::

View File

@ -1,5 +1,4 @@
'''
Keybinding
'''Keybinding
==========
This module forces the mapping of some keys to functions:
@ -15,9 +14,9 @@ Usage
For normal module usage, please see the :mod:`~kivy.modules` documentation.
The Keybinding module, however, can also be imported and used just like a normal
python module. This has the added advantage of being able to activate and
deactivate the module programmatically::
The Keybinding module, however, can also be imported and used just
like a normal python module. This has the added advantage of being
able to activate and deactivate the module programmatically::
from kivy.app import App
from kivy.uix.button import Button
@ -25,7 +24,7 @@ deactivate the module programmatically::
from kivy.core.window import Window
class Demo(App):
def build(self):
button = Button(text="Hello")
keybinding.start(Window, button)

View File

@ -1,5 +1,4 @@
'''
Screen
'''Screen
======
This module changes some environement and configuration variables
@ -20,14 +19,15 @@ To simulate a high-density screen such as HTC One X, in portrait::
To simulate the iPad 2 screen::
python main.py -m screen:ipad
If the generated window is too large, you can specify a scale::
python main.py -m screen:note2,portrait,scale=.75
Note that to display your contents correctly on a scaled window you must
consistently use units 'dp' and 'sp' throughout your app. See :mod:`~kiv.metrics`
for more details.
Note that to display your contents correctly on a scaled window you
must consistently use units 'dp' and 'sp' throughout your app. See
:mod:`~kiv.metrics` for more details.
'''
import sys

View File

@ -197,7 +197,8 @@ for fruit_record in fruit_data_list_of_dicts:
dict({'name': fruit_record['name'],
'Serving Size': fruit_record['Serving Size'],
'is_selected': fruit_record['is_selected']},
**dict(list(zip(list(attributes_and_units.keys()), fruit_record['data']))))
**dict(list(zip(list(attributes_and_units.keys()),
fruit_record['data']))))
class CategoryItem(SelectableDataItem):

View File

@ -1,5 +1,5 @@
#
# Bug fixed:
# Bug fixed:
# - put utf-8 in string, and validate -> no more crash due to str() encoding
# - put utf-8 in string, validate, close, open the app and edit the value -> no
# more weird space due to ascii->utf8 encoding.
@ -30,11 +30,13 @@ data = '''
]
'''
class UnicodeIssueSetting(App):
def build_config(self, config):
config.add_section('test')
config.setdefault('test', 'string', 'Hello world')
config.setdefault('test', 'path', '/')
def build(self):
s = Settings()
s.add_json_panel('Test Panel', self.config, data=data)

View File

@ -2,14 +2,15 @@ import unittest
from kivy.uix.stacklayout import StackLayout
from kivy.uix.widget import Widget
class PaddingSpacingTestCase(unittest.TestCase):
def test_tb_lr_stacklayout(self):
stacklayout = StackLayout(
orientation='tb-lr',
size=(200, 200),
padding=20,
spacing=10,
)
orientation='tb-lr',
size=(200, 200),
padding=20,
spacing=10,
)
widget = Widget(width=100, size_hint=(0.2, 0.4))
stacklayout.add_widget(widget)

View File

@ -173,7 +173,8 @@ for fruit_record in fruit_data_list_of_dicts:
dict({'name': fruit_record['name'],
'Serving Size': fruit_record['Serving Size'],
'is_selected': fruit_record['is_selected']},
**dict(list(zip(list(attributes_and_units.keys()), fruit_record['data']))))
**dict(list(zip(list(attributes_and_units.keys()),
fruit_record['data']))))
class CategoryItem(SelectableDataItem):

View File

@ -58,7 +58,7 @@ import sys
def upload(ffile, project_name, user_name, password, summary, labels=None):
"""Upload a file to a Google Code project's file server.
Args:
file: The local path to the file.
project_name: The name of your project on Google Code.
@ -88,9 +88,8 @@ def upload(ffile, project_name, user_name, password, summary, labels=None):
upload_host = '%s.googlecode.com' % project_name
upload_uri = '/files'
auth_token = base64.b64encode('%s:%s'% (user_name, password))
headers = {
'Authorization': 'Basic %s' % auth_token,
auth_token = base64.b64encode('%s:%s' % (user_name, password))
headers = {'Authorization': 'Basic %s' % auth_token,
'User-Agent': 'Googlecode.com uploader v0.9.4',
'Content-Type': content_type,
}
@ -123,8 +122,7 @@ def encode_upload_request(fields, file_path):
# Add the metadata about the upload first
for key, value in fields:
body.extend(
['--' + BOUNDARY,
body.extend(['--' + BOUNDARY,
'Content-Disposition: form-data; name="%s"' % key,
'',
value,
@ -137,10 +135,11 @@ def encode_upload_request(fields, file_path):
file_content = f.read()
f.close()
body.extend(
['--' + BOUNDARY,
'Content-Disposition: form-data; name="filename"; filename="%s"' % file_name,
# The upload server determines the mime-type, no need to set it.
body.extend(['--' + BOUNDARY,
('Content-Disposition: form-data; name="filename";'
'filename="%s"') % file_name,
# The upload server determines the mime-type,
# no need to set it.
'Content-Type: application/octet-stream',
'',
file_content,
@ -155,7 +154,8 @@ def encode_upload_request(fields, file_path):
def upload_find_auth(file_path, project_name, summary, labels=None,
user_name=None, password=None, tries=3):
"""Find credentials and upload a file to a Google Code project's file server.
"""Find credentials and upload a file to a Google Code project's file
server.
file_path, project_name, summary, and labels are passed as-is to upload.
@ -167,6 +167,7 @@ def upload_find_auth(file_path, project_name, summary, labels=None,
config_dir: Path to Subversion configuration directory, 'none', or None.
user_name: Your Google account name.
tries: How many attempts to make.
"""
if user_name is None or password is None:
from netrc import netrc
@ -185,14 +186,18 @@ def upload_find_auth(file_path, project_name, summary, labels=None,
sys.stdout.flush()
user_name = sys.stdin.readline().rstrip()
if password is None:
# Read password if not loaded from svn config, or on subsequent tries.
# Read password if not loaded from svn config, or on
# subsequent tries.
print('Please enter your googlecode.com password.')
print('** Note that this is NOT your Gmail account password! **')
print('It is the password you use to access Subversion repositories,')
print('and can be found here: http://code.google.com/hosting/settings')
print('It is the password you use to access Subversion'
'repositories,')
print('and can be found here:'
'http://code.google.com/hosting/settings')
password = getpass.getpass()
status, reason, url = upload(file_path, project_name, user_name, password,
status, reason, url = upload(file_path, project_name,
user_name, password,
summary, labels)
# Returns 403 Forbidden instead of 401 Unauthorized for bad
# credentials as of 2007-07-17.

View File

@ -326,8 +326,10 @@ class Accordion(Widget):
'horizontal', 'vertical'))
'''Orientation of the layout.
:data:`orientation` is an :class:`~kivy.properties.OptionProperty` and
defaults to 'horizontal'. Can take a value of 'vertical' or 'horizontal'.
:data:`orientation` is an :class:`~kivy.properties.OptionProperty`
and defaults to 'horizontal'. Can take a value of 'vertical' or
'horizontal'.
'''
anim_duration = NumericProperty(.25)
@ -350,10 +352,10 @@ class Accordion(Widget):
min_space = NumericProperty('44dp')
'''Minimum space to use for the title of each item. This value is
automatically set for each child every time the layout event occurs.
automatically set for each child every time the layout event occurs.
:data:`min_space` is a :class:`~kivy.properties.NumericProperty` and
defaults to 44 (px).
defaults to 44 (px).
'''
def __init__(self, **kwargs):
@ -366,7 +368,6 @@ class Accordion(Widget):
pos=self._trigger_layout,
min_space=self._trigger_layout)
def add_widget(self, widget, *largs):
if not isinstance(widget, AccordionItem):
raise AccordionException('Accordion accept only AccordionItem')

View File

@ -61,7 +61,8 @@ You can check the `examples/widgets/boxlayout_poshint.py` for a live example.
__all__ = ('BoxLayout', )
from kivy.uix.layout import Layout
from kivy.properties import NumericProperty, OptionProperty, VariableListProperty
from kivy.properties import (NumericProperty, OptionProperty,
VariableListProperty)
class BoxLayout(Layout):

View File

@ -39,6 +39,7 @@ from kivy.uix.label import Label
from kivy.properties import StringProperty, ListProperty
from kivy.uix.behaviors import ButtonBehavior
class Button(ButtonBehavior, Label):
'''Button class, see module documentation for more information.

View File

@ -17,7 +17,7 @@ Basic example
A button with a dropdown list of 10 possible values. All the buttons within the
dropdown list will trigger the dropdown :meth:`DropDown.select` method. After
being called, the main button text will display the selection of the
being called, the main button text will display the selection of the
dropdown. ::
from kivy.uix.dropdown import DropDown
@ -87,6 +87,7 @@ __all__ = ('DropDown', )
from kivy.uix.scrollview import ScrollView
from kivy.properties import ObjectProperty, NumericProperty, BooleanProperty
from kivy.core.window import Window
from kivy.lang import Builder
Builder.load_string('''
@ -164,8 +165,14 @@ class DropDown(ScrollView):
def __init__(self, **kwargs):
self._win = None
super(DropDown, self).__init__(**kwargs)
Window.bind(on_key_down=self.on_key_down)
self.bind(size=self._reposition)
def on_key_down(self, instance, key, scancode, codepoint, modifiers):
if key == 27 and self.get_parent_window():
self.dismiss()
return True
def on_container(self, instance, value):
self.container.bind(minimum_size=self._container_minimum_size)
@ -250,6 +257,8 @@ class DropDown(ScrollView):
def on_touch_up(self, touch):
if super(DropDown, self).on_touch_up(touch):
return True
if 'button' in touch.profile and touch.button.startswith('scroll'):
return
self.dismiss()
def _reposition(self, *largs):

View File

@ -191,9 +191,9 @@ class FileChooserController(FloatLayout):
[seq] matches any character in seq
[!seq] matches any character not in seq
========== =================================
#. Callbacks
You can specify a function that will be called for each file. The
callback will be passed the folder and file name as the first and second
parameters respectively. It should return True to indicate a match and

View File

@ -2,7 +2,7 @@
Float Layout
============
The :class:`FloatLayout` class will only honor the :data:`Widget.pos_hint` and
The :class:`FloatLayout` class honors only the :data:`Widget.pos_hint` and
:data:`Widget.size_hint` attributes.
.. only:: html
@ -15,18 +15,18 @@ The :class:`FloatLayout` class will only honor the :data:`Widget.pos_hint` and
.. image:: images/floatlayout.png
:align: right
For example, if you create a FloatLayout with size a of (300, 300)::
For example, say you create a FloatLayout with a size of (300, 300)::
layout = FloatLayout(size=(300, 300))
By default, all widgets have size_hint=(1, 1), so this button will have the
same size as the layout::
By default, all widgets have their size_hint=(1, 1), so this button will adopt
the same size as the layout::
button = Button(text='Hello world')
layout.add_widget(button)
To create a button of 50% width and 25% height of the layout and positioned at
(20, 20), you can do::
To create a button 50% of the width and 25% of the height of the layout and
positioned at (20, 20), you can do::
button = Button(
text='Hello world',
@ -46,8 +46,8 @@ If you want to create a button that will always be the size of layout minus
.. warning::
If you are not using pos_hint, you must handle the position of
children: If the float layout is moving, you must handle moving
If you are not using pos_hint, you must handle the positioning of the
children: If the float layout is moving, you must handle moving the
children too.
'''

View File

@ -14,20 +14,20 @@ Grid Layout
.. versionadded:: 1.0.4
:class:`GridLayout` arranges children in a matrix. It takes the available space
and divides it into columns and rows, then adds widgets to the resulting
The :class:`GridLayout` arranges children in a matrix. It takes the available
space and divides it into columns and rows, then adds widgets to the resulting
"cells".
.. versionadded:: 1.0.7
The implementation has changed to use widget size_hint for calculating
column/row sizes. `uniform_width` and `uniform_height` have been removed,
and others properties have added to give you more control.
The implementation has changed to use the widget size_hint for calculating
column/row sizes. `uniform_width` and `uniform_height` have been removed
and other properties have added to give you more control.
Background
----------
Unlike many other toolkits, you cannot explicitly place a widget at a specific
column/row. Each child is automatically assigned a position, depending on the
Unlike many other toolkits, you cannot explicitly place a widget in a specific
column/row. Each child is automatically assigned a position determined by the
layout configuration and the child's index in the children list.
A GridLayout must always have at least one input constraint:
@ -42,17 +42,17 @@ The column width/row height are determined in 3 steps:
- The initial size is given by the :data:`col_default_width` and
:data:`row_default_height` properties. To customize the size of a single
column or row, use :data:`cols_minimum` or :data:`rows_minimum`.
- Then the `size_hint_x`/`size_hint_y` of the child are taken into account.
- The `size_hint_x`/`size_hint_y` of the children are taken into account.
If no widgets have a size hint, the maximum size is used for all children.
- You can force the default size by setting the :data:`col_force_default`
or :data:`row_force_default` property. This will force the layout to
ignore the `width` and `size_hint` properties of children and use the
default size.
Usage of GridLayout
-------------------
Using a GridLayout
------------------
In the example below, all widgets will get an equal size. By default,
In the example below, all widgets will have an equal size. By default, the
`size_hint` is (1, 1), so a Widget will take the full size of the parent::
layout = GridLayout(cols=2)
@ -63,7 +63,8 @@ In the example below, all widgets will get an equal size. By default,
.. image:: images/gridlayout_1.jpg
Now, let's fix the size of Hello buttons to 100px instead of using size_hint 1::
Now, let's fix the size of Hello buttons to 100px instead of using
size_hint_x=1::
layout = GridLayout(cols=2)
layout.add_widget(Button(text='Hello 1', size_hint_x=None, width=100))
@ -95,7 +96,7 @@ from math import ceil
def nmax(*args):
'''(internal) Implementation of a max() function that support None.
'''(internal) Implementation of a max() function that supports None.
'''
# merge into one list
args = [x for x in args if x is not None]
@ -103,7 +104,7 @@ def nmax(*args):
class GridLayoutException(Exception):
'''Exception for errors in the grid layout manipulation.
'''Exception for errors if the grid layout manipulation fails.
'''
pass
@ -117,13 +118,13 @@ class GridLayout(Layout):
spacing also accepts a one argument form [spacing].
:data:`spacing` is a :class:`~kivy.properties.VariableListProperty`, default to
[0, 0].
:data:`spacing` is a
:class:`~kivy.properties.VariableListProperty`, default to [0, 0].
'''
padding = VariableListProperty([0, 0, 0, 0])
'''Padding between layout box and children: [padding_left, padding_top,
padding_right, padding_bottom].
'''Padding between the layout box and it's children: [padding_left,
padding_top, padding_right, padding_bottom].
padding also accepts a two argument form [padding_horizontal,
padding_vertical] and a one argument form [padding].
@ -132,8 +133,8 @@ class GridLayout(Layout):
Replaced NumericProperty with VariableListProperty.
:data:`padding` is a :class:`~kivy.properties.VariableListProperty`, default to
[0, 0, 0, 0].
:data:`padding` is a :class:`~kivy.properties.VariableListProperty` and
defaults to [0, 0, 0, 0].
'''
cols = BoundedNumericProperty(None, min=0, allow_none=True)
@ -141,10 +142,11 @@ class GridLayout(Layout):
.. versionadded:: 1.0.8
Change from NumericProperty to BoundedNumericProperty. You cannot set a
negative value anymore.
Changed from a NumericProperty to BoundedNumericProperty. You can no
longer set this to a negative value.
:data:`cols` is a :class:`~kivy.properties.NumericProperty`, default to 0.
:data:`cols` is a :class:`~kivy.properties.NumericProperty` and defaults to
0.
'''
rows = BoundedNumericProperty(None, min=0, allow_none=True)
@ -152,19 +154,20 @@ class GridLayout(Layout):
.. versionadded:: 1.0.8
Change from NumericProperty to BoundedNumericProperty. You cannot set a
negative value anymore.
Changed from a NumericProperty to a BoundedNumericProperty. You can no
longer set this to a negative value.
:data:`rows` is a :class:`~kivy.properties.NumericProperty`, default to 0.
:data:`rows` is a :class:`~kivy.properties.NumericProperty` and defaults to
0.
'''
col_default_width = NumericProperty(0)
'''Default minimum size to use for column.
'''Default minimum size to use for a column.
.. versionadded:: 1.0.7
:data:`col_default_width` is a :class:`~kivy.properties.NumericProperty`,
default to 0.
:data:`col_default_width` is a :class:`~kivy.properties.NumericProperty`
and defaults to 0.
'''
row_default_height = NumericProperty(0)
@ -172,46 +175,46 @@ class GridLayout(Layout):
.. versionadded:: 1.0.7
:data:`row_default_height` is a :class:`~kivy.properties.NumericProperty`,
default to 0.
:data:`row_default_height` is a :class:`~kivy.properties.NumericProperty`
and defaults to 0.
'''
col_force_default = BooleanProperty(False)
'''If True, ignore the width and size_hint_x of the child, and use the
'''If True, ignore the width and size_hint_x of the child and use the
default column width.
.. versionadded:: 1.0.7
:data:`col_force_default` is a :class:`~kivy.properties.BooleanProperty`,
default to False.
:data:`col_force_default` is a :class:`~kivy.properties.BooleanProperty`
and defaults to False.
'''
row_force_default = BooleanProperty(False)
'''If True, ignore the height and size_hint_y of the child, and use the
'''If True, ignore the height and size_hint_y of the child and use the
default row height.
.. versionadded:: 1.0.7
:data:`row_force_default` is a :class:`~kivy.properties.BooleanProperty`,
default to False.
:data:`row_force_default` is a :class:`~kivy.properties.BooleanProperty`
and defaults to False.
'''
cols_minimum = DictProperty({})
'''List of minimum size for each column.
'''List of minimum sizes for each column.
.. versionadded:: 1.0.7
:data:`cols_minimum` is a :class:`~kivy.properties.DictProperty`, default
to {}
:data:`cols_minimum` is a :class:`~kivy.properties.DictProperty` and
defaults to {}.
'''
rows_minimum = DictProperty({})
'''List of minimum size for each row.
'''List of minimum sizes for each row.
.. versionadded:: 1.0.7
:data:`rows_minimum` is a :class:`~kivy.properties.DictProperty`, default
to {}
:data:`rows_minimum` is a :class:`~kivy.properties.DictProperty` and
defaults to {}.
'''
minimum_width = NumericProperty(0)
@ -219,8 +222,8 @@ class GridLayout(Layout):
.. versionadded:: 1.0.8
:data:`minimum_width` is a :class:`kivy.properties.NumericProperty`, default
to 0.
:data:`minimum_width` is a :class:`kivy.properties.NumericProperty` and
defaults to 0.
'''
minimum_height = NumericProperty(0)
@ -228,8 +231,8 @@ class GridLayout(Layout):
.. versionadded:: 1.0.8
:data:`minimum_height` is a :class:`kivy.properties.NumericProperty`,
default to 0.
:data:`minimum_height` is a :class:`kivy.properties.NumericProperty` and
defaults to 0.
'''
minimum_size = ReferenceListProperty(minimum_width, minimum_height)

View File

@ -17,16 +17,16 @@ the :class:`AsyncImage` subclass::
Alignment
---------
By default, the image is centered and fit inside the widget bounding box.
By default, the image is centered and fits inside the widget bounding box.
If you don't want that, you can inherit from Image and create your own style.
For example, if you want your image to take the same size of your widget, you
can do::
For example, if you want your image to be the same size as your widget, you
could do::
class FullImage(Image):
pass
And in your kivy language file, you can do::
And in your kivy language file::
<FullImage>:
canvas:
@ -57,7 +57,7 @@ class Image(Widget):
source = StringProperty(None)
'''Filename / source of your image.
:data:`source` is a :class:`~kivy.properties.StringProperty`, default to
:data:`source` is a :class:`~kivy.properties.StringProperty` and defaults to
None.
'''
@ -65,11 +65,11 @@ class Image(Widget):
'''Texture object of the image.
Depending of the texture creation, the value will be a
:class:`~kivy.graphics.texture.Texture` or
:class:`~kivy.graphics.texture.Texture` or a
:class:`~kivy.graphics.texture.TextureRegion` object.
:data:`texture` is a :class:`~kivy.properties.ObjectProperty`, default to
None.
:data:`texture` is a :class:`~kivy.properties.ObjectProperty` and defaults
to None.
'''
texture_size = ListProperty([0, 0])
@ -77,8 +77,8 @@ class Image(Widget):
.. warning::
The texture size is set after the texture property. So if you listen on
the change to :data:`texture`, the property texture_size will not be
The texture size is set after the texture property. So if you listen to
the change on :data:`texture`, the property texture_size will not be
up-to-date. Use self.texture.size instead.
'''
@ -88,31 +88,31 @@ class Image(Widget):
return 1.
mipmap = BooleanProperty(False)
'''Indicate if you want OpenGL mipmapping to be applied on the texture.
'''Indicate if you want OpenGL mipmapping to be applied to the texture.
Read :ref:`mipmap` for more information.
.. versionadded:: 1.0.7
:data:`mipmap` is a :class:`~kivy.properties.BooleanProperty`, default to
False.
:data:`mipmap` is a :class:`~kivy.properties.BooleanProperty` and defaults
to False.
'''
image_ratio = AliasProperty(get_image_ratio, None, bind=('texture', ))
'''Ratio of the image (width / float(height).
:data:`image_ratio` is a :class:`~kivy.properties.AliasProperty`, and is
:data:`image_ratio` is a :class:`~kivy.properties.AliasProperty` and is
read-only.
'''
color = ListProperty([1, 1, 1, 1])
'''Image color, in the format (r, g, b, a). This attribute can be used to
'tint' an image. Be careful, if the source image is not gray/white, the
'tint' an image. Be careful: if the source image is not gray/white, the
color will not really work as expected.
.. versionadded:: 1.0.6
:data:`color` is a :class:`~kivy.properties.ListProperty`, default to [1, 1,
1, 1].
:data:`color` is a :class:`~kivy.properties.ListProperty` and defaults to
[1, 1, 1, 1].
'''
allow_stretch = BooleanProperty(False)
@ -122,52 +122,52 @@ class Image(Widget):
.. versionadded:: 1.0.7
:data:`allow_stretch` is a :class:`~kivy.properties.BooleanProperty`,
default to False
:data:`allow_stretch` is a :class:`~kivy.properties.BooleanProperty` and
defaults to False.
'''
keep_ratio = BooleanProperty(True)
'''If False along with allow_stretch being True, the normalized image
size will be maximized to fit in the image box, disregarding the aspect
size will be maximized to fit in the image box and ignores the aspect
ratio of the image.
Otherwise, if the box is too tall, the image will not be stretched more
than 1:1 pixels.
.. versionadded:: 1.0.8
:data:`keep_ratio` is a :class:`~kivy.properties.BooleanProperty`,
default to True
:data:`keep_ratio` is a :class:`~kivy.properties.BooleanProperty` and
defaults to True.
'''
keep_data = BooleanProperty(False)
'''If true the underlaying _coreimage have to keep the raw image data.
Useful to perform pixel based collision detection
'''If True, the underlaying _coreimage will store the raw image data.
This is useful when performing pixel based collision detection.
.. versionadded:: 1.3.0
:data:`keep_data` is a :class:`~kivy.properties.BooleanProperty`, default
to False
:data:`keep_data` is a :class:`~kivy.properties.BooleanProperty` and
defaults to False.
'''
anim_delay = NumericProperty(.25)
'''Delay of animation if the image is sequenced (like an animated gif).
If the anim_delay is set to -1, the animation will be stopped.
'''Delay the animation if the image is sequenced (like an animated gif).
If anim_delay is set to -1, the animation will be stopped.
.. versionadded:: 1.0.8
:data:`anim_delay` is a :class:`~kivy.properties.NumericProperty`, default
to .25 (4 FPS)
:data:`anim_delay` is a :class:`~kivy.properties.NumericProperty` and
defaults to 0.25 (4 FPS).
'''
nocache = BooleanProperty(False)
'''If this property is set True, the image will not be added to the
internal cache anymore. (the cache will simply ignore any calls trying to
append the core image)
internal cache. The cache will simply ignore any calls trying to
append the core image.
.. versionadded:: 1.6.0
:data:`nocache` is a :class:`~kivy.properties.BooleanProperty`, default
to False
:data:`nocache` is a :class:`~kivy.properties.BooleanProperty` and defaults
to False.
'''
def get_norm_image_size(self):
@ -201,10 +201,10 @@ class Image(Widget):
'texture', 'size', 'image_ratio', 'allow_stretch'))
'''Normalized image size within the widget box.
This size will always be fit to the widget size, and will preserve the image
This size will always fit the widget size and will preserve the image
ratio.
:data:`norm_image_size` is a :class:`~kivy.properties.AliasProperty`, and is
:data:`norm_image_size` is a :class:`~kivy.properties.AliasProperty` and is
read-only.
'''
@ -250,7 +250,7 @@ class Image(Widget):
def reload(self):
'''Reload image from disk. This facilitates re-loading of
image from disk in case contents change.
images from disk in case the image content changes.
.. versionadded:: 1.3.0

View File

@ -232,8 +232,8 @@ class Label(Widget):
.. versionadded:: 1.8.0
:data:`disabled_color` is a :class:`~kivy.properties.ListProperty`, default to [1, 1,
1, .5].
:data:`disabled_color` is a :class:`~kivy.properties.ListProperty`,
default to [1, 1, 1, .5].
'''
text = StringProperty('')

View File

@ -23,9 +23,9 @@ relative to the containing layout.
Prior to version 1.7.0 The :class:`RelativeLayout` was implemented as a
:class`FloatLayout` inside a :class:`Scatter`. This behaviour/widget has
been renamed to `ScatterLayout`. The :class:`RelativeLayout` now only
supports relative position (and can't be rotated, scaled or translated on
a multitouch system using two or more fingers), so that the implementation
can be optimized and avoid the heavier calculations from :class:`Scatter`
supports relative position (and can't be rotated, scaled or translated on
a multitouch system using two or more fingers), so that the implementation
can be optimized and avoid the heavier calculations from :class:`Scatter`
(e.g. inverse matrix, recaculating multiple properties,etc)
'''

View File

@ -97,7 +97,7 @@ from kivy.graphics.transformation import Matrix
class Scatter(Widget):
'''Scatter class. See module documentation for more information.
:Events:
`on_transform_with_touch`:
Fired when the scatter has been transformed by user touch
@ -397,7 +397,7 @@ class Scatter(Widget):
dy = dy / self.translation_touches
self.apply_transform(Matrix().translate(dx, dy, 0))
changed = True
if len(self._touches) == 1:
return changed
@ -499,7 +499,7 @@ class Scatter(Widget):
# stop propagating if its within our bounds
if self.collide_point(x, y):
return True
def on_transform_with_touch(self, touch):
'''
Called when a touch event has transformed the scatter widget.

View File

@ -10,13 +10,13 @@ position = (0,0), the child widget will also move, when you change the
position of the :class:`ScatterLayout`. The child widget's coordinates remain
(0,0), i.e. they are relative to the containing layout.
However, since :class:`ScatterLayout` is implemented using a :class:`Scatter`
widget, you can also translate, rotate and scale the layout using touches
(mouse or fingers) just like a normal :class:`Scatter` widget, and the child
However, since :class:`ScatterLayout` is implemented using a :class:`Scatter`
widget, you can also translate, rotate and scale the layout using touches
(mouse or fingers) just like a normal :class:`Scatter` widget, and the child
widgets will behave as expected.
In contrast with a Scatter, the Layout favours 'hint' properties, such as
size_hint, size_hint_x, size_hint_y and pos_hint.
size_hint, size_hint_x, size_hint_y and pos_hint.
..note::

View File

@ -403,7 +403,7 @@ class ShaderTransition(TransitionBase):
def make_screen_fbo(self, screen):
fbo = Fbo(size=screen.size)
with fbo:
ClearColor(0, 0, 0, 0)
ClearColor(0, 0, 0, 1)
ClearBuffers()
fbo.add(screen.canvas)
with fbo.before:
@ -817,6 +817,7 @@ class ScreenManager(FloatLayout):
return
old_current = self.current_screen
def remove_old_screen(transition):
if old_current in self.children:
self.remove_widget(old_current)
@ -825,7 +826,6 @@ class ScreenManager(FloatLayout):
self.current = screen.name
def _generate_screen_name(self):
i = 0
while True:

View File

@ -142,7 +142,7 @@ class Splitter(BoxLayout):
_strp.unbind(on_touch_down=instance.strip_down)
_strp.unbind(on_touch_move=instance.strip_move)
_strp.unbind(on_touch_up=instance.strip_up)
self.unbind(disabled = _strp.setter('disabled'))
self.unbind(disabled=_strp.setter('disabled'))
sup.remove_widget(instance._strip)
else:

View File

@ -41,8 +41,9 @@ class StackLayout(Layout):
spacing also accepts a one argument form [spacing].
:data:`spacing` is a :class:`~kivy.properties.VariableListProperty`, default to
[0, 0].
:data:`spacing` is a
:class:`~kivy.properties.VariableListProperty`, default to [0, 0].
'''
padding = VariableListProperty([0, 0, 0, 0])
@ -56,8 +57,10 @@ class StackLayout(Layout):
Replaced NumericProperty with VariableListProperty.
:data:`padding` is a :class:`~kivy.properties.VariableListProperty`, default to
[0, 0, 0, 0].
:data:`padding` is a
:class:`~kivy.properties.VariableListProperty`, default to [0, 0,
0, 0].
'''
orientation = OptionProperty('lr-tb', options=(

View File

@ -232,8 +232,10 @@ class VKeyboard(Scatter):
.. versionadded:: 1.8.0
:data:`background_disabled` a :class:`~kivy.properties.StringProperty`, default to
:data:`background_disabled` a
:class:`~kivy.properties.StringProperty`, default to
:file:`atlas://data/images/defaulttheme/vkeyboard__disabled_background`.
'''
key_background_color = ListProperty([1, 1, 1, 1])
@ -260,8 +262,10 @@ class VKeyboard(Scatter):
..versionadded:: 1.8.0
:data:`key_disabled_background_normal` a :class:`~kivy.properties.StringProperty`,
default to :file:`atlas://data/images/defaulttheme/vkeyboard_disabled_key_normal`.
:data:`key_disabled_background_normal` a
:class:`~kivy.properties.StringProperty`, default to
:file:`atlas://data/images/defaulttheme/vkeyboard_disabled_key_normal`.
'''
key_background_down = StringProperty(

View File

@ -1,5 +1,4 @@
'''
Vector
'''Vector
======
The :class:`Vector` represents a 2D vector (x, y).
@ -34,8 +33,9 @@ Exemple for constructing a Vector::
Optimized usage
---------------
Most of the time, you can use a list for arguments, instead of using a Vector. For
example, if you want to have the distance between 2 points::
Most of the time, you can use a list for arguments, instead of using a
Vector. For example, if you want to have the distance between 2
points::
a = (10, 10)
b = (87, 34)