Merge http://github.com/kivy/kivy into splitter
Conflicts: kivy/data/images/defaulttheme-0.png kivy/data/images/defaulttheme.atlas
|
@ -0,0 +1,19 @@
|
|||
language: python
|
||||
python:
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
# command to install dependencies
|
||||
before_install:
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install python-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsdl1.2-dev libsmpeg-dev python-numpy libportmidi-dev ffmpeg libswscale-dev libavformat-dev libavcodec-dev libjpeg-dev libtiff4-dev libx11-6 libX11-dev
|
||||
- sudo apt-get install python-setuptools python-opengl gstreamer0.10-plugins-good build-essential libgl1-mesa-dev libgles2-mesa-dev mercurial
|
||||
- sudo apt-get install xvfb
|
||||
|
||||
install:
|
||||
- pip install hg+http://bitbucket.org/pygame/pygame
|
||||
- pip install --upgrade cython pil --use-mirrors
|
||||
- make
|
||||
|
||||
# command to run tests
|
||||
script:
|
||||
- xvfb-run -s "+extension GLX" make test
|
|
@ -23,6 +23,7 @@ import kivy
|
|||
|
||||
# force loading of kivy modules
|
||||
import kivy.app
|
||||
import kivy.metrics
|
||||
import kivy.atlas
|
||||
import kivy.core.audio
|
||||
import kivy.core.camera
|
||||
|
@ -43,6 +44,7 @@ import kivy.modules.monitor
|
|||
import kivy.modules.touchring
|
||||
import kivy.modules.inspector
|
||||
import kivy.modules.recorder
|
||||
import kivy.modules.screen
|
||||
import kivy.network.urlrequest
|
||||
import kivy.support
|
||||
import kivy.input.recorder
|
||||
|
@ -50,7 +52,7 @@ import kivy.interactive
|
|||
from kivy.factory import Factory
|
||||
|
||||
# force loading of all classes from factory
|
||||
for x in Factory.classes:
|
||||
for x in Factory.classes.keys()[:]:
|
||||
getattr(Factory, x)
|
||||
|
||||
|
||||
|
|
|
@ -25,4 +25,9 @@ stunning applications in short time using the framework.
|
|||
contact
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
guide2-index
|
||||
|
||||
.. include:: api-index.rst
|
||||
|
|
|
@ -175,11 +175,43 @@ get instant karma. Congratulations, you're a hero!
|
|||
Documentation Contributions
|
||||
---------------------------
|
||||
|
||||
Documentation contributions generally follow the same workflow as code
|
||||
contributions, just a bit more lax. We don't ask you to go through all the
|
||||
hassle just to correct a single typo. For more complex contributions, please
|
||||
consider following the suggested workflow though.
|
||||
Documentation contributions generally follow the same workflow as code contributions, just a bit more lax.
|
||||
|
||||
#. Following the instructions above,
|
||||
|
||||
#. Fork the repository.
|
||||
|
||||
#. Clone your fork to your computer.
|
||||
|
||||
#. Setup kivy repo as a remote source.
|
||||
|
||||
#. Install python-sphinx. (See docs/sources/README for assistance.)
|
||||
|
||||
#. Use ReStructuredText_Markup_ to make changes to the HTML documentation in docs/sources.
|
||||
|
||||
.. _ReStructuredText_Markup: http://docutils.sourceforge.net/rst.html
|
||||
|
||||
To submit a documentation update, use the following steps:
|
||||
|
||||
#. Create a new, appropriately named branch in your local repository.::
|
||||
|
||||
git checkout -b my_docs_update
|
||||
|
||||
#. Modify the documentation with your correction or improvement.
|
||||
#. Re-generate the HTML pages, and review your update.::
|
||||
|
||||
make html
|
||||
|
||||
#. Give each commit an appropriate commit message, so that others who are not familiar with the matter get a good idea of what you changed.
|
||||
#. Keep each commit focused on a single related theme. Don't commit other stuff that doesn't logically belong to this update.
|
||||
|
||||
#. Push to your remote repository on GitHub::
|
||||
|
||||
git push
|
||||
|
||||
#. Send a *Pull Request* with a description of what you changed via the button in the GitHub interface of your repository.
|
||||
|
||||
We don't ask you to go through all the hassle just to correct a single typo, but for more complex contributions, please follow the suggested workflow.
|
||||
|
||||
Docstrings
|
||||
~~~~~~~~~~
|
||||
|
|
|
@ -107,6 +107,8 @@ Examples
|
|||
.. |wdg_desc1| replace:: Usage and Showcase of :class:`Accordion <kivy.uix.accordion>` Widget.
|
||||
.. |wdg_file2| replace:: asyncimage.py
|
||||
.. |wdg_desc2| replace:: Usage and Showcase of :class:`AsyncImage <kivy.uix.image.AsyncImage>` Widget.
|
||||
.. |wdg_file25| replace:: boxlayout_pos_hint.py
|
||||
.. |wdg_desc25| replace:: Showcase of pos_hint under BoxLayout :class:`BoxLayout <kivy.uix.boxlayout>`
|
||||
.. |wdg_file3| replace:: bubble_test.py
|
||||
.. |wdg_desc3| replace:: Usage and Showcase of :class:`Bubble <kivy.uix.bubble>` Widget.
|
||||
.. |wdg_file4| replace:: customcollide.py
|
||||
|
@ -118,7 +120,11 @@ Examples
|
|||
.. |wdg_file7| replace:: keyboardlistener.py
|
||||
.. |wdg_desc7| replace:: listen to the keyboard input and spew result to console.
|
||||
.. |wdg_file8| replace:: label_mipmap.py
|
||||
.. |wdg_desc8| replace:: How to use :class:`Label <kivy.uix.label>` widget with mipmap.
|
||||
.. |wdg_desc8| replace:: How to use :class:`Label <kivy.uix.label>` widget with
|
||||
.. |wdg_file81| replace:: label_with_markup.py
|
||||
.. |wdg_desc81| replace:: Useage of :class:`Label <kivy.uix.label>` widget with markup.
|
||||
.. |wdg_file82| replace:: popup_with_kv.py
|
||||
.. |wdg_desc82| replace:: Useage of :class:`Popup <kivy.uix.popup>` widget with ``kv`` language
|
||||
.. |wdg_file9| replace:: rstexample.py
|
||||
.. |wdg_desc9| replace:: Usage and Showcase of :class:`RstDocument <kivy.uix.rst.RstDocument>` Widget.
|
||||
.. |wdg_file10| replace:: scatter.py
|
||||
|
@ -198,12 +204,15 @@ Examples
|
|||
+------------+---------------+------------------------+
|
||||
|- |wdg_dir| | - |wdg_file1| |- |wdg_desc1| |
|
||||
| | - |wdg_file2| |- |wdg_desc2| |
|
||||
| | - |wdg_file25||- |wdg_desc25| |
|
||||
| | - |wdg_file3| |- |wdg_desc3| |
|
||||
| | - |wdg_file4| |- |wdg_desc4| |
|
||||
| | - |wdg_file5| |- |wdg_desc5| |
|
||||
| | - |wdg_file6| |- |wdg_desc6| |
|
||||
| | - |wdg_file7| |- |wdg_desc7| |
|
||||
| | - |wdg_file8| |- |wdg_desc8| |
|
||||
| | - |wdg_file81||- |wdg_desc81| |
|
||||
| | - |wdg_file82||- |wdg_desc82| |
|
||||
| | - |wdg_file9| |- |wdg_desc9| |
|
||||
| | - |wdg_file10||- |wdg_desc10| |
|
||||
| | - |wdg_file11||- |wdg_desc11| |
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
.. _guide-index:
|
||||
|
||||
Programming Guide
|
||||
=================
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
Designing with the Kivy Language
|
||||
================================
|
||||
|
||||
The code goes in main.py
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Let's start with a little example. First, the Python file named `main.py`:
|
||||
|
||||
.. include:: ../../../examples/guide/designwithkv/main.py
|
||||
|
@ -20,6 +23,9 @@ In addition, we are creating a ``do_action()`` method, that will use both of
|
|||
these properties. It will change the ``info`` text, and change text in the
|
||||
``label_wid`` widget.
|
||||
|
||||
The layout goes in controller.kv
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Executing this application without a corresponding `.kv` file will work, but
|
||||
nothing will be shown on the screen. This is expected, because the
|
||||
``Controller`` class has no widgets in it, it's just a ``FloatLayout``. We can
|
||||
|
|
|
@ -32,11 +32,6 @@ KIVY_NO_FILELOG
|
|||
KIVY_NO_CONSOLELOG
|
||||
If set, logs will be not print on the console
|
||||
|
||||
KIVY_DPI
|
||||
If set, the value will be used instead of the value returned by the window.
|
||||
|
||||
.. versionadded:: 1.4.0
|
||||
|
||||
Path control
|
||||
------------
|
||||
|
||||
|
@ -101,3 +96,22 @@ KIVY_CLIPBOARD
|
|||
|
||||
Values: pygame, dummy
|
||||
|
||||
Metrics
|
||||
-------
|
||||
|
||||
KIVY_DPI
|
||||
If set, the value will be used for :data:`Metrics.dpi`.
|
||||
|
||||
.. versionadded:: 1.4.0
|
||||
|
||||
KIVY_METRICS_DENSITY
|
||||
If set, the value will be used for :data:`Metrics.density`.
|
||||
|
||||
.. versionadded:: 1.5.0
|
||||
|
||||
KIVY_METRICS_FONTSCALE
|
||||
|
||||
If set, the value will be used for :data:`Metrics.fontscale`.
|
||||
|
||||
.. versionadded:: 1.5.0
|
||||
|
||||
|
|
|
@ -169,17 +169,15 @@ This is what has changed:
|
|||
:class:`~kivy.graphics.vertex_instructions.Line`, you will see that
|
||||
it accepts a ``points`` argument that has to be a list of 2D point
|
||||
coordinates, like ``(x1, y1, x2, y2, ..., xN, yN)``.
|
||||
* Line 8: This is where it gets interesting. ``touch.ud`` is a Python
|
||||
* Line 13: This is where it gets interesting. ``touch.ud`` is a Python
|
||||
dictionary (type <dict>) that allows us to store *custom attributes*
|
||||
for a touch. On this line we simply get a reference to it to make it
|
||||
more clear that ``ud`` stands for ``userdata``. You could just as
|
||||
well write ``touch.ud`` instead of ``userdata``.
|
||||
for a touch.
|
||||
* Line 13: We make use of the Line instruction that we imported and
|
||||
set a Line up for drawing. Since this is done in ``on_touch_down``,
|
||||
there will be a new line for every new touch. By creating the line
|
||||
inside the ``with`` block, the canvas automatically knows about the
|
||||
line and will draw it. We just want to modify the line later, so we
|
||||
store a reference to it in the ``userdata`` dictionary under the
|
||||
store a reference to it in the ``touch.ud`` dictionary under the
|
||||
arbitrarily chosen but aptly named key 'line'.
|
||||
We pass the line that we're creating the initial touch position
|
||||
because that's where our line will begin.
|
||||
|
@ -193,13 +191,13 @@ This is what has changed:
|
|||
shortly see why.
|
||||
* Line 16: Remember: This is the same touch object that we got in
|
||||
``on_touch_down``, so we can simply access the data we stored away
|
||||
in the userdata dictionary!
|
||||
in the ``touch.ud`` dictionary!
|
||||
To the line we set up for this touch earlier, we now add the current
|
||||
position of the touch as a new point. We know that we need to extend
|
||||
the line because this happens in ``on_touch_move``, which is only
|
||||
called when the touch has moved, which is exactly why we want to
|
||||
update the line.
|
||||
Storing the line in the userdata makes it a whole lot
|
||||
Storing the line in the ``touch.ud`` makes it a whole lot
|
||||
easier for us as we don't have to maintain our own touch-to-line
|
||||
bookkeeping.
|
||||
|
||||
|
@ -218,13 +216,11 @@ Here are the changes:
|
|||
|
||||
* Line 1: We import Python's random() function that will give us
|
||||
random values in the range of [0., 1.).
|
||||
* Line 10: We want to memorize the color for this touch, so we store
|
||||
it in the touch's userdata dictionary.
|
||||
In this case we simply create a new tuple of 3 random
|
||||
* Line 10: In this case we simply create a new tuple of 3 random
|
||||
float values that will represent a random RGB color. Since we do
|
||||
this in ``on_touch_down``, every new touch will get its own color.
|
||||
Don't get confused by the use of two ``=`` operators. We're just
|
||||
binding the tuple to ``c`` as well as a shortcut for use within this
|
||||
binding the tuple to ``color`` as well as a shortcut for use within this
|
||||
method because we're lazy.
|
||||
* Line 12: As before, we set the color for the canvas. Only this time
|
||||
we use the random values we generated and feed them to the color
|
||||
|
@ -248,7 +244,7 @@ might even be able to create a nice little drawing!
|
|||
There is a nice trick to prevent this: Instead of creating a tuple with
|
||||
three random values, create a tuple like this: ``(random(), 1., 1.)``.
|
||||
Then, when passing it to the color instruction, set the mode to HSV
|
||||
color space: ``Color(*c, mode='hsv')``. This way you will have a
|
||||
color space: ``Color(*color, mode='hsv')``. This way you will have a
|
||||
smaller number of possible colors, but the colors that you get will
|
||||
always be equally bright. Only the hue changes.
|
||||
|
||||
|
|
|
@ -115,6 +115,10 @@ is where the Kivy language can be useful.
|
|||
Usage of the Kivy language for graphics
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. note::
|
||||
|
||||
By default the name of the ``.kv`` file to be loaded is decided by the name of your main class. So if you main class's name is ``MyTestApp`` or ``MultiMapMayhem`` then ``mytest.kv`` or ``multimapmayhem.kv`` file will be auto-loaded respectively.
|
||||
|
||||
The Kivy language has a lot of benefits for this example ``Button``. You can
|
||||
create a rule that will match your widget, create graphics instructions, and
|
||||
update their properties according to a python expression. Here is the complete
|
||||
|
|
|
@ -10,6 +10,12 @@ Create a package for Android
|
|||
|
||||
.. _Packaging your application into APK:
|
||||
|
||||
TestDrive
|
||||
---------
|
||||
There is a VirtualBox Image we provide with the prerequisites along with
|
||||
Android SDK and NDK preinstalled to ease your installation woes. You can
|
||||
download it from `here <http://www.google.com/url?sa=D&q=https://docs.google.com/file/d/0B1WO07-OL50_VDNESDRUaDhXSmM/edit&usg=AFQjCNGrsg0SU8EMgAcLHWxbjSe8KM2kyA>`_.
|
||||
|
||||
Packaging your application into APK
|
||||
-----------------------------------
|
||||
|
||||
|
@ -29,7 +35,7 @@ First, follow the prerequisites needed for the project:
|
|||
|
||||
http://python-for-android.readthedocs.org/en/latest/prerequisites/
|
||||
|
||||
Then a console, and type::
|
||||
Then open a console, and type::
|
||||
|
||||
git clone git://github.com/kivy/python-for-android
|
||||
|
||||
|
|
|
@ -81,6 +81,8 @@ You can customize the build in many ways:
|
|||
#. Go to the settings panel > build, search for "strip" options, and
|
||||
triple-check that they are all set to NO. Stripping is not working with
|
||||
Python dynamic modules, and will strip needed symbols.
|
||||
#. Indicate a launch image in portrait/landscape for ipad with and without
|
||||
retina display.
|
||||
|
||||
.. _Known issues:
|
||||
|
||||
|
@ -90,12 +92,6 @@ Known issues
|
|||
Currently, the project have few issues as (we'll fixes them during the
|
||||
development):
|
||||
|
||||
- Loading time: Apple provide a way to reduce the feeling of a slow application
|
||||
loading by showing an image when the application is initialize. But, due to
|
||||
the SDL approach, IOS remove the launch image before we have started. So if
|
||||
you are using a launch image, the user will see: The launch image -> black
|
||||
screen -> your app. Remove the launch image for now.
|
||||
|
||||
- Application configuration not writing: we are learning how IOS manage its
|
||||
filesystem.
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ Build the spec
|
|||
#. Go to the pyinstaller directory, and build the spec::
|
||||
|
||||
cd pyinstaller-2.0
|
||||
python Build.py touchtracer\\touchtracer.spec
|
||||
python pyinstaller.py touchtracer\\touchtracer.spec
|
||||
|
||||
#. The package will be in the `touchtracer\\dist\\touchtracer` directory !
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ it will be generated like this:
|
|||
|
||||
.. image:: images/api-button.jpg
|
||||
|
||||
It should be read like this: the "Button" class is into the "kivy.uix.button"
|
||||
It should be read like this: the "Button" class is in the "kivy.uix.button"
|
||||
module. So if you want to import that class in your code, write that::
|
||||
|
||||
from kivy.uix.button import Button
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
Programming Guide 2
|
||||
===================
|
||||
|
||||
.. warning::
|
||||
|
||||
We are currently refactoring the whole Programming Guide. This is a work in
|
||||
progress, and might change at any times.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
guide2/basic
|
||||
guide2/events
|
||||
guide2/widgets
|
||||
guide2/graphics
|
||||
guide2/lang
|
||||
guide2/bestpractices
|
||||
guide2/advancedgraphics
|
||||
guide2/packaging
|
|
@ -0,0 +1,13 @@
|
|||
.. _advancedgraphics:
|
||||
|
||||
Advanced Graphics
|
||||
=================
|
||||
|
||||
Create your own Shader
|
||||
----------------------
|
||||
|
||||
Rendering in a Framebuffer
|
||||
--------------------------
|
||||
|
||||
Optimizations
|
||||
-------------
|
|
@ -0,0 +1,47 @@
|
|||
.. _basic:
|
||||
|
||||
Basic Kivy
|
||||
==========
|
||||
|
||||
Installation of Kivy environment
|
||||
--------------------------------
|
||||
|
||||
Kivy depends on multiples dependencies, such as pygame, gstreamer, PIL, cairo,
|
||||
and more. All of them are not required, but depending the platform you're
|
||||
working on, it can be a pain to install them. For Windows and MacOSX, we
|
||||
provide a portable package that you can just unzip and use.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
/installation/installation-windows.rst
|
||||
/installation/installation-macosx.rst
|
||||
/installation/installation-linux.rst
|
||||
|
||||
If you want to install everything yourself, ensure that you have at least
|
||||
`Cython <http://cython.org>`_, `Pygame <http://pygame.org>`. A typical pip
|
||||
installation look like::
|
||||
|
||||
pip install cython
|
||||
pip install hg+http://bitbucket.org/pygame/pygame
|
||||
pip install kivy
|
||||
|
||||
The `development version <https://github.com/kivy/kivy>`_ can be installed with
|
||||
git::
|
||||
|
||||
git clone https://github.com/kivy/kivy
|
||||
make
|
||||
|
||||
|
||||
Create an application
|
||||
---------------------
|
||||
|
||||
Running the application
|
||||
-----------------------
|
||||
|
||||
Customize the application
|
||||
-------------------------
|
||||
|
||||
Platform specifics
|
||||
------------------
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
.. _bestpractices:
|
||||
|
||||
Best Practices
|
||||
==============
|
||||
|
||||
Designing your Application code
|
||||
-------------------------------
|
||||
|
||||
Handle Window resizing
|
||||
----------------------
|
||||
|
||||
Managing resources
|
||||
------------------
|
||||
|
||||
Platform consideration
|
||||
----------------------
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
.. _events:
|
||||
.. _properties:
|
||||
|
||||
Events and Properties
|
||||
=====================
|
||||
|
||||
Introduction to Event Dispatcher
|
||||
--------------------------------
|
||||
|
||||
Creating custom events
|
||||
----------------------
|
||||
|
||||
Attaching callbacks
|
||||
-------------------
|
||||
|
||||
Introduction to properties
|
||||
--------------------------
|
||||
|
||||
Declaration of a Property
|
||||
-------------------------
|
||||
|
||||
Dispatching a Property event
|
||||
----------------------------
|
|
@ -0,0 +1,17 @@
|
|||
.. _graphics:
|
||||
|
||||
Graphics
|
||||
========
|
||||
|
||||
Introduction to Canvas
|
||||
----------------------
|
||||
|
||||
Context instructions
|
||||
--------------------
|
||||
|
||||
Drawing instructions
|
||||
--------------------
|
||||
|
||||
Manipulating instructions
|
||||
-------------------------
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
.. _lang:
|
||||
|
||||
Kv language
|
||||
===========
|
||||
|
||||
Concept behind the language
|
||||
---------------------------
|
||||
|
||||
Rule context
|
||||
------------
|
||||
|
||||
Instanciate children
|
||||
--------------------
|
||||
|
||||
Extend canvas
|
||||
-------------
|
||||
|
||||
Templating
|
||||
----------
|
|
@ -0,0 +1,2 @@
|
|||
Packaging
|
||||
=========
|
|
@ -0,0 +1,17 @@
|
|||
.. _widgets:
|
||||
|
||||
Widgets
|
||||
=======
|
||||
|
||||
Introduction to Widget
|
||||
----------------------
|
||||
|
||||
Manipulating the Widget tree
|
||||
----------------------------
|
||||
|
||||
Organize with Layouts
|
||||
---------------------
|
||||
|
||||
Seperate with Screen Manager
|
||||
----------------------------
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 859 KiB After Width: | Height: | Size: 554 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 314 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 406 KiB After Width: | Height: | Size: 795 KiB |
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 1.8 MiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 644 KiB After Width: | Height: | Size: 764 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
@ -8,12 +8,10 @@ Welcome to Kivy's documentation. Kivy is an open source software library for rap
|
|||
development of applications equipped with novel user interfaces, such as
|
||||
multi-touch apps.
|
||||
|
||||
You are probably wondering why you'd be interested in using Kivy. There is
|
||||
a document outlining our :ref:`philosophy` that we encourage you to read.
|
||||
We recommend that you get started with :doc:`/gettingstarted/index`. Then head over the :ref:`guide-index`. We also have a :ref:`quickstart` if you are impatient.
|
||||
|
||||
We recommend that you get started with :ref:`installation` and then head over to
|
||||
the :ref:`quickstart` document. Besides the quickstart, there is also a more
|
||||
detailed :ref:`architecture`.
|
||||
You are probably wondering why you'd be interested in using Kivy. There is
|
||||
a document outlining our :ref:`philosophy` that we encourage you to read, and an detailed :ref:`architecture`.
|
||||
|
||||
If you want to contribute to Kivy, make sure to read :ref:`contributing`. If your
|
||||
concern isn't addressed in the documentation, feel free to :ref:`contact`.
|
||||
|
|
|
@ -6,14 +6,15 @@ Installation on Linux
|
|||
Prerequisites
|
||||
-------------
|
||||
|
||||
Ubuntu (11.10)
|
||||
~~~~~~~~~~~~~~
|
||||
Ubuntu (11.10 or newer)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
$ sudo apt-get install python-setuptools python-pygame python-opengl \
|
||||
python-gst0.10 python-enchant gstreamer0.10-plugins-good cython python-dev \
|
||||
build-essential libgl1-mesa-dev libgles2-mesa-dev
|
||||
python-gst0.10 python-enchant gstreamer0.10-plugins-good python-dev \
|
||||
build-essential libgl1-mesa-dev libgles2-mesa-dev python-pip
|
||||
$ sudo pip install --upgrade cython
|
||||
|
||||
Fedora (16)
|
||||
~~~~~~~~~~~
|
||||
|
@ -21,10 +22,10 @@ Fedora (16)
|
|||
::
|
||||
|
||||
$ sudo yum install python-distutils-extra python-enchant freeglut PyOpenGL \
|
||||
SDL_ttf-devel SDL_mixer-devel pygame pygame-devel Cython khrplatform-devel \
|
||||
SDL_ttf-devel SDL_mixer-devel pygame pygame-devel khrplatform-devel \
|
||||
mesa-libGLES mesa-libGLES-devel gstreamer-plugins-good gstreamer \
|
||||
gstreamer-python mtdev-devel
|
||||
|
||||
gstreamer-python mtdev-devel python-pip
|
||||
$ sudo pip install --upgrade cython
|
||||
|
||||
OpenSuse (12.1)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
@ -33,8 +34,9 @@ OpenSuse (12.1)
|
|||
|
||||
$ sudo zypper install python-distutils-extra python-pygame python-opengl \
|
||||
python-gstreamer-0_10 python-enchant gstreamer-0_10-plugins-good \
|
||||
python-Cython python-devel Mesa-devel
|
||||
python-devel Mesa-devel python-pip
|
||||
$ zypper install -t pattern devel_C_C++
|
||||
$ sudo pip install --upgrade cython
|
||||
|
||||
|
||||
Mageia (1 and 2(cauldron))
|
||||
|
@ -47,6 +49,8 @@ Mageia (1 and 2(cauldron))
|
|||
gstreamer0.10-python python-enchant gstreamer0.10-plugins-good \
|
||||
python-cython lib64python-devel lib64mesagl1-devel lib64mesaegl1-devel \
|
||||
lib64mesaglesv2_2-devel make gcc
|
||||
$ sudo easy_install pip
|
||||
$ sudo pip install --upgrade cython
|
||||
|
||||
|
||||
Installation
|
||||
|
|
|
@ -21,7 +21,7 @@ file that contains:
|
|||
|
||||
To install Kivy, you must:
|
||||
|
||||
1. Download the latest version from http://kivy.org/#downloads
|
||||
1. Download the latest version from http://kivy.org/#download
|
||||
2. Double-click to open it
|
||||
3. Drag the Kivy.app into your Applications folder
|
||||
4. Make sure to read the Readme.txt
|
||||
|
|
|
@ -4,7 +4,7 @@ Installation
|
|||
============
|
||||
|
||||
We try not to reinvent the wheel, but to bring something innovative to the
|
||||
market. As a consequence, we're focused on our own code and use pre-existing,
|
||||
market. As a consequence, we're focused on our own code and use pre-existing,
|
||||
high-quality third-party libraries where possible.
|
||||
To support the full, rich set of features that Kivy offers, several other libraries are
|
||||
required. If you do not use a specific feature (e.g. video playback) you
|
||||
|
@ -12,7 +12,7 @@ don't need the corresponding dependency, however.
|
|||
That said, there is one dependency that Kivy **does** require:
|
||||
`Cython <http://cython.org>`_.
|
||||
|
||||
In addition, you need a `Python <http://python.org/>`_ 2.x (**not** 3.x)
|
||||
In addition, you need a `Python <http://python.org/>`_ 2.x (2.6 <= x < 3.0)
|
||||
interpreter. If you want to enable features like windowing (i.e., open a Window),
|
||||
audio/video playback or spelling correction, additional dependencies must
|
||||
be available. For these, we recommend `Pygame <http://pygame.org>`_, `Gst-Python
|
||||
|
@ -79,8 +79,14 @@ necessary packages:
|
|||
::
|
||||
|
||||
$ sudo apt-get install python-setuptools python-pygame python-opengl \
|
||||
python-gst0.10 python-enchant gstreamer0.10-plugins-good cython python-dev \
|
||||
build-essential libgl1-mesa-dev libgles2-mesa-dev
|
||||
python-gst0.10 python-enchant gstreamer0.10-plugins-good python-dev \
|
||||
build-essential libgl1-mesa-dev libgles2-mesa-dev python-pip
|
||||
|
||||
Kivy require a recent version of cython, so it's better to use the last
|
||||
version published on pypi.
|
||||
|
||||
::
|
||||
$ sudo pip install --upgrade cython
|
||||
|
||||
.. _dev-install:
|
||||
|
||||
|
|
|
@ -106,8 +106,8 @@ def callback_signature(app, what, name, obj, options, signature,
|
|||
|
||||
def setup(app):
|
||||
import kivy
|
||||
sys.path += [join(dirname(kivy.__file__), 'tools', 'highlight', 'pygments')]
|
||||
from lexer_kivy import KivyLexer
|
||||
sys.path += [join(dirname(kivy.__file__), 'extras')]
|
||||
from highlight import KivyLexer
|
||||
|
||||
app.add_lexer('kv', KivyLexer())
|
||||
app.add_autodocumenter(CythonMethodDocumenter)
|
||||
|
|
After Width: | Height: | Size: 34 KiB |
|
@ -0,0 +1,24 @@
|
|||
Compass
|
||||
=======
|
||||
|
||||
Demonstrate the combination of the Android Magnetic Field Sensor and the Kivy functionality viewing a Compass.
|
||||
|
||||
Kivy Python-For-Android
|
||||
-----------------------
|
||||
|
||||
Please look at the lastest docs of the
|
||||
`Kivy Python-For-Android Project <http://python-for-android.readthedocs.org/en/latest/>`__
|
||||
|
||||
Building an APK
|
||||
---------------
|
||||
|
||||
::
|
||||
|
||||
./distribute.sh -m "pyjnius kivy"
|
||||
|
||||
|
||||
::
|
||||
|
||||
./build.py --package org.test.compass --name compass \
|
||||
--version 1.0 --dir ~/code/kivy/examples/android/compass debug
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
title=Compass
|
||||
author=Nik Klever
|
||||
orientation=portrait
|
|
@ -0,0 +1,223 @@
|
|||
import kivy
|
||||
kivy.require('1.3.0')
|
||||
|
||||
import math
|
||||
import time
|
||||
|
||||
from kivy.app import App
|
||||
from kivy.uix.floatlayout import FloatLayout
|
||||
from kivy.uix.button import Button
|
||||
from kivy.uix.scatter import Scatter
|
||||
from kivy.clock import Clock
|
||||
from kivy.vector import Vector
|
||||
from kivy.core.window import Window
|
||||
from kivy.graphics import Color, Ellipse, Rectangle, Triangle
|
||||
from kivy.logger import Logger
|
||||
|
||||
from jnius import autoclass
|
||||
|
||||
Logger.info('COMPASS: STARTED')
|
||||
|
||||
def LoggerDisplayMetrics(metrics):
|
||||
"""
|
||||
Logging all values of the Java Android DisplayMetrics class
|
||||
to get some more information about the metrics of Android devices
|
||||
"""
|
||||
display = {'Default':metrics.DENSITY_DEFAULT,
|
||||
'Device':metrics.DENSITY_DEVICE,
|
||||
'High':metrics.DENSITY_HIGH,
|
||||
'Low':metrics.DENSITY_LOW,
|
||||
'Medium':metrics.DENSITY_MEDIUM,
|
||||
'XHIGH':metrics.DENSITY_XHIGH,
|
||||
'density':metrics.density,
|
||||
'densityDpi':metrics.densityDpi,
|
||||
'heightPixels':metrics.heightPixels,
|
||||
'scaledDensity':metrics.scaledDensity,
|
||||
'widthPixels':metrics.widthPixels,
|
||||
'xdpi':metrics.xdpi,
|
||||
'ydpi':metrics.ydpi}
|
||||
for (k,v) in display.items():
|
||||
Logger.info('COMPASS: display %s = %s'%(k,v))
|
||||
|
||||
class CompassWidget(FloatLayout):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""
|
||||
Constructor of the CompassWidget class
|
||||
"""
|
||||
super(CompassWidget, self).__init__(**kwargs)
|
||||
|
||||
def build(self,pos,size):
|
||||
"""
|
||||
building the background of the CompassWidget with a circle of a
|
||||
compass windrose image
|
||||
(Source of this image: Wikipedia - http://en.wikipedia.org/wiki/Compass_rose)
|
||||
"""
|
||||
with self.canvas:
|
||||
self.pos = pos
|
||||
self.size = size
|
||||
self.windrose = Ellipse(source="500px-Windrose.svg.png", pos=pos, size=size)
|
||||
|
||||
class NeedleWidget(Scatter):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""
|
||||
Constructor of the NeedleWidget class
|
||||
|
||||
do_rotation, do_translation, do_scale are all set to False
|
||||
to indicate that the scatter widget can onlybe updated from the
|
||||
app and not by an interaction with your fingers
|
||||
"""
|
||||
super(NeedleWidget, self).__init__(**kwargs)
|
||||
|
||||
self.do_rotation = False
|
||||
self.do_translation = False
|
||||
self.do_scale = False
|
||||
self.auto_bring_to_front = True
|
||||
|
||||
def rotateNeedle(self,angle):
|
||||
"""
|
||||
rotate the NeedleWidget with the parameter angle
|
||||
90 is subtracted because North of the windrose is at 90 degrees
|
||||
of the device
|
||||
"""
|
||||
self.rotation = angle - 90
|
||||
|
||||
def build(self,center,needleSize):
|
||||
"""
|
||||
building the needle with two Triangles of different color
|
||||
"""
|
||||
self.pos = center - needleSize/2.
|
||||
self.size = needleSize
|
||||
self.size_hint = [None, None]
|
||||
with self.canvas:
|
||||
Color(1., 0, 0)
|
||||
needleTP1 = Vector(needleSize[0]/2.,needleSize[1])
|
||||
needleTP2 = Vector(needleSize[0]/2.,0)
|
||||
needleTP3 = Vector(-needleSize[0],needleSize[1]/2.)
|
||||
needlePoints = (needleTP1[0],needleTP1[1],
|
||||
needleTP2[0],needleTP2[1],
|
||||
needleTP3[0],needleTP3[1])
|
||||
self.needleT1 = Triangle(points=needlePoints)
|
||||
Color(0.5, 0.5, 0.5)
|
||||
needleTP3 = Vector(2*needleSize[0],needleSize[1]/2.)
|
||||
needlePoints = (needleTP1[0],needleTP1[1],
|
||||
needleTP2[0],needleTP2[1],
|
||||
needleTP3[0],needleTP3[1])
|
||||
self.needleT2 = Triangle(points=needlePoints)
|
||||
|
||||
class CompassApp(App):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""
|
||||
Constructor of the Compass App
|
||||
|
||||
1) The Java Android API DisplayMetrics is called to get
|
||||
information about the densityDpi factor of the Android device
|
||||
|
||||
2) The Kivy Python-For-Android Android API is called to
|
||||
get access to the hardware sensors of the Android device
|
||||
|
||||
"""
|
||||
super(CompassApp, self).__init__(**kwargs)
|
||||
DisplayMetrics = autoclass('android.util.DisplayMetrics')
|
||||
metrics = DisplayMetrics()
|
||||
metrics.setToDefaults()
|
||||
LoggerDisplayMetrics(metrics)
|
||||
self.densityDpi = metrics.densityDpi
|
||||
|
||||
Hardware = autoclass('org.renpy.android.Hardware')
|
||||
self.hw = Hardware()
|
||||
Logger.info('COMPASS: Hardware Objects: %s'%(str(dir(self.hw))))
|
||||
Logger.info('COMPASS: Hardware Sensors\n%s\n'%(self.hw.getHardwareSensors()))
|
||||
|
||||
def viewCompass(self, *largs):
|
||||
"""
|
||||
viewCompass calls the readSensor method of the
|
||||
magneticFieldSensor instance of the generic3AxisSensor, it reads the
|
||||
3-tuple value of the magnetic field
|
||||
|
||||
the declination angle is computed as the angle of the magnetic field
|
||||
vector in the x,y-plane and the unity-vector of the y-axis.
|
||||
|
||||
afterwards the rotateNeedle function rotates the needle as given
|
||||
by the declination angle parameter
|
||||
"""
|
||||
(x, y, z) = self.hw.magneticFieldSensor.readSensor()
|
||||
declination = Vector(x,y).angle((0,1))
|
||||
#Logger.info('COMPASS: viewCompass x=%s y=%s z=%s declination=%s'%(x,y,z,declination))
|
||||
self.needle.rotateNeedle(declination)
|
||||
|
||||
def stopApp(self,*largs):
|
||||
"""
|
||||
this function is called when pushed the stopButton, disables
|
||||
the magneticFieldSensor and stops the app
|
||||
"""
|
||||
self.hw.magneticFieldSensor.changeStatus(False)
|
||||
Logger.info('COMPASS: stop largs '+str(largs))
|
||||
self.stop()
|
||||
|
||||
def build(self):
|
||||
"""
|
||||
Building all together:
|
||||
|
||||
1) Creating the parent widget and clearing it to white background color
|
||||
|
||||
2) Defining a suitable position and size of the CompassWidget, the
|
||||
needleSize and the stopButtonHeight depending on the densityDpi value
|
||||
given by DisplayMetrics
|
||||
|
||||
3) Creating an instance of the CompassWidget and adding it to the
|
||||
parent widget and calling the appropriate build function
|
||||
|
||||
4) Creating an instance of the NeedleWidget and adding it also to the
|
||||
parent widget and calling the appropriate build function
|
||||
|
||||
5) Creating an instance of a Button widget and adding it as stopButton
|
||||
also to the parent widget and bind it with the stopApp function
|
||||
|
||||
6) Calling the instance method changeStatus of the magneticFieldSensor
|
||||
instance with parameter True to enable the magnetic field sensor
|
||||
and additionally calling the function schedule_interval of the Clock
|
||||
class for a repeated call of the function viewCompass every second.
|
||||
"""
|
||||
parent = FloatLayout(size=(500,500))
|
||||
Window.clearcolor = (1, 1, 1, 1)
|
||||
|
||||
if self.densityDpi == 240:
|
||||
CompassPos = Vector(50., 200.)
|
||||
CompassSize = Vector(400., 400.)
|
||||
needleSize = Vector(100., 60.)
|
||||
stopButtonHeight = 60
|
||||
elif self.densityDpi == 320:
|
||||
CompassPos = Vector(75., 300.)
|
||||
CompassSize = Vector(600., 600.)
|
||||
needleSize = Vector(150., 90.)
|
||||
stopButtonHeight = 90
|
||||
else:
|
||||
Logger.info('COMPASS: widget size should be adopted - minimum used for densityDpi=%s'%(str(self.densityDpi)))
|
||||
CompassPos = Vector(50., 200.)
|
||||
CompassSize = Vector(400., 400.)
|
||||
needleSize = Vector(100., 60.)
|
||||
stopButtonHeight = 60
|
||||
|
||||
self.Compass = CompassWidget()
|
||||
parent.add_widget(self.Compass)
|
||||
self.Compass.build(pos=CompassPos,size=CompassSize)
|
||||
|
||||
self.needle = NeedleWidget()
|
||||
parent.add_widget(self.needle)
|
||||
self.needle.build(center=CompassPos+CompassSize/2.,needleSize=needleSize)
|
||||
|
||||
self.stopButton = Button(text='Stop', pos_hint={'right':1}, size_hint=(None,None), height=stopButtonHeight)
|
||||
parent.add_widget(self.stopButton)
|
||||
self.stopButton.bind(on_press=self.stopApp)
|
||||
|
||||
self.hw.magneticFieldSensor.changeStatus(True)
|
||||
Clock.schedule_interval(self.viewCompass, 1.)
|
||||
return parent
|
||||
|
||||
if __name__ in ('__main__', '__android__'):
|
||||
CompassApp().run()
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
1323529642.46
|
|
@ -28,8 +28,7 @@ class TestApp(App):
|
|||
|
||||
def build(self):
|
||||
# create a button, and attach animate() method as a on_press handler
|
||||
button = Button(size_hint=(None, None), text='plop')
|
||||
button.bind(on_press=self.animate)
|
||||
button = Button(size_hint=(None, None), text='plop', on_press=self.animate)
|
||||
return button
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -34,14 +34,14 @@ class StressCanvasApp(App):
|
|||
|
||||
label = Label(text='0')
|
||||
|
||||
btn_add100 = Button(text='+ 100 rects')
|
||||
btn_add100.bind(on_press=partial(self.add_rects, label, wid, 100))
|
||||
btn_add100 = Button(text='+ 100 rects',
|
||||
on_press=partial(self.add_rects, label, wid, 100))
|
||||
|
||||
btn_add500 = Button(text='+ 500 rects')
|
||||
btn_add500.bind(on_press=partial(self.add_rects, label, wid, 500))
|
||||
btn_add500 = Button(text='+ 500 rects',
|
||||
on_press=partial(self.add_rects, label, wid, 500))
|
||||
|
||||
btn_reset = Button(text='Reset')
|
||||
btn_reset.bind(on_press=partial(self.reset_rects, label, wid))
|
||||
btn_reset = Button(text='Reset',
|
||||
on_press=partial(self.reset_rects, label, wid))
|
||||
|
||||
layout = BoxLayout(size_hint=(1, None), height=50)
|
||||
layout.add_widget(btn_add100)
|
||||
|
|
|
@ -83,6 +83,20 @@ Builder.load_string('''
|
|||
Label:
|
||||
center: root.center
|
||||
text: 'Rectangle'
|
||||
|
||||
|
||||
<LineBezier>:
|
||||
canvas:
|
||||
Color:
|
||||
rgba: .1, .1, 1, .9
|
||||
Line:
|
||||
width: 2.
|
||||
bezier: (self.x, self.y, self.center_x - 40, self.y + 100, self.center_x + 40, self.y - 100, self.right, self.y)
|
||||
Label:
|
||||
center: root.center
|
||||
text: 'Bezier'
|
||||
|
||||
|
||||
''')
|
||||
|
||||
|
||||
|
@ -107,6 +121,9 @@ class LineCircle3(Widget):
|
|||
class LineRectangle(Widget):
|
||||
pass
|
||||
|
||||
class LineBezier(Widget):
|
||||
pass
|
||||
|
||||
class LineExtendedApp(App):
|
||||
def build(self):
|
||||
root = GridLayout(cols=2, padding=50, spacing=50)
|
||||
|
@ -117,6 +134,7 @@ class LineExtendedApp(App):
|
|||
root.add_widget(LineCircle2())
|
||||
root.add_widget(LineCircle3())
|
||||
root.add_widget(LineRectangle())
|
||||
root.add_widget(LineBezier())
|
||||
return root
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
This is the Kivy Catalog viewer. It serves two purposes:
|
||||
|
||||
1. To showcase the various widgets available in Kivy
|
||||
2. To allow interactive editing of Kivy language files
|
||||
to get immediate feedback as to how they work
|
||||
Known bugs:
|
||||
* The DropDown
|
||||
* Some widgets are still missing
|
|
@ -0,0 +1,15 @@
|
|||
#:kivy 1.4
|
||||
|
||||
AnchorLayout:
|
||||
anchor_x: "right"
|
||||
anchor_y: "bottom"
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 2"
|
||||
size_hint: .4, .2
|
||||
|
||||
Button:
|
||||
text: "Button 3"
|
||||
size_hint: .2, .2
|
|
@ -0,0 +1,14 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
padding: 20
|
||||
spacing: 10
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint: 1, None
|
||||
Button:
|
||||
text: "Button 2"
|
||||
size_hint: 1, 0.5
|
||||
Button:
|
||||
text: "Button 3"
|
|
@ -0,0 +1,27 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
cols: 2
|
||||
Button:
|
||||
text: "Button 1"
|
||||
Button:
|
||||
text: "Button 2"
|
||||
font_size: 24
|
||||
Button:
|
||||
text: "Button 3"
|
||||
background_color: .7, .7, 1, 1
|
||||
Button:
|
||||
text: "Button 4"
|
||||
on_press: self.text = 'pressed'
|
||||
on_release: self.text = 'Button 4'
|
||||
ToggleButton:
|
||||
text: "A toggle button"
|
||||
ToggleButton:
|
||||
text: "a toggle button in a group"
|
||||
group: "money"
|
||||
ToggleButton:
|
||||
text: "A toggle in the down state"
|
||||
state: "down"
|
||||
ToggleButton:
|
||||
text: "another toggle button in a group"
|
||||
group: "money"
|
|
@ -0,0 +1,27 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
cols: 2
|
||||
CheckBox:
|
||||
Label:
|
||||
text: "A checkbox"
|
||||
active: True
|
||||
CheckBox:
|
||||
Label:
|
||||
text: "Another checkbox"
|
||||
CheckBox:
|
||||
group: "money"
|
||||
Label:
|
||||
text: "A radio in a group"
|
||||
CheckBox:
|
||||
group: "money"
|
||||
Label:
|
||||
text: "Another radio in same group"
|
||||
active: True
|
||||
Switch:
|
||||
Label:
|
||||
text: "A Switch"
|
||||
Switch:
|
||||
active: True
|
||||
Label:
|
||||
text: "An active switch"
|
|
@ -0,0 +1,19 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
# Double as a Tabbed Panel Demo!
|
||||
TabbedPanel:
|
||||
tab_pos: "top_right"
|
||||
default_tab_text: "List View"
|
||||
default_tab_content: list_view_tab
|
||||
|
||||
TabbedPanelHeader:
|
||||
text: 'Icon View'
|
||||
content: icon_view_tab
|
||||
|
||||
FileChooserListView:
|
||||
id: list_view_tab
|
||||
|
||||
FileChooserIconView:
|
||||
id: icon_view_tab
|
||||
show_hidden: True
|
|
@ -0,0 +1,16 @@
|
|||
#:kivy 1.4
|
||||
|
||||
FloatLayout:
|
||||
Button:
|
||||
text: "Button 1"
|
||||
pos: 100, 100
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 2"
|
||||
pos: 200, 200
|
||||
size_hint: .4, .2
|
||||
|
||||
Button:
|
||||
text: "Button 3"
|
||||
pos_hint: {'x': .8, 'y': .6}
|
||||
size_hint: .2, .2
|
|
@ -0,0 +1,20 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
cols: 2
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint_x: None
|
||||
width: 100
|
||||
Button:
|
||||
text: "Button 2"
|
||||
Button:
|
||||
text: "Button 3"
|
||||
size_hint_x: None
|
||||
Button:
|
||||
text: "Button 4"
|
||||
Button:
|
||||
text: "Button 5"
|
||||
Button:
|
||||
text: "Button 6"
|
||||
size_hint_x: None
|
|
@ -0,0 +1,21 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
rows: 2
|
||||
Label:
|
||||
text: "Label 1"
|
||||
Label:
|
||||
text: "Label with\nmultiple lines"
|
||||
Label:
|
||||
text: "Label [color=ff3333]with[/color] [color=3333ff][b]markup[/b][/color]"
|
||||
markup: True
|
||||
Label:
|
||||
text: "Label with [ref=reference]reference[/ref]"
|
||||
markup: True
|
||||
on_ref_press: self.text = "ref clicked"
|
||||
Label:
|
||||
text: "different font"
|
||||
bold: True
|
||||
font_name: "data/fonts/DroidSansMono.ttf"
|
||||
font_size: 32
|
||||
valign: "bottom"
|
|
@ -0,0 +1,9 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
Image:
|
||||
source: "../../widgets/softboy.png"
|
||||
Video:
|
||||
source: "../../widgets/softboy.avi"
|
||||
state: "play"
|
|
@ -0,0 +1,4 @@
|
|||
#:kivy 1.4
|
||||
|
||||
RstDocument:
|
||||
text: "Welcome\n---------------\nThe Kivy Catalog is an interactive showcase of Kivy Widgets defined in the Kivy language. For each widget you see, you can directly edit the .kv language syntax to see what effects your changes have on the widget. Click 'Render' or hit 'Ctrl-S' to view your changes.\n\nThere is also a playground on this tab where you can test your Kivy language code directly. This is beta software. The basics seem to work, but some widgets are missing or don't have the ideal .kv representation. Not all widgets are represented yet. It is trivial to add a new .kv file to the interface.\n\nPull requests are welcome."
|
|
@ -0,0 +1,23 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
Bubble:
|
||||
size_hint: (None, None)
|
||||
size: (150, 50)
|
||||
pos_hint: {'center_x': .5, 'y': .6}
|
||||
arrow_pos: 'bottom_mid'
|
||||
orientation: 'horizontal'
|
||||
BubbleButton:
|
||||
text: 'Click'
|
||||
BubbleButton:
|
||||
text: 'A'
|
||||
BubbleButton:
|
||||
text: 'Bubble'
|
||||
Popup:
|
||||
id: popup
|
||||
title: "An example popup"
|
||||
content: popupcontent
|
||||
Label:
|
||||
id: popupcontent
|
||||
text: "Some text\nin the popup"
|
|
@ -0,0 +1,17 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
padding: 50
|
||||
ProgressBar:
|
||||
id: bar
|
||||
value: 140
|
||||
max: 300
|
||||
Slider:
|
||||
id: slider
|
||||
max: 200
|
||||
value: 140
|
||||
on_value: bar.value = self.value
|
||||
Slider:
|
||||
orientation: 'vertical'
|
||||
on_value: slider.value = self.value
|
|
@ -0,0 +1,5 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
RstDocument:
|
||||
text: ".. _top:\n\nHello world\n===========\n\nThis is an **emphased text**, some ``interpreted text``.\nAnd this is a reference to top_::\n\n $ print 'Hello world'\n"
|
|
@ -0,0 +1,16 @@
|
|||
#:kivy 1.4
|
||||
|
||||
FloatLayout:
|
||||
Scatter:
|
||||
size_hint: None, None
|
||||
size: 100, 100
|
||||
pos: 100, 100
|
||||
Image:
|
||||
source: "../../widgets/softboy.png"
|
||||
Scatter:
|
||||
size_hint: None, None
|
||||
size: 100, 100
|
||||
pos: 100, 100
|
||||
do_rotation: False
|
||||
Label:
|
||||
text: "something"
|
|
@ -0,0 +1,10 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
Spinner:
|
||||
text: "Work"
|
||||
values: "Work", "Home", "Mobile", "Skype"
|
||||
size_hint: (None, None)
|
||||
size: (100, 44)
|
||||
# Wanted to put DropDown here, too, but it seems not to be working too well when loaded from .kv
|
|
@ -0,0 +1,25 @@
|
|||
#:kivy 1.4
|
||||
|
||||
StackLayout:
|
||||
orientation: 'tb-lr'
|
||||
padding: 10
|
||||
spacing: 5
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint: .2, .4
|
||||
width: 100
|
||||
Button:
|
||||
text: "Button 2"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 3"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 4"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 5"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 6"
|
||||
size_hint: .2, .4
|
|
@ -0,0 +1,20 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
TextInput:
|
||||
text: "Single Line Input"
|
||||
multiline: False
|
||||
TextInput:
|
||||
text: "Text Input, start typing here\nmultiline\nsupport"
|
||||
background_color: .8, .8, 0, 1
|
||||
size_hint: 1, 3
|
||||
TextInput:
|
||||
text: "Password (but you can't see it)"
|
||||
password: True
|
||||
multiline: False
|
||||
on_text: viewer.text = self.text
|
||||
TextInput:
|
||||
id: viewer
|
||||
read_only: True
|
||||
text: "edit the password to see it here"
|
|
@ -0,0 +1,147 @@
|
|||
#:kivy 1.4
|
||||
#:import KivyLexer kivy.extras.highlight.KivyLexer
|
||||
|
||||
[ContainerToggle@ToggleButton]:
|
||||
group: "container_toggle"
|
||||
text: ctx.text
|
||||
on_press: root.parent.parent.parent.show_kv(*args)
|
||||
state: ctx.state if hasattr(ctx, "state") else "normal"
|
||||
|
||||
<Catalog>:
|
||||
language_box: language_box
|
||||
screen_manager: screen_manager
|
||||
auto_reload: chkbx.active
|
||||
info_label: info_lbl
|
||||
orientation: 'vertical'
|
||||
BoxLayout:
|
||||
BoxLayout:
|
||||
size_hint: None, 1
|
||||
orientation: "vertical"
|
||||
ContainerToggle:
|
||||
text: "Welcome"
|
||||
state: "down"
|
||||
ContainerToggle:
|
||||
text: "Float Layout"
|
||||
ContainerToggle:
|
||||
text: "Box Layout"
|
||||
ContainerToggle:
|
||||
text: "Anchor Layout"
|
||||
ContainerToggle:
|
||||
text: "Grid Layout"
|
||||
ContainerToggle:
|
||||
text: "Stack Layout"
|
||||
ContainerToggle:
|
||||
text: "Buttons"
|
||||
ContainerToggle:
|
||||
text: "Labels"
|
||||
ContainerToggle:
|
||||
text: "Booleans"
|
||||
ContainerToggle:
|
||||
text: "Progress Bar"
|
||||
ContainerToggle:
|
||||
text: "Media"
|
||||
ContainerToggle:
|
||||
text: "Text"
|
||||
ContainerToggle:
|
||||
text: "Popups"
|
||||
ContainerToggle:
|
||||
text: "Selectors"
|
||||
ContainerToggle:
|
||||
text: "File Choosers"
|
||||
ContainerToggle:
|
||||
text: "Scatter"
|
||||
ContainerToggle:
|
||||
text: "ReST"
|
||||
ScreenManager:
|
||||
id: screen_manager
|
||||
Screen:
|
||||
name: "Welcome"
|
||||
PlaygroundContainer:
|
||||
Screen:
|
||||
name: "Float Layout"
|
||||
FloatLayoutContainer
|
||||
Screen:
|
||||
name: "Box Layout"
|
||||
BoxLayoutContainer:
|
||||
Screen:
|
||||
name: "Anchor Layout"
|
||||
AnchorLayoutContainer:
|
||||
Screen:
|
||||
name: "Grid Layout"
|
||||
GridLayoutContainer:
|
||||
Screen:
|
||||
name: "Stack Layout"
|
||||
StackLayoutContainer:
|
||||
Screen:
|
||||
name: "Buttons"
|
||||
ButtonContainer:
|
||||
Screen:
|
||||
name: "Labels"
|
||||
LabelContainer:
|
||||
Screen:
|
||||
name: "Booleans"
|
||||
CheckBoxContainer:
|
||||
Screen:
|
||||
name: "Progress Bar"
|
||||
ProgressBarContainer:
|
||||
Screen:
|
||||
name: "Media"
|
||||
MediaContainer:
|
||||
Screen:
|
||||
name: "Text"
|
||||
TextContainer:
|
||||
Screen:
|
||||
name: "Popups"
|
||||
PopupContainer:
|
||||
Screen:
|
||||
name: "Selectors"
|
||||
SelectorsContainer:
|
||||
Screen:
|
||||
name: "File Choosers"
|
||||
FileChooserContainer:
|
||||
Screen:
|
||||
name: "Scatter"
|
||||
ScatterContainer:
|
||||
Screen:
|
||||
name: "ReST"
|
||||
RestContainer:
|
||||
|
||||
BoxLayout:
|
||||
id: bl
|
||||
orientation: "vertical"
|
||||
size_hint: None, 1
|
||||
width: 400
|
||||
KivyRenderTextInput:
|
||||
lexer: KivyLexer()
|
||||
text_size: self.width-20, self.height-20
|
||||
font_name: "data/fonts/DroidSansMono.ttf"
|
||||
valign: "top"
|
||||
id: language_box
|
||||
text: "This box will display the kivy language for whatever has been selected"
|
||||
on_text: root.schedule_reload()
|
||||
BoxLayout:
|
||||
size_hint: 1, None
|
||||
height: '30pt'
|
||||
BoxLayout:
|
||||
CheckBox:
|
||||
id: chkbx
|
||||
active: True
|
||||
Label:
|
||||
text: "Auto Reload"
|
||||
Button:
|
||||
text: 'Render Now'
|
||||
on_release: root.change_kv(*args)
|
||||
FloatLayout:
|
||||
size_hint: 1, None
|
||||
height: 0
|
||||
TextInput:
|
||||
id:info_lbl
|
||||
readonly: True
|
||||
font_size: '14sp'
|
||||
background_color: (0, 0, 0, 1)
|
||||
foreground_color: (1, 1, 1, 1)
|
||||
opacity:0
|
||||
size_hint: 1, None
|
||||
text_size: self.size
|
||||
height: '150pt'
|
||||
top: 0
|
|
@ -0,0 +1,166 @@
|
|||
import kivy
|
||||
kivy.require('1.4.2')
|
||||
import os
|
||||
import sys
|
||||
from kivy.app import App
|
||||
from kivy.factory import Factory
|
||||
from kivy.lang import Builder, Parser, ParserException
|
||||
from kivy.properties import ObjectProperty
|
||||
from kivy.config import Config
|
||||
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.popup import Popup
|
||||
from kivy.uix.label import Label
|
||||
from kivy.uix.codeinput import CodeInput
|
||||
from kivy.animation import Animation
|
||||
from kivy.clock import Clock
|
||||
|
||||
print Config.get('graphics', 'width')
|
||||
|
||||
Config.set('graphics', 'width', '1024')
|
||||
Config.set('graphics', 'height', '768')
|
||||
|
||||
'''List of classes that need to be instantiated in the factory from .kv files.
|
||||
'''
|
||||
CONTAINER_CLASSES = [c[:-3] for c in os.listdir('container_kvs')
|
||||
if c.endswith('.kv')]
|
||||
|
||||
|
||||
class Container(BoxLayout):
|
||||
'''A container is essentially a class that loads its root from a known
|
||||
.kv file.
|
||||
|
||||
The name of the .kv file is taken from the Container's class.
|
||||
We can't just use kv rules because the class may be edited
|
||||
in the interface and reloaded by the user.
|
||||
See :meth: change_kv where this happens.
|
||||
'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(Container, self).__init__(**kwargs)
|
||||
parser = Parser(content=file(self.kv_file).read())
|
||||
widget = Factory.get(parser.root.name)()
|
||||
Builder._apply_rule(widget, parser.root, parser.root)
|
||||
self.add_widget(widget)
|
||||
|
||||
@property
|
||||
def kv_file(self):
|
||||
'''Get the name of the kv file, a lowercase version of the class
|
||||
name.
|
||||
'''
|
||||
return os.path.join('container_kvs',
|
||||
self.__class__.__name__ + ".kv")
|
||||
|
||||
|
||||
for class_name in CONTAINER_CLASSES:
|
||||
globals()[class_name] = type(class_name, (Container,), {})
|
||||
|
||||
|
||||
class KivyRenderTextInput(CodeInput):
|
||||
def _keyboard_on_key_down(self, window, keycode, text, modifiers):
|
||||
is_osx = sys.platform == 'darwin'
|
||||
# Keycodes on OSX:
|
||||
ctrl, cmd = 64, 1024
|
||||
key, key_str = keycode
|
||||
|
||||
if text and not key in (self.interesting_keys.keys() + [27]):
|
||||
# This allows *either* ctrl *or* cmd, but not both.
|
||||
if modifiers == ['ctrl'] or (is_osx and modifiers == ['meta']):
|
||||
if key == ord('s'):
|
||||
self.parent.parent.parent.change_kv(True)
|
||||
return
|
||||
|
||||
super(KivyRenderTextInput, self)._keyboard_on_key_down(
|
||||
window, keycode, text, modifiers)
|
||||
|
||||
|
||||
class Catalog(BoxLayout):
|
||||
'''Catalog of widgets. This is the root widget of the app. It contains
|
||||
a tabbed pain of widgets that can be displayed and a textbox where .kv
|
||||
language files for widgets being demoed can be edited.
|
||||
|
||||
The entire interface for the Catalog is defined in kivycatalog.kv,
|
||||
although individual containers are defined in the container_kvs
|
||||
directory.
|
||||
|
||||
To add a container to the catalog,
|
||||
first create the .kv file in container_kvs
|
||||
The name of the file (sans .kv) will be the name of the widget available
|
||||
inside the kivycatalog.kv
|
||||
Finally modify kivycatalog.kv to add an AccordionItem
|
||||
to hold the new widget.
|
||||
Follow the examples in kivycatalog.kv to ensure the item
|
||||
has an appropriate id and the class has been referenced.
|
||||
|
||||
You do not need to edit any python code, just .kv language files!
|
||||
'''
|
||||
language_box = ObjectProperty()
|
||||
screen_manager = ObjectProperty()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(Catalog, self).__init__(**kwargs)
|
||||
self.show_kv(None)
|
||||
|
||||
def show_kv(self, object):
|
||||
'''Called when an accordionitem is collapsed or expanded. If it
|
||||
was expanded, we need to show the .kv language file associated with
|
||||
the newly revealed container.'''
|
||||
|
||||
# if object is not passed, it's initialization, we just need to load
|
||||
# the file
|
||||
if object:
|
||||
# one button must always be pressed, even if user presses it again
|
||||
if object.state == "normal":
|
||||
object.state = "down"
|
||||
|
||||
self.screen_manager.current = object.text
|
||||
|
||||
with open(self.screen_manager.current_screen.content.children[
|
||||
0].kv_file) as file:
|
||||
self.language_box.text = file.read()
|
||||
# reset undo/redo history
|
||||
self.language_box.reset_undo()
|
||||
|
||||
def schedule_reload(self):
|
||||
if self.auto_reload:
|
||||
Clock.unschedule(self.change_kv)
|
||||
Clock.schedule_once(self.change_kv, 2)
|
||||
|
||||
def change_kv(self, *largs):
|
||||
'''Called when the update button is clicked. Needs to update the
|
||||
interface for the currently active kv widget, if there is one based
|
||||
on the kv file the user entered. If there is an error in their kv
|
||||
syntax, show a nice popup.'''
|
||||
|
||||
kv_container = self.screen_manager.current_screen.content.children[0]
|
||||
try:
|
||||
parser = Parser(content=self.language_box.text.encode('utf8'))
|
||||
kv_container.clear_widgets()
|
||||
widget = Factory.get(parser.root.name)()
|
||||
Builder._apply_rule(widget, parser.root, parser.root)
|
||||
kv_container.add_widget(widget)
|
||||
except (SyntaxError, ParserException) as e:
|
||||
self.info_label.text = str(e)
|
||||
self.anim = Animation(top=190.0, opacity=1, d=2, t='in_back') +\
|
||||
Animation(top=190.0, d=2) +\
|
||||
Animation(top=0, opacity=0, d=2)
|
||||
self.anim.start(self.info_label)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
popup = Popup(title="Boom",
|
||||
content=Label(text='Something horrible happened while parsing'
|
||||
+ 'your Kivy Language', text_size=(350, None),
|
||||
size_hint=(None, None), size=(400, 400)))
|
||||
popup.open()
|
||||
|
||||
|
||||
class KivyCatalogApp(App):
|
||||
'''The kivy App that runs the main root. All we do is build a catalog
|
||||
widget into the root.'''
|
||||
def build(self):
|
||||
return Catalog()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
KivyCatalogApp().run()
|
|
@ -1,4 +1,5 @@
|
|||
#:kivy 1.0
|
||||
#: import GLShaderLexer pygments.lexers.GLShaderLexer
|
||||
|
||||
<ShaderEditor>:
|
||||
viewer: viewer
|
||||
|
@ -13,16 +14,18 @@
|
|||
text: 'Fragment Shader'
|
||||
size_hint_y: None
|
||||
height: self.texture_size[1] + 10
|
||||
TextInput:
|
||||
CodeInput:
|
||||
text: root.fs
|
||||
lexer: GLShaderLexer()
|
||||
on_text: root.fs = args[1]
|
||||
|
||||
Label:
|
||||
text: 'Vertex Shader'
|
||||
size_hint_y: None
|
||||
height: self.texture_size[1] + 10
|
||||
TextInput:
|
||||
CodeInput:
|
||||
text: root.vs
|
||||
lexer: GLShaderLexer()
|
||||
on_text: root.vs = args[1]
|
||||
|
||||
ShaderViewer:
|
||||
|
|
|
@ -16,6 +16,7 @@ from kivy.properties import StringProperty
|
|||
from kivy.clock import Clock
|
||||
import random
|
||||
|
||||
|
||||
class Showcase(FloatLayout):
|
||||
pass
|
||||
|
||||
|
@ -60,6 +61,7 @@ class BoxLayoutShowcase(FloatLayout):
|
|||
super(BoxLayoutShowcase, self).__init__(**kwargs)
|
||||
self.buttons = 0
|
||||
self.txt = 'horizontal'
|
||||
self.text_size = self.size
|
||||
Clock.schedule_once(self.add_button, 1)
|
||||
|
||||
def add_button(self, *l):
|
||||
|
@ -71,7 +73,10 @@ class BoxLayoutShowcase(FloatLayout):
|
|||
self.txt = self.blayout.orientation = 'horizontal'
|
||||
else:
|
||||
self.txt = self.blayout.orientation = 'vertical'
|
||||
self.blayout.add_widget(Button(text = self.txt))
|
||||
|
||||
btn = Button(text=self.txt, halign='center', valign='middle')
|
||||
btn.bind(size=btn.setter('text_size'))
|
||||
self.blayout.add_widget(btn)
|
||||
Clock.schedule_once(self.add_button, 1)
|
||||
|
||||
|
||||
|
@ -87,9 +92,9 @@ class FloatLayoutShowcase(FloatLayout):
|
|||
if self.buttons > 5:
|
||||
self.buttons = 0
|
||||
self.flayout.clear_widgets()
|
||||
self.flayout.add_widget(Button(text = 'no restrictions\n what so ever',
|
||||
size_hint = (None, None), size = (150, 40),
|
||||
pos_hint = {'x':random.random(), 'y': random.random()}))
|
||||
self.flayout.add_widget(Button(text='no restrictions\n what so ever',
|
||||
size_hint=(None, None), size=(150, 40),
|
||||
pos_hint={'x': random.random(), 'y': random.random()}))
|
||||
Clock.schedule_once(self.add_button, 1)
|
||||
|
||||
|
||||
|
@ -106,7 +111,7 @@ class GridLayoutShowcase(FloatLayout):
|
|||
|
||||
def add_button(self, *l):
|
||||
self.buttons += 1
|
||||
if self.buttons > 20:
|
||||
if self.buttons > 10:
|
||||
self.buttons = 0
|
||||
self.glayout.clear_widgets()
|
||||
if self.txt == "rows = 3":
|
||||
|
@ -117,7 +122,7 @@ class GridLayoutShowcase(FloatLayout):
|
|||
self.glayout.rows = 3
|
||||
self.glayout.cols = 7
|
||||
self.txt = "rows = 3"
|
||||
self.glayout.add_widget(Button(text = self.txt))
|
||||
self.glayout.add_widget(Button(text=self.txt))
|
||||
Clock.schedule_once(self.add_button, 1)
|
||||
|
||||
|
||||
|
@ -157,9 +162,11 @@ class StandardWidgets(FloatLayout):
|
|||
class ComplexWidgets(FloatLayout):
|
||||
pass
|
||||
|
||||
|
||||
class TreeViewWidgets(FloatLayout):
|
||||
pass
|
||||
|
||||
|
||||
class ShowcaseApp(App):
|
||||
|
||||
def on_select_node(self, instance, value):
|
||||
|
@ -243,17 +250,16 @@ class ShowcaseApp(App):
|
|||
return col
|
||||
|
||||
def show_popup(self):
|
||||
btnclose = Button(text='Close this popup', size_hint_y=None, height=50)
|
||||
btnclose = Button(text='Close this popup', size_hint_y=None, height='50sp')
|
||||
content = BoxLayout(orientation='vertical')
|
||||
content.add_widget(Label(text='Hello world'))
|
||||
content.add_widget(btnclose)
|
||||
popup = Popup(content=content, title='Modal popup example',
|
||||
size_hint=(None, None), size=(300, 300),
|
||||
auto_dismiss=False)
|
||||
size_hint=(None, None), size=('300dp', '300dp'))
|
||||
btnclose.bind(on_release=popup.dismiss)
|
||||
button = Button(text='Open popup', size_hint=(None, None),
|
||||
size=(150, 70))
|
||||
button.bind(on_release=popup.open)
|
||||
size=('150sp', '70dp'),
|
||||
on_release=popup.open)
|
||||
popup.open()
|
||||
col = AnchorLayout()
|
||||
col.add_widget(button)
|
||||
|
|
|
@ -14,17 +14,18 @@
|
|||
orientation: 'vertical'
|
||||
|
||||
BoxLayout:
|
||||
padding: 10
|
||||
spacing: 10
|
||||
padding: '10dp'
|
||||
spacing: '10dp'
|
||||
size_hint: 1, None
|
||||
pos_hint: {'top': 1}
|
||||
height: 44
|
||||
height: '44dp'
|
||||
Image:
|
||||
size_hint: None, None
|
||||
size: 24, 24
|
||||
source: 'data/logo/kivy-icon-24.png'
|
||||
size: '24dp', '24dp'
|
||||
source: 'data/logo/kivy-icon-64.png'
|
||||
mipmap: True
|
||||
Label:
|
||||
height: 24
|
||||
height: '24dp'
|
||||
text_size: self.width, None
|
||||
color: (1, 1, 1, .8)
|
||||
text: 'Kivy %s - Showcase' % kivy.__version__
|
||||
|
@ -55,7 +56,7 @@
|
|||
[Title@Label]
|
||||
pos_hint: {'center_x': .5, 'y': .3}
|
||||
text: ctx.text
|
||||
font_size: 22
|
||||
font_size: '29dp'
|
||||
|
||||
<AnchorLayoutShowcase>
|
||||
Title:
|
||||
|
@ -153,9 +154,9 @@
|
|||
|
||||
[HSeparator@Label]:
|
||||
size_hint_y: None
|
||||
height: 45
|
||||
height: max(dp(45), self.texture_size[1] + dp(10))
|
||||
text: ctx.text if 'text' in ctx else ''
|
||||
text_size: self.size
|
||||
text_size: self.width, None
|
||||
valign: 'middle'
|
||||
halign: 'center'
|
||||
canvas.before:
|
||||
|
@ -257,18 +258,18 @@
|
|||
TextInput:
|
||||
text: 'Monoline textinput'
|
||||
size_hint_y: None
|
||||
height: 30
|
||||
height: sp(30)
|
||||
|
||||
TextInput:
|
||||
text: 'This is a password'
|
||||
size_hint_y: None
|
||||
height: 30
|
||||
height: sp(30)
|
||||
password: True
|
||||
|
||||
TextInput:
|
||||
text: 'Readonly textinput'
|
||||
size_hint_y: None
|
||||
height: 30
|
||||
height: sp(30)
|
||||
readonly: True
|
||||
|
||||
TextInput:
|
||||
|
@ -313,6 +314,8 @@
|
|||
title: 'Panel 1'
|
||||
Label:
|
||||
text: 'This is a label fit to the content view'
|
||||
halign: 'center'
|
||||
text_size: self.width, None
|
||||
|
||||
AccordionItem:
|
||||
title: 'Panel 2'
|
||||
|
@ -323,6 +326,8 @@
|
|||
title: 'Panel 3'
|
||||
Label:
|
||||
text: 'This is a label fit to the content view'
|
||||
halign: 'center'
|
||||
text_size: self.width, None
|
||||
|
||||
|
||||
Accordion:
|
||||
|
@ -333,6 +338,7 @@
|
|||
title: 'Panel 1'
|
||||
Label:
|
||||
text: 'This is a label fit to the content view'
|
||||
text_size: self.width, None
|
||||
|
||||
AccordionItem:
|
||||
title: 'Panel 2'
|
||||
|
@ -343,6 +349,7 @@
|
|||
title: 'Panel 3'
|
||||
Label:
|
||||
text: 'This is a label fit to the content view'
|
||||
text_size: self.width, None
|
||||
|
||||
|
||||
VSeparator
|
||||
|
|
|
@ -10,17 +10,18 @@
|
|||
size: self.size
|
||||
|
||||
BoxLayout:
|
||||
padding: 10
|
||||
spacing: 10
|
||||
padding: '10dp'
|
||||
spacing: '10dp'
|
||||
size_hint: 1, None
|
||||
pos_hint: {'top': 1}
|
||||
height: 44
|
||||
height: '44dp'
|
||||
Image:
|
||||
size_hint: None, None
|
||||
size: 24, 24
|
||||
source: 'data/logo/kivy-icon-24.png'
|
||||
size: '24dp', '24dp'
|
||||
source: 'data/logo/kivy-icon-64.png'
|
||||
mipmap: True
|
||||
Label:
|
||||
height: 24
|
||||
height: '24dp'
|
||||
text_size: self.width, None
|
||||
color: (1, 1, 1, .8)
|
||||
text: 'Kivy %s - Touchtracer' % kivy.__version__
|
||||
|
|
|
@ -4,14 +4,16 @@ from kivy.graphics import Color, Ellipse
|
|||
|
||||
|
||||
class MyPaintWidget(Widget):
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
with self.canvas:
|
||||
Color(1, 1, 0)
|
||||
d = 30.
|
||||
Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))
|
||||
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
|
||||
|
||||
|
||||
class MyPaintApp(App):
|
||||
|
||||
def build(self):
|
||||
return MyPaintWidget()
|
||||
|
||||
|
|
|
@ -4,19 +4,20 @@ from kivy.graphics import Color, Ellipse, Line
|
|||
|
||||
|
||||
class MyPaintWidget(Widget):
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
userdata = touch.ud
|
||||
with self.canvas:
|
||||
Color(1, 1, 0)
|
||||
d = 30.
|
||||
Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))
|
||||
userdata['line'] = Line(points=(touch.x, touch.y))
|
||||
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
|
||||
touch.ud['line'] = Line(points=(touch.x, touch.y))
|
||||
|
||||
def on_touch_move(self, touch):
|
||||
touch.ud['line'].points += [touch.x, touch.y]
|
||||
|
||||
|
||||
class MyPaintApp(App):
|
||||
|
||||
def build(self):
|
||||
return MyPaintWidget()
|
||||
|
||||
|
|
|
@ -5,20 +5,21 @@ from kivy.graphics import Color, Ellipse, Line
|
|||
|
||||
|
||||
class MyPaintWidget(Widget):
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
userdata = touch.ud
|
||||
userdata['color'] = c = (random(), random(), random())
|
||||
color = (random(), random(), random())
|
||||
with self.canvas:
|
||||
Color(*c)
|
||||
Color(*color)
|
||||
d = 30.
|
||||
Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))
|
||||
userdata['line'] = Line(points=(touch.x, touch.y))
|
||||
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
|
||||
touch.ud['line'] = Line(points=(touch.x, touch.y))
|
||||
|
||||
def on_touch_move(self, touch):
|
||||
touch.ud['line'].points += [touch.x, touch.y]
|
||||
|
||||
|
||||
class MyPaintApp(App):
|
||||
|
||||
def build(self):
|
||||
return MyPaintWidget()
|
||||
|
||||
|
|
|
@ -8,13 +8,12 @@ from kivy.graphics import Color, Ellipse, Line
|
|||
class MyPaintWidget(Widget):
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
userdata = touch.ud
|
||||
userdata['color'] = c = (random(), 1, 1)
|
||||
color = (random(), 1, 1)
|
||||
with self.canvas:
|
||||
Color(*c, mode='hsv')
|
||||
d = 30
|
||||
Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))
|
||||
userdata['line'] = Line(points=(touch.x, touch.y))
|
||||
Color(*color, mode='hsv')
|
||||
d = 30.
|
||||
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
|
||||
touch.ud['line'] = Line(points=(touch.x, touch.y))
|
||||
|
||||
def on_touch_move(self, touch):
|
||||
touch.ud['line'].points += [touch.x, touch.y]
|
||||
|
|
|
@ -17,7 +17,7 @@ class BlehApp(App):
|
|||
def build(self):
|
||||
root = BoxLayout()
|
||||
for idx, word in enumerate(('Hello', 'World')):
|
||||
wid = Builder.template('BlehItem', {
|
||||
wid = Builder.template('BlehItem', **{
|
||||
'idx': idx, 'word': word,
|
||||
})
|
||||
root.add_widget(wid)
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
from kivy.uix.gridlayout import GridLayout
|
||||
from kivy.app import App
|
||||
from kivy.lang import Builder
|
||||
|
||||
Builder.load_string('''
|
||||
<Demo>:
|
||||
cols: 1
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
Button:
|
||||
size_hint_x: 0.4
|
||||
pos_hint: {'x': 0}
|
||||
text: 'pos_hint: x=0'
|
||||
|
||||
Button:
|
||||
size_hint_x: 0.2
|
||||
pos_hint: {'center_x': 0.5}
|
||||
text: 'pos_hint: center_x=0.5'
|
||||
|
||||
Button:
|
||||
size_hint_x: 0.4
|
||||
pos_hint: {'right': 1}
|
||||
text: 'pos_hint: right=1'
|
||||
|
||||
BoxLayout:
|
||||
Button:
|
||||
size_hint_y: 0.4
|
||||
pos_hint: {'y': 0}
|
||||
text: 'pos_hint: y=0'
|
||||
|
||||
Button:
|
||||
size_hint_y: 0.2
|
||||
pos_hint: {'center_y': .5}
|
||||
text: 'pos_hint: center_y=0.5'
|
||||
|
||||
Button:
|
||||
size_hint_y: 0.4
|
||||
pos_hint: {'top': 1}
|
||||
text: 'pos_hint: top=1'
|
||||
''')
|
||||
|
||||
class Demo(GridLayout):
|
||||
pass
|
||||
|
||||
|
||||
class DemoApp(App):
|
||||
def build(self):
|
||||
return Demo()
|
||||
|
||||
if __name__ == '__main__':
|
||||
DemoApp().run()
|
|
@ -0,0 +1,37 @@
|
|||
'''
|
||||
Carousel example with button inside.
|
||||
This is a tiny test for testing the scroll distance/timeout
|
||||
And ensure the down/up are dispatched if no gesture is done.
|
||||
'''
|
||||
from kivy.uix.carousel import Carousel
|
||||
from kivy.uix.gridlayout import GridLayout
|
||||
from kivy.app import App
|
||||
from kivy.lang import Builder
|
||||
|
||||
Builder.load_string('''
|
||||
<Page>:
|
||||
cols: 3
|
||||
Label:
|
||||
text: str(id(root))
|
||||
Button
|
||||
Button
|
||||
Button
|
||||
Button
|
||||
Button
|
||||
Button
|
||||
Button
|
||||
Button
|
||||
''')
|
||||
|
||||
class Page(GridLayout):
|
||||
pass
|
||||
|
||||
class TestApp(App):
|
||||
def build(self):
|
||||
root = Carousel()
|
||||
for x in xrange(10):
|
||||
root.add_widget(Page())
|
||||
return root
|
||||
|
||||
if __name__ == '__main__':
|
||||
TestApp().run()
|
|
@ -0,0 +1,179 @@
|
|||
from kivy.app import App
|
||||
from kivy.extras.highlight import KivyLexer
|
||||
from kivy.uix.spinner import Spinner, SpinnerOption
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.codeinput import CodeInput
|
||||
from kivy.uix.popup import Popup
|
||||
from kivy.properties import ListProperty
|
||||
from kivy.core.window import Window
|
||||
from pygments import lexers
|
||||
from pygame import font as fonts
|
||||
import codecs, os
|
||||
|
||||
example_text = '''
|
||||
---------------------Python----------------------------------
|
||||
import kivy
|
||||
kivy.require('1.0.6') # replace with your current kivy version !
|
||||
from kivy.app import App
|
||||
from kivy.uix.button import Button
|
||||
|
||||
class MyApp(App):
|
||||
def build(self):
|
||||
return Button(text='Hello World')
|
||||
|
||||
if __name__ == '__main__':
|
||||
MyApp().run()
|
||||
----------------------Java-----------------------------------
|
||||
|
||||
public static byte toUnsignedByte(int intVal) {
|
||||
byte byteVal;
|
||||
return (byte)(intVal & 0xFF);
|
||||
}
|
||||
---------------------kv lang---------------------------------
|
||||
#:kivy 1.0
|
||||
|
||||
<YourWidget>:
|
||||
canvas:
|
||||
Color:
|
||||
rgb: .5, .5, .5
|
||||
Rectangle:
|
||||
pos: self.pos
|
||||
size: self.size
|
||||
---------------------HTML------------------------------------
|
||||
<!-- Place this tag where you want the +1 button to render. -->
|
||||
<div class="g-plusone" data-annotation="inline" data-width="300"></div>
|
||||
|
||||
<!-- Place this tag after the last +1 button tag. -->
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
var po = document.createElement('script');
|
||||
po.type = 'text/javascript';
|
||||
po.async = true;
|
||||
po.src = 'https://apis.google.com/js/plusone.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(po, s);
|
||||
})();
|
||||
</script>
|
||||
'''
|
||||
|
||||
|
||||
class Fnt_SpinnerOption(SpinnerOption):
|
||||
pass
|
||||
|
||||
|
||||
class LoadDialog(Popup):
|
||||
|
||||
def load(self, path, selection):
|
||||
self.choosen_file = [None, ]
|
||||
self.choosen_file = selection
|
||||
Window.title = selection[0][selection[0].rfind(os.sep)+1:]
|
||||
self.dismiss()
|
||||
|
||||
def cancel(self):
|
||||
self.dismiss()
|
||||
|
||||
|
||||
class SaveDialog(Popup):
|
||||
|
||||
def save(self, path, selection):
|
||||
_file = codecs.open(selection, 'w', encoding='utf8')
|
||||
_file.write(self.text)
|
||||
Window.title = selection[selection.rfind(os.sep)+1:]
|
||||
_file.close()
|
||||
self.dismiss()
|
||||
|
||||
def cancel(self):
|
||||
self.dismiss()
|
||||
|
||||
|
||||
class CodeInputTest(App):
|
||||
|
||||
files = ListProperty([None, ])
|
||||
|
||||
def build(self):
|
||||
b = BoxLayout(orientation='vertical')
|
||||
languages = Spinner(
|
||||
text='language',
|
||||
values=sorted(['KvLexer', ] + lexers.LEXERS.keys()))
|
||||
|
||||
languages.bind(text=self.change_lang)
|
||||
|
||||
menu = BoxLayout(
|
||||
size_hint_y=None,
|
||||
height='30pt')
|
||||
fnt_size = Spinner(
|
||||
text='12',
|
||||
values=map(str, range(5, 40)))
|
||||
fnt_size.bind(text=self._update_size)
|
||||
fnt_name = Spinner(
|
||||
text='DroidSansMono',
|
||||
option_cls=Fnt_SpinnerOption,
|
||||
values=sorted(map(str, fonts.get_fonts())))
|
||||
fnt_name.bind(text=self._update_font)
|
||||
mnu_file = Spinner(
|
||||
text='File',
|
||||
values=('Open', 'SaveAs', 'Save', 'Close'))
|
||||
mnu_file.bind(text=self._file_menu_selected)
|
||||
|
||||
menu.add_widget(mnu_file)
|
||||
menu.add_widget(fnt_size)
|
||||
menu.add_widget(fnt_name)
|
||||
menu.add_widget(languages)
|
||||
b.add_widget(menu)
|
||||
|
||||
self.codeinput = CodeInput(
|
||||
lexer=KivyLexer(),
|
||||
font_name='data/fonts/DroidSansMono.ttf', font_size=12,
|
||||
text=example_text)
|
||||
|
||||
b.add_widget(self.codeinput)
|
||||
|
||||
return b
|
||||
|
||||
def _update_size(self, instance, size):
|
||||
self.codeinput.font_size = float(size)
|
||||
|
||||
def _update_font(self, instance, fnt_name):
|
||||
instance.font_name = self.codeinput.font_name =\
|
||||
fonts.match_font(fnt_name)
|
||||
|
||||
def _file_menu_selected(self, instance, value):
|
||||
if value == 'File':
|
||||
return
|
||||
instance.text = 'File'
|
||||
if value == 'Open':
|
||||
if not hasattr(self, 'load_dialog'):
|
||||
self.load_dialog = LoadDialog()
|
||||
self.load_dialog.open()
|
||||
self.load_dialog.bind(choosen_file=self.setter('files'))
|
||||
elif value == 'SaveAs':
|
||||
if not hasattr(self, 'saveas_dialog'):
|
||||
self.saveas_dialog = SaveDialog()
|
||||
self.saveas_dialog.text = self.codeinput.text
|
||||
self.saveas_dialog.open()
|
||||
elif value == 'Save':
|
||||
if self.files[0]:
|
||||
_file = codecs.open(self.files[0], 'w', encoding='utf8')
|
||||
_file.write(self.codeinput.text)
|
||||
_file.close()
|
||||
elif value == 'Close':
|
||||
if self.files[0]:
|
||||
self.codeinput.text = ''
|
||||
Window.title = 'untitled'
|
||||
|
||||
def on_files(self, instance, values):
|
||||
if not values[0]:
|
||||
return
|
||||
_file = codecs.open(values[0], 'r', encoding='utf8')
|
||||
self.codeinput.text = _file.read()
|
||||
_file.close()
|
||||
|
||||
def change_lang(self, instance, l):
|
||||
if l == 'KvLexer':
|
||||
lx = KivyLexer()
|
||||
else:
|
||||
lx = lexers.get_lexer_by_name(lexers.LEXERS[l][2][0])
|
||||
self.codeinput.lexer = lx
|
||||
|
||||
if __name__ == '__main__':
|
||||
CodeInputTest().run()
|
|
@ -0,0 +1,55 @@
|
|||
#:import fonts pygame.font
|
||||
#:import os os
|
||||
<Fnt_SpinnerOption>:
|
||||
fnt_name: fonts.match_font(self.text)
|
||||
font_name: self.fnt_name if self.fnt_name else self.font_name
|
||||
|
||||
<LoadDialog>:
|
||||
title: filechooser.path
|
||||
choosen_file: None
|
||||
BoxLayout:
|
||||
size: root.size
|
||||
pos: root.pos
|
||||
orientation: "vertical"
|
||||
FileChooserListView:
|
||||
id: filechooser
|
||||
path: os.getcwd()
|
||||
|
||||
BoxLayout:
|
||||
size_hint_y: None
|
||||
height: 30
|
||||
Button:
|
||||
text: "Cancel"
|
||||
on_release: root.cancel()
|
||||
|
||||
Button:
|
||||
text: "Load"
|
||||
on_release: root.load(filechooser.path, filechooser.selection)
|
||||
|
||||
<SaveDialog>:
|
||||
text_input: text_input
|
||||
BoxLayout:
|
||||
size: root.size
|
||||
pos: root.pos
|
||||
orientation: "vertical"
|
||||
FileChooserListView:
|
||||
id: filechooser
|
||||
path: os.getcwd()
|
||||
on_selection: text_input.text = self.selection and self.selection[0] or ''
|
||||
|
||||
TextInput:
|
||||
id: text_input
|
||||
size_hint_y: None
|
||||
height: 30
|
||||
multiline: False
|
||||
|
||||
BoxLayout:
|
||||
size_hint_y: None
|
||||
height: 30
|
||||
Button:
|
||||
text: "Cancel"
|
||||
on_release: root.cancel()
|
||||
|
||||
Button:
|
||||
text: "Save"
|
||||
on_release: root.save(filechooser.path, text_input.text)
|
|
@ -22,8 +22,7 @@ class CustomPopup(Popup):
|
|||
|
||||
class TestApp(App):
|
||||
def build(self):
|
||||
b = Button()
|
||||
b.bind(on_press=self.show_popup)
|
||||
b = Button(on_press=self.show_popup)
|
||||
return b
|
||||
|
||||
def show_popup(self, b):
|
||||
|
|
|
@ -54,8 +54,9 @@ Builder.load_string('''
|
|||
<PanelLeft>
|
||||
size_hint: (.45, .45)
|
||||
pos_hint: {'center_x': .25, 'y': .55}
|
||||
#replace the default tab with our custom tab
|
||||
#replace the default tab with our custom tab class
|
||||
default_tab_cls: sh.__class__
|
||||
do_default_tab: True
|
||||
default_tab_content: default_content
|
||||
tab_width: 40
|
||||
tab_height: 70
|
||||
|
@ -100,19 +101,18 @@ Builder.load_string('''
|
|||
size_hint: None, 1
|
||||
orientation: 'vertical'
|
||||
width: 22
|
||||
Widget:
|
||||
Button:
|
||||
border: 0,0,0,0
|
||||
background_normal: 'tools/theming/defaulttheme/close.png'
|
||||
on_release: root.panel.remove_widget(root)
|
||||
Widget:
|
||||
Image:
|
||||
source: 'tools/theming/defaulttheme/close.png'
|
||||
on_touch_down:
|
||||
if self.collide_point(*args[1].pos) :\
|
||||
root.panel.remove_widget(root)
|
||||
|
||||
|
||||
<PanelRight>
|
||||
tab_pos: 'top_right'
|
||||
size_hint: (.45, .45)
|
||||
pos_hint: {'center_x': .75, 'y': .55}
|
||||
#replace the default tab with our custom tab
|
||||
# replace the default tab with our custom tab
|
||||
default_tab: def_tab
|
||||
#allow variable tab width
|
||||
tab_width: None
|
||||
|
@ -170,29 +170,23 @@ Builder.load_string('''
|
|||
tab_pos: 'bottom_left'
|
||||
size_hint: (.45, .45)
|
||||
pos_hint: {'center_x': .25, 'y': .02}
|
||||
default_tab_text: 'Settings'
|
||||
default_tab_content: default_content
|
||||
FloatLayout:
|
||||
do_default_tab: False
|
||||
|
||||
TabbedPanelItem:
|
||||
id: settings
|
||||
text: 'Settings'
|
||||
RstDocument:
|
||||
id: default_content
|
||||
text: '\\n'.join(("Normal tabs", "-------------",\
|
||||
"Tabs in \\'%s\\' position" %root.tab_pos))
|
||||
Image:
|
||||
id: tab_2_content
|
||||
pos: self.parent.pos
|
||||
size: self.parent.size
|
||||
source: 'data/images/defaulttheme-0.png'
|
||||
Image:
|
||||
id: tab_3_content
|
||||
pos:self.parent.pos
|
||||
size: self.parent.size
|
||||
source: 'data/images/image-loading.gif'
|
||||
TabbedPanelHeader:
|
||||
"Tabs in \\'%s\\' position" %root.tab_pos))
|
||||
TabbedPanelItem:
|
||||
text: 'tab2'
|
||||
content: tab_2_content
|
||||
TabbedPanelHeader:
|
||||
BubbleButton:
|
||||
text: 'switch to settings'
|
||||
on_press: root.switch_to(settings)
|
||||
TabbedPanelItem:
|
||||
text: 'tab3'
|
||||
content: tab_3_content
|
||||
Image:
|
||||
source: 'data/images/image-loading.gif'
|
||||
|
||||
<PanelbRight>
|
||||
tab_pos: 'right_top'
|
||||
|
@ -257,26 +251,23 @@ Builder.load_string('''
|
|||
|
||||
|
||||
class Tp(TabbedPanel):
|
||||
|
||||
#override tab switching method to animate on tab switch
|
||||
def switch_to(self, header):
|
||||
anim = Animation(color=(1, 1, 1, 0), d =.24, t = 'in_out_quad')
|
||||
anim = Animation(opacity=0, d=.24, t='in_out_quad')
|
||||
|
||||
def start_anim(_anim, child, in_complete, *lt):
|
||||
if hasattr(child, 'color'):
|
||||
_anim.start(child)
|
||||
elif not in_complete:
|
||||
_on_complete()
|
||||
_anim.start(child)
|
||||
|
||||
def _on_complete(*lt):
|
||||
if hasattr(header.content, 'color'):
|
||||
header.content.color = (0, 0, 0, 0)
|
||||
anim = Animation(color =
|
||||
(1, 1, 1, 1), d =.23, t = 'in_out_quad')
|
||||
if header.content:
|
||||
header.content.opacity = 0
|
||||
anim = Animation(opacity=1, d=.43, t='in_out_quad')
|
||||
start_anim(anim, header.content, True)
|
||||
super(Tp, self).switch_to(header)
|
||||
|
||||
anim.bind(on_complete = _on_complete)
|
||||
if self.content:
|
||||
if self.current_tab.content:
|
||||
start_anim(anim, self.current_tab.content, False)
|
||||
else:
|
||||
_on_complete()
|
||||
|
|
|
@ -15,30 +15,24 @@ Builder.load_string("""
|
|||
<Test>:
|
||||
size_hint: .5, .5
|
||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||
default_tab_content: set1_content
|
||||
do_default_tab: False
|
||||
|
||||
Label:
|
||||
id: set1_content
|
||||
text: 'First tab content area'
|
||||
|
||||
BoxLayout:
|
||||
id: set2_content
|
||||
TabbedPanelItem:
|
||||
text: 'first tab'
|
||||
Label:
|
||||
text: 'Second tab content area'
|
||||
Button:
|
||||
text: 'Button that does nothing'
|
||||
text: 'First tab content area'
|
||||
TabbedPanelItem:
|
||||
text: 'tab2'
|
||||
BoxLayout:
|
||||
Label:
|
||||
text: 'Second tab content area'
|
||||
Button:
|
||||
text: 'Button that does nothing'
|
||||
TabbedPanelItem:
|
||||
text: 'tab3'
|
||||
RstDocument:
|
||||
text: '\\n'.join(("Hello world", "-----------", "You are in the third tab."))
|
||||
|
||||
RstDocument:
|
||||
id: set3_content
|
||||
text: '\\n'.join(("Hello world", "-----------", "You are in the third tab."))
|
||||
|
||||
# now categorize widgets inserted above in a specific header
|
||||
TabbedPanelHeader:
|
||||
text: 'Tab 2'
|
||||
content: set2_content
|
||||
TabbedPanelHeader:
|
||||
text: 'Tab 3'
|
||||
content: set3_content
|
||||
""")
|
||||
|
||||
class Test(TabbedPanel):
|
||||
|
|
|
@ -5,25 +5,50 @@ from kivy.lang import Builder
|
|||
from kivy.properties import StringProperty, ObjectProperty
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.floatlayout import FloatLayout
|
||||
from kivy.uix.spinner import SpinnerOption
|
||||
from kivy.uix.popup import Popup
|
||||
import os
|
||||
|
||||
|
||||
Builder.load_string(
|
||||
'''
|
||||
#: import utils kivy
|
||||
#: import os os
|
||||
#: import font pygame.font
|
||||
#: import Factory kivy.factory.Factory
|
||||
<FntSpinnerOption>
|
||||
fnt_name: font.match_font(self.text)
|
||||
font_name: self.fnt_name if self.fnt_name else self.font_name
|
||||
|
||||
<Unicode_TextInput>
|
||||
orientation: 'vertical'
|
||||
txt_input: unicode_txt
|
||||
spnr_fnt: fnt_spnr
|
||||
BoxLayout:
|
||||
size_hint: 1, .05
|
||||
Spinner:
|
||||
id: fnt_spnr
|
||||
text: 'DroidSansMono'
|
||||
fnt_name: font.match_font(self.text)
|
||||
font_name: self.fnt_name if self.fnt_name else self.font_name
|
||||
values: sorted(font.get_fonts())
|
||||
option_cls: Factory.FntSpinnerOption
|
||||
Spinner:
|
||||
id: fntsz_spnr
|
||||
text: '15'
|
||||
values: map(str, map(sp, range(5,39)))
|
||||
ScrollView:
|
||||
size_hint: 1, .9
|
||||
TextInput:
|
||||
id: unicode_txt
|
||||
background_color: [.5, .5, .5, 1]
|
||||
foreground_color: .5, 1, .5, 1
|
||||
background_color: .8811, .8811, .8811, 1
|
||||
foreground_color: 0, 0, 0, 1
|
||||
font_name: fnt_spnr.font_name
|
||||
font_size: fntsz_spnr.text + 'sp'
|
||||
text: root.unicode_string
|
||||
size_hint: 1, None
|
||||
height: 1364
|
||||
height: 1494
|
||||
on_font_name: self.height = (self.line_height + self.padding_y) * (len(self._lines)-1)
|
||||
BoxLayout:
|
||||
size_hint: 1, .05
|
||||
Label:
|
||||
|
@ -86,6 +111,8 @@ if _platform == 'linux' else '/system/fonts' if _platform == 'android' else os.p
|
|||
(filechooser.path, filechooser.selection)
|
||||
''')
|
||||
|
||||
class FntSpinnerOption(SpinnerOption):
|
||||
pass
|
||||
|
||||
class LoadDialog(FloatLayout):
|
||||
load = ObjectProperty(None)
|
||||
|
@ -172,6 +199,9 @@ Yiddish: דער גיך ברוין פוקס דזשאַמפּס איבער
|
|||
|
||||
def load(self, _path, _fname):
|
||||
self.txt_input.font_name = _fname[0]
|
||||
_f_name = _fname[0][_fname[0].rfind(os.sep) + 1:]
|
||||
self.spnr_fnt.text = _f_name[:_f_name.rfind('.')]
|
||||
|
||||
self._popup.dismiss()
|
||||
|
||||
def show_load(self):
|
||||
|
|
|
@ -28,7 +28,7 @@ __all__ = (
|
|||
'kivy_config_fn', 'kivy_usermodules_dir',
|
||||
)
|
||||
|
||||
__version__ = '1.4.1-dev'
|
||||
__version__ = '1.4.2-dev'
|
||||
|
||||
import sys
|
||||
import shutil
|
||||
|
@ -201,7 +201,7 @@ for option in kivy_options:
|
|||
if key in environ:
|
||||
try:
|
||||
if type(kivy_options[option]) in (list, tuple):
|
||||
kivy_options[option] = (str(environ[key]), )
|
||||
kivy_options[option] = environ[key].split(',')
|
||||
else:
|
||||
kivy_options[option] = environ[key].lower() in \
|
||||
('true', '1', 'yes', 'yup')
|
||||
|
@ -369,11 +369,15 @@ if not environ.get('KIVY_DOC_INCLUDE'):
|
|||
Logger.info('Core: Kivy configuration saved.')
|
||||
sys.exit(0)
|
||||
|
||||
# android hooks: force fullscreen and add android touch input provider
|
||||
if platform() == 'android':
|
||||
from kivy.config import Config
|
||||
Config.set('graphics', 'fullscreen', 'auto')
|
||||
Config.remove_section('input')
|
||||
Config.add_section('input')
|
||||
Config.set('input', 'androidtouch', 'android')
|
||||
# configure all activated modules
|
||||
from kivy.modules import Modules
|
||||
Modules.configure()
|
||||
|
||||
# android hooks: force fullscreen and add android touch input provider
|
||||
if platform() == 'android':
|
||||
from kivy.config import Config
|
||||
Config.set('graphics', 'fullscreen', 'auto')
|
||||
Config.remove_section('input')
|
||||
Config.add_section('input')
|
||||
Config.set('input', 'androidtouch', 'android')
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
cdef class EventDispatcher(object):
|
||||
cdef dict __event_stack
|
||||
cdef dict __properties
|
||||
cdef dict __storage
|
||||
cpdef dict properties(self)
|
||||
cdef readonly int uid
|
|
@ -19,7 +19,6 @@ from functools import partial
|
|||
from kivy.weakmethod import WeakMethod
|
||||
from kivy.properties cimport Property, ObjectProperty
|
||||
|
||||
cdef tuple forbidden_properties = ('touch_down', 'touch_move', 'touch_up')
|
||||
cdef int widget_uid = 0
|
||||
cdef dict cache_properties = {}
|
||||
|
||||
|
@ -29,18 +28,17 @@ cdef class EventDispatcher(object):
|
|||
See the module docstring for usage.
|
||||
'''
|
||||
|
||||
cdef dict __event_stack
|
||||
cdef dict __properties
|
||||
|
||||
def __cinit__(self, *largs, **kwargs):
|
||||
global widget_uid, cache_properties
|
||||
cdef dict widget_dict = self.__dict__
|
||||
cdef dict cp = cache_properties
|
||||
cdef dict attrs_found
|
||||
cdef list attrs
|
||||
cdef Property attr
|
||||
cdef str k
|
||||
|
||||
self.__event_stack = {}
|
||||
self.__storage = {}
|
||||
|
||||
__cls__ = self.__class__
|
||||
|
||||
# XXX for the moment, we need to create a uniq id for properties.
|
||||
|
@ -48,8 +46,7 @@ cdef class EventDispatcher(object):
|
|||
# are longer than using a custom __uid. I hope we can figure out a way
|
||||
# of doing that without require any python code. :)
|
||||
widget_uid += 1
|
||||
widget_dict['__uid'] = widget_uid
|
||||
widget_dict['__storage'] = {}
|
||||
self.uid = widget_uid
|
||||
|
||||
if __cls__ not in cp:
|
||||
attrs_found = cp[__cls__] = {}
|
||||
|
@ -58,7 +55,7 @@ cdef class EventDispatcher(object):
|
|||
uattr = getattr(__cls__, k)
|
||||
if not isinstance(uattr, Property):
|
||||
continue
|
||||
if k in forbidden_properties:
|
||||
if k == 'touch_down' or k == 'touch_move' or k == 'touch_up':
|
||||
raise Exception('The property <%s> have a forbidden name' % k)
|
||||
attrs_found[k] = uattr
|
||||
else:
|
||||
|
@ -175,6 +172,7 @@ cdef class EventDispatcher(object):
|
|||
print 'press on button', obj, 'with date:', value
|
||||
|
||||
'''
|
||||
cdef Property prop
|
||||
for key, value in kwargs.iteritems():
|
||||
if key[:3] == 'on_':
|
||||
if key not in self.__event_stack:
|
||||
|
@ -183,13 +181,15 @@ cdef class EventDispatcher(object):
|
|||
handler = WeakMethod(value)
|
||||
self.__event_stack[key].append(handler)
|
||||
else:
|
||||
self.__properties[key].bind(self, value)
|
||||
prop = self.__properties[key]
|
||||
prop.bind(self, value)
|
||||
|
||||
def unbind(self, **kwargs):
|
||||
'''Unbind properties from callback functions.
|
||||
|
||||
Same usage as :func:`bind`.
|
||||
'''
|
||||
cdef Property prop
|
||||
for key, value in kwargs.iteritems():
|
||||
if key[:3] == 'on_':
|
||||
if key not in self.__event_stack:
|
||||
|
@ -201,7 +201,8 @@ cdef class EventDispatcher(object):
|
|||
self.__event_stack[key].remove(handler)
|
||||
break
|
||||
else:
|
||||
self.__properties[key].unbind(self, value)
|
||||
prop = self.__properties[key]
|
||||
prop.unbind(self, value)
|
||||
|
||||
def dispatch(self, str event_type, *largs):
|
||||
'''Dispatch an event across all the handler added in bind().
|
||||
|
@ -224,11 +225,13 @@ cdef class EventDispatcher(object):
|
|||
#
|
||||
# Properties
|
||||
#
|
||||
def __proxy_setter(self, dstinstance, name, instance, value):
|
||||
self.__properties[name].__set__(dstinstance, value)
|
||||
def __proxy_setter(self, EventDispatcher dstinstance, name, instance, value):
|
||||
cdef Property prop = self.__properties[name]
|
||||
prop.set(dstinstance, value)
|
||||
|
||||
def __proxy_getter(self, dstinstance, name, instance):
|
||||
return self.__properties[name].__get__(dstinstance)
|
||||
def __proxy_getter(self, EventDispatcher dstinstance, name, instance):
|
||||
cdef Property prop = self.__properties[name]
|
||||
return prop.get(dstinstance)
|
||||
|
||||
def setter(self, name):
|
||||
'''Return the setter of a property. Useful if you want to directly bind
|
||||
|
@ -261,7 +264,7 @@ cdef class EventDispatcher(object):
|
|||
'''
|
||||
return self.__properties[name]
|
||||
|
||||
cpdef dict properties(self):
|
||||
cpdef dict properties(EventDispatcher self):
|
||||
'''Return all the properties in that class in a dictionnary of
|
||||
key/property class. Can be used for introspection.
|
||||
|
||||
|
@ -270,7 +273,7 @@ cdef class EventDispatcher(object):
|
|||
cdef dict ret, p
|
||||
ret = {}
|
||||
p = self.__properties
|
||||
for x in self.__dict__['__storage'].keys():
|
||||
for x in self.__storage:
|
||||
ret[x] = p[x]
|
||||
return ret
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ class Animation(EventDispatcher):
|
|||
return self._transition
|
||||
|
||||
@property
|
||||
def animated_animated_properties(self):
|
||||
def animated_properties(self):
|
||||
'''Return the properties used to animate
|
||||
'''
|
||||
return self._animated_properties
|
||||
|
@ -231,7 +231,7 @@ class Animation(EventDispatcher):
|
|||
|
||||
# no more properties to animation ? kill the animation.
|
||||
if not props['properties']:
|
||||
self.stop(widget)
|
||||
self.cancel(widget)
|
||||
|
||||
#
|
||||
# Private
|
||||
|
|
|
@ -381,6 +381,7 @@ class App(EventDispatcher):
|
|||
if clsname.endswith('App'):
|
||||
clsname = clsname[:-3]
|
||||
filename = join(kv_directory, '%s.kv' % clsname.lower())
|
||||
Logger.debug('App: Loading kv <{0}>'.format(filename))
|
||||
if not exists(filename):
|
||||
Logger.debug('App: kv <%s> not found' % filename)
|
||||
return False
|
||||
|
@ -472,6 +473,7 @@ class App(EventDispatcher):
|
|||
filename = self.get_application_config()
|
||||
if filename is None:
|
||||
return config
|
||||
Logger.debug('App: Loading configuration <{0}>'.format(filename))
|
||||
if exists(filename):
|
||||
try:
|
||||
config.read(filename)
|
||||
|
@ -481,6 +483,8 @@ class App(EventDispatcher):
|
|||
self.build_config(config)
|
||||
pass
|
||||
else:
|
||||
Logger.debug('App: First configuration, create <{0}>'.format(
|
||||
filename))
|
||||
config.filename = filename
|
||||
config.write()
|
||||
return config
|
||||
|
@ -542,6 +546,10 @@ class App(EventDispatcher):
|
|||
runTouchApp()
|
||||
self.dispatch('on_stop')
|
||||
|
||||
# Clear the window children
|
||||
for child in window.children:
|
||||
window.remove_widget(child)
|
||||
|
||||
def stop(self, *largs):
|
||||
'''Stop the application.
|
||||
|
||||
|
|