commiting in case the kivy trial fails

This commit is contained in:
shockrah
2020-03-16 19:36:10 -07:00
parent 71e9d8adad
commit 40ca9a9674
424 changed files with 24252 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
from kivy.uix.accordion import Accordion, AccordionItem
from kivy.uix.label import Label
from kivy.app import App
class AccordionApp(App):
def build(self):
root = Accordion()
for x in range(5):
item = AccordionItem(title='Title %d' % x)
item.add_widget(Label(text='Very big content\n' * 10))
root.add_widget(item)
return root
if __name__ == '__main__':
AccordionApp().run()

View File

@@ -0,0 +1,32 @@
from kivy.base import runTouchApp
from kivy.lang import Builder
runTouchApp(Builder.load_string('''
ActionBar:
pos_hint: {'top':1}
ActionView:
use_separator: True
ActionPrevious:
title: 'Action Bar'
with_previous: False
ActionOverflow:
ActionButton:
icon: 'atlas://data/images/defaulttheme/audio-volume-high'
ActionButton:
important: True
text: 'Important'
ActionButton:
text: 'Btn2'
ActionButton:
text: 'Btn3'
ActionButton:
text: 'Btn4'
ActionGroup:
text: 'Group1'
ActionButton:
text: 'Btn5'
ActionButton:
text: 'Btn6'
ActionButton:
text: 'Btn7'
'''))

View File

@@ -0,0 +1,35 @@
'''
Asynchronous image loading
==========================
Test of the widget AsyncImage.
We are just putting it in a CenteredAsyncImage for being able to center the
image on screen without doing upscale like the original AsyncImage.
'''
from kivy.app import App
from kivy.uix.image import AsyncImage
from kivy.lang import Builder
Builder.load_string('''
<CenteredAsyncImage>:
size_hint: 0.8, 0.8
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
mipmap: True
''')
class CenteredAsyncImage(AsyncImage):
pass
class TestAsyncApp(App):
def build(self):
url = ('https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/'
'STS-116_spacewalk_1.jpg/1024px-STS-116_spacewalk_1.jpg')
return CenteredAsyncImage(source=url)
if __name__ == '__main__':
TestAsyncApp().run()

View File

@@ -0,0 +1,54 @@
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()

View File

@@ -0,0 +1,59 @@
'''
Bubble
======
Test of the widget Bubble.
'''
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.lang import Builder
from kivy.uix.bubble import Bubble
Builder.load_string('''
<cut_copy_paste>
size_hint: (None, None)
size: (160, 120)
pos_hint: {'center_x': .5, 'y': .6}
BubbleButton:
text: 'Cut'
BubbleButton:
text: 'Copy'
BubbleButton:
text: 'Paste'
''')
class cut_copy_paste(Bubble):
pass
class BubbleShowcase(FloatLayout):
def __init__(self, **kwargs):
super(BubbleShowcase, self).__init__(**kwargs)
self.but_bubble = Button(text='Press to show bubble')
self.but_bubble.bind(on_release=self.show_bubble)
self.add_widget(self.but_bubble)
def show_bubble(self, *l):
if not hasattr(self, 'bubb'):
self.bubb = bubb = cut_copy_paste()
self.add_widget(bubb)
else:
values = ('left_top', 'left_mid', 'left_bottom', 'top_left',
'top_mid', 'top_right', 'right_top', 'right_mid',
'right_bottom', 'bottom_left', 'bottom_mid', 'bottom_right')
index = values.index(self.bubb.arrow_pos)
self.bubb.arrow_pos = values[(index + 1) % len(values)]
class TestBubbleApp(App):
def build(self):
return BubbleShowcase()
if __name__ == '__main__':
TestBubbleApp().run()

View File

@@ -0,0 +1,33 @@
from kivy.app import App
from kivy.lang import Builder
kv = '''
BoxLayout:
orientation: 'vertical'
Camera:
id: camera
resolution: 399, 299
BoxLayout:
orientation: 'horizontal'
size_hint_y: None
height: '48dp'
Button:
text: 'Start'
on_release: camera.play = True
Button:
text: 'Stop'
on_release: camera.play = False
'''
class CameraApp(App):
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
CameraApp().run()

View File

@@ -0,0 +1,50 @@
'''
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
text: 'load(page 3)'
on_release:
carousel = root.parent.parent
carousel.load_slide(carousel.slides[2])
Button
Button
text: 'prev'
on_release:
root.parent.parent.load_previous()
Button
Button
text: 'next'
on_release:
root.parent.parent.load_next()
''')
class Page(GridLayout):
pass
class TestApp(App):
def build(self):
root = Carousel()
for x in range(10):
root.add_widget(Page())
return root
if __name__ == '__main__':
TestApp().run()

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 KiB

View File

@@ -0,0 +1,225 @@
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.behaviors import EmacsBehavior
from kivy.uix.popup import Popup
from kivy.properties import ListProperty
from kivy.core.window import Window
from kivy.core.text import LabelBase
from pygments import lexers
import codecs
import 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>
----------------------Emacs key bindings---------------------
This CodeInput inherits from EmacsBehavior, so you can use Emacs key bindings
if you want! To try out Emacs key bindings, set the "Key bindings" option to
"Emacs". Experiment with the shortcuts below on some of the text in this window
(just be careful not to delete the cheat sheet before you have made note of the
commands!)
Shortcut Description
-------- -----------
Control + a Move cursor to the beginning of the line
Control + e Move cursor to the end of the line
Control + f Move cursor one character to the right
Control + b Move cursor one character to the left
Alt + f Move cursor to the end of the word to the right
Alt + b Move cursor to the start of the word to the left
Alt + Backspace Delete text left of the cursor to the beginning of word
Alt + d Delete text right of the cursor to the end of the word
Alt + w Copy selection
Control + w Cut selection
Control + y Paste selection
'''
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 CodeInputWithBindings(EmacsBehavior, CodeInput):
'''CodeInput with keybindings.
To add more bindings, add the behavior before CodeInput in the class
definition.
'''
pass
class CodeInputTest(App):
files = ListProperty([None, ])
def build(self):
b = BoxLayout(orientation='vertical')
languages = Spinner(
text='language',
values=sorted(['KvLexer', ] + list(lexers.LEXERS.keys())))
languages.bind(text=self.change_lang)
menu = BoxLayout(
size_hint_y=None,
height='30pt')
fnt_size = Spinner(
text='12',
values=list(map(str, list(range(5, 40)))))
fnt_size.bind(text=self._update_size)
fonts = [
file for file in LabelBase._font_dirs_files
if file.endswith('.ttf')]
fnt_name = Spinner(
text='RobotoMono',
option_cls=Fnt_SpinnerOption,
values=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)
key_bindings = Spinner(
text='Key bindings',
values=('Default key bindings', 'Emacs key bindings'))
key_bindings.bind(text=self._bindings_selected)
menu.add_widget(mnu_file)
menu.add_widget(fnt_size)
menu.add_widget(fnt_name)
menu.add_widget(languages)
menu.add_widget(key_bindings)
b.add_widget(menu)
self.codeinput = CodeInputWithBindings(
lexer=KivyLexer(),
font_size=12,
text=example_text,
key_bindings='default',
)
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 = 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 _bindings_selected(self, instance, value):
value = value.split(' ')[0]
self.codeinput.key_bindings = value.lower()
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, z):
if z == 'KvLexer':
lx = KivyLexer()
else:
lx = lexers.get_lexer_by_name(lexers.LEXERS[z][2][0])
self.codeinput.lexer = lx
if __name__ == '__main__':
CodeInputTest().run()

View File

@@ -0,0 +1,53 @@
#:import os os
<Fnt_SpinnerOption>:
font_name: self.text
<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)

View File

@@ -0,0 +1,234 @@
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scatter import Scatter
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty, StringProperty
from kivy.graphics import Color, Point
from math import sqrt
from os import walk
from os.path import dirname, join
from kivy.lang import Builder
Builder.load_string('''
#:import os os
<Picture>:
# each time a picture is created, the image can delay the loading
# as soon as the image is loaded, ensure that the center is changed
# to the center of the screen.
on_size: self.center = app.main_root_widget.center
size: img.size
size_hint: None, None
on_touch_down: if self.collide_point(*args[1].pos): app.current_image = img
Image:
id: img
source: root.source
# create initial image to be 400 pixels width
size: 400, 400 / self.image_ratio
# add shadow background
canvas.before:
Color:
rgba: 1, 1, 1, 1
BorderImage:
source: '../demo/pictures/shadow32.png'
border: (36, 36, 36, 36)
size:(self.width + 72, self.height + 72)
pos: (-36, -36)
<ColorSelector>:
color: 1, 1, 1, 1
title: 'Color Slector'
content:content
BoxLayout:
id: content
orientation: 'vertical'
ColorPicker:
id: clr_picker
color: root.color
BoxLayout:
size_hint_y: None
height: '27sp'
Button:
text: 'ok'
on_release:
root.color = clr_picker.color
root.dismiss()
Button:
text: 'cancel'
on_release: root.dismiss()
<LeftPanel@BoxLayout>
orientation: 'vertical'
padding: '2pt'
canvas.before:
Color:
rgba: .5, .4, .9, .2
Rectangle:
pos: self.pos
size: self.size
Label:
size_hint_y: None
font_size: '18sp'
text_size: self.width, None
valign: 'middle'
halign: 'center'
height: self.texture.size[1] if self.texture else 10
text:
("Selected Image:\\n" + app.current_image.source.split(os.sep)[-1]
if app.current_image else 'None')
Button:
text: 'Brush'
size_hint_y: None
height: self.parent.width
on_release:
app.color_selector.open()
app.color_mode = 'brush'
Image:
color: app.color_selector.color
source: '../demo/touchtracer/particle.png'
allow_stretch: True
size: self.parent.size
pos: self.parent.pos
Button:
text: 'cursor'
on_release: app.color_mode = 'cursor'
Button:
text: 'clear'
on_release:
app.handle_clear()
<MainRootWidget>
current_image: None
client_area: client_area
RelativeLayout:
id: client_area
Splitter:
sizable_from: 'left'
size_hint: None, 1
width: '99dp'
LeftPanel:
''')
def calculate_points(x1, y1, x2, y2, steps=5):
dx = x2 - x1
dy = y2 - y1
dist = sqrt(dx * dx + dy * dy)
if dist < steps:
return
o = []
m = dist / steps
for i in range(1, int(m)):
mi = i / m
lastx = x1 + dx * mi
lasty = y1 + dy * mi
o.extend([lastx, lasty])
return o
class ColorSelector(Popup):
pass
class Picture(Scatter):
source = StringProperty(None)
'''path to the Image to be loaded
'''
def __init__(self, **kwargs):
super(Picture, self).__init__(**kwargs)
self._app = App.get_running_app()
def on_touch_down(self, touch):
_app = self._app
if (_app.color_mode[0] == 'c' or
not self.collide_point(*touch.pos)):
return super(Picture, self).on_touch_down(touch)
ud = touch.ud
ud['group'] = g = str(touch.uid)
_pos = list(self.ids.img.to_widget(*touch.pos))
_pos[0] += self.parent.x
with self.ids.img.canvas.after:
ud['color'] = Color(*_app.color_selector.color, group=g)
ud['lines'] = Point(points=(_pos),
source='../demo/touchtracer/particle.png',
pointsize=5, group=g)
touch.grab(self)
return True
def on_touch_move(self, touch):
if touch.grab_current is not self:
return
_app = self._app
if _app.color_mode[0] == 'c' or not self.collide_point(*touch.pos):
return super(Picture, self).on_touch_move(touch)
ud = touch.ud
_pos = list(self.ids.img.to_widget(*touch.pos))
_pos[0] += self.parent.x
points = ud['lines'].points
oldx, oldy = points[-2], points[-1]
points = calculate_points(oldx, oldy, _pos[0], _pos[1])
if points:
try:
lp = ud['lines'].add_point
for idx in range(0, len(points), 2):
lp(points[idx], points[idx + 1])
except GraphicException:
pass
def on_touch_up(self, touch):
if touch.grab_current is not self:
return
_app = self._app
if _app.color_mode[0] == 'c':
return super(Picture, self).on_touch_up(touch)
touch.ungrab(self)
ud = touch.ud
self.canvas.remove_group(ud['group'])
class MainRootWidget(BoxLayout):
clent_area = ObjectProperty(None)
# The Client Area in which all editing is Done
def on_parent(self, instance, parent):
if parent:
_dir = join(dirname(__file__), 'lists/fruit_images/')
for image in list(walk(_dir))[0][2]:
if image.find('512') > -1:
self.client_area.add_widget(Picture(source=_dir + image))
class MainApp(App):
main_root_widget = ObjectProperty(None)
# we will be accessing this later as App.main_root_widget
current_image = ObjectProperty(None)
'''This is a handle to the currently selected image on which the effects
would be applied.'''
color_mode = StringProperty('cursor')
'''This defines the current mode `brush` or `cursor`. `brush` mode allows
adding brush strokes to the currently selected Image.
'''
def build(self):
self.color_selector = ColorSelector()
self.main_root_widget = MainRootWidget()
return self.main_root_widget
def handle_clear(self):
if self.current_image:
self.current_image.canvas.after.clear()
if __name__ == '__main__':
MainApp().run()

View File

@@ -0,0 +1,62 @@
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.lang import Builder
Builder.load_string("""
#:import hex kivy.utils.get_color_from_hex
<Root>:
cols: 2
canvas:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
Label:
canvas.before:
Color:
rgb: 39/255., 174/255., 96/255.
Rectangle:
pos: self.pos
size: self.size
text: "rgb: 39/255., 174/255., 96/255."
Label:
canvas.before:
Color:
rgba: 39/255., 174/255., 96/255., 1
Rectangle:
pos: self.pos
size: self.size
text: "rgba: 39/255., 174/255., 96/255., 1"
Label:
canvas.before:
Color:
hsv: 145/360., 77.6/100, 68.2/100
Rectangle:
pos: self.pos
size: self.size
text: "hsv: 145/360., 77.6/100, 68.2/100"
Label:
canvas.before:
Color:
rgba: hex('#27ae60')
Rectangle:
pos: self.pos
size: self.size
text: "rgba: hex('#27ae60')"
""")
class Root(GridLayout):
pass
class ColorusageApp(App):
def build(self):
return Root()
if __name__ == "__main__":
ColorusageApp().run()

View File

@@ -0,0 +1,83 @@
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.behaviors import CompoundSelectionBehavior
from kivy.uix.behaviors import FocusBehavior
from kivy.app import runTouchApp
class SelectableGrid(FocusBehavior, CompoundSelectionBehavior, GridLayout):
def __init__(self, **kwargs):
super(SelectableGrid, self).__init__(**kwargs)
def print_selection(*l):
print('selected: ', [x.text for x in self.selected_nodes])
self.bind(selected_nodes=print_selection)
def keyboard_on_key_down(self, window, keycode, text, modifiers):
if super(SelectableGrid, self).keyboard_on_key_down(
window, keycode, text, modifiers):
return True
if self.select_with_key_down(window, keycode, text, modifiers):
return True
return False
def keyboard_on_key_up(self, window, keycode):
if super(SelectableGrid, self).keyboard_on_key_up(window, keycode):
return True
if self.select_with_key_up(window, keycode):
return True
return False
def goto_node(self, key, last_node, last_node_idx):
''' This function is used to go to the node by typing the number
of the text of the button.
'''
node, idx = super(SelectableGrid, self).goto_node(key, last_node,
last_node_idx)
if node != last_node:
return node, idx
items = list(enumerate(self.get_selectable_nodes()))
'''If self.nodes_order_reversed (the default due to using
self.children which is reversed), the index is counted from the
starts of the selectable nodes, like normal but the nodes are traversed
in the reverse order.
'''
# start searching after the last selected node
if not self.nodes_order_reversed:
items = items[last_node_idx + 1:] + items[:last_node_idx + 1]
else:
items = items[:last_node_idx][::-1] + items[last_node_idx:][::-1]
for i, child in items:
if child.text.startswith(key):
return child, i
return node, idx
def select_node(self, node):
node.background_color = (1, 0, 0, 1)
return super(SelectableGrid, self).select_node(node)
def deselect_node(self, node):
node.background_color = (1, 1, 1, 1)
super(SelectableGrid, self).deselect_node(node)
def do_touch(self, instance, touch):
if ('button' in touch.profile and touch.button in
('scrollup', 'scrolldown', 'scrollleft', 'scrollright')) or\
instance.collide_point(*touch.pos):
self.select_with_touch(instance, touch)
else:
return False
return True
root = SelectableGrid(cols=5, up_count=5, multiselect=True, scroll_count=1)
for i in range(40):
c = Button(text=str(i))
c.bind(on_touch_down=root.do_touch)
root.add_widget(c)
runTouchApp(root)

View File

@@ -0,0 +1,82 @@
'''
Custom shape & collide widget
=============================
This is a Triangle widget with a triangle shape based on 3 points (p1, p2, p3),
plus a custom collision function.
The p1, p2, p3 are automatically calculated from the position and the size of
the Widget bounding box. We are using them to draw the triangle shape.
(Please note in the kv the special case for Scatter.)
Then we need to setup a new collision function to collide only on the triangle.
We are using a external method that will check if a point is inside a polygon
(we consider our triangle as a polygon).
'''
import kivy
kivy.require('1.0.8')
from kivy.uix.scatter import Scatter
from kivy.properties import ListProperty
from kivy.lang import Builder
Builder.load_string('''
<Triangle>:
# example for doing a triangle
# this will automatically recalculate pX from pos/size
p1: 0, 0
p2: self.width, 0
p3: self.width / 2, self.height
# If you use a Widget instead of Scatter as base class, you need that:
#p1: self.pos
#p2: self.right, self.y
#p3: self.center_x, self.top
# draw something
canvas:
Color:
rgb: 1, 0, 0
Triangle:
points: self.p1 + self.p2 + self.p3
''')
def point_inside_polygon(x, y, poly):
'''Taken from http://www.ariel.com.au/a/python-point-int-poly.html
'''
n = len(poly)
inside = False
p1x = poly[0]
p1y = poly[1]
for i in range(0, n + 2, 2):
p2x = poly[i % n]
p2y = poly[(i + 1) % n]
if y > min(p1y, p2y):
if y <= max(p1y, p2y):
if x <= max(p1x, p2x):
if p1y != p2y:
xinters = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
if p1x == p2x or x <= xinters:
inside = not inside
p1x, p1y = p2x, p2y
return inside
class Triangle(Scatter):
p1 = ListProperty([0, 0])
p2 = ListProperty([0, 0])
p3 = ListProperty([0, 0])
def collide_point(self, x, y):
x, y = self.to_local(x, y)
return point_inside_polygon(x, y,
self.p1 + self.p2 + self.p3)
if __name__ == '__main__':
from kivy.base import runTouchApp
runTouchApp(Triangle(size_hint=(None, None)))

View File

@@ -0,0 +1,200 @@
'''
Example usage of the effectwidget.
Currently highly experimental.
'''
from kivy.app import App
from kivy.uix.effectwidget import EffectWidget
from kivy.uix.spinner import Spinner
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.effectwidget import (MonochromeEffect,
InvertEffect,
ScanlinesEffect,
ChannelMixEffect,
ScanlinesEffect,
FXAAEffect,
PixelateEffect,
HorizontalBlurEffect,
VerticalBlurEffect)
class ComparisonWidget(EffectWidget):
pass
class ComparisonWidget(EffectWidget):
pass
class EffectSpinner(Spinner):
pass
class SpinnerRow(BoxLayout):
effectwidget = ObjectProperty()
def update_effectwidget(self, *args):
effects = []
for child in self.children[::-1]:
text = child.text
if text == 'none':
pass
if text == 'fxaa':
effects.append(FXAAEffect())
if text == 'monochrome':
effects.append(MonochromeEffect())
if text == 'invert':
effects.append(InvertEffect())
if text == 'mix':
effects.append(ChannelMixEffect())
if text == 'flash':
effects.append(FlashEffect())
if text == 'blur_h':
effects.append(HorizontalBlurEffect())
if text == 'blur_v':
effects.append(VerticalBlurEffect())
if text == 'postprocessing':
effects.append(ScanlinesEffect())
if text == 'pixelate':
effects.append(PixelateEffect())
if self.effectwidget:
self.effectwidget.effects = effects
example = Builder.load_string('''
#:import Vector kivy.vector.Vector
BoxLayout:
orientation: 'vertical'
FloatLayout:
ComparisonWidget:
pos_hint: {'x': 0, 'y': 0}
size_hint: 0.5, 1
id: effect1
ComparisonWidget:
pos_hint: {'x': pos_slider.value, 'y': 0}
size_hint: 0.5, 1
id: effect2
background_color: (rs.value, gs.value, bs.value, als.value)
SpinnerRow:
effectwidget: effect1
text: 'left effects'
SpinnerRow:
effectwidget: effect2
text: 'right effects'
BoxLayout:
size_hint_y: None
height: sp(40)
Label:
text: 'control overlap:'
Slider:
min: 0
max: 0.5
value: 0.5
id: pos_slider
BoxLayout:
size_hint_y: None
height: sp(40)
Label:
text: 'right bg r,g,b,a'
Slider:
min: 0
max: 1
value: 0
id: rs
Slider:
min: 0
max: 1
value: 0
id: gs
Slider:
min: 0
max: 1
value: 0
id: bs
Slider:
min: 0
max: 1
value: 0
id: als
<ComparisonWidget>:
Widget:
canvas:
Color:
rgba: 1, 0, 0, 1
Ellipse:
pos: Vector(self.pos) + 0.5*Vector(self.size)
size: 0.4*Vector(self.size)
Color:
rgba: 0, 1, 0.3, 1
Ellipse:
pos: Vector(self.pos) + 0.1*Vector(self.size)
size: 0.6*Vector(self.size)
Color:
rgba: 0.5, 0.3, 0.8, 1
Ellipse:
pos: Vector(self.pos) + Vector([0, 0.6])*Vector(self.size)
size: 0.4*Vector(self.size)
Color:
rgba: 1, 0.8, 0.1, 1
Ellipse:
pos: Vector(self.pos) + Vector([0.5, 0])*Vector(self.size)
size: 0.4*Vector(self.size)
Color:
rgba: 0, 0, 0.8, 1
Line:
points:
[self.x, self.y,
self.x + self.width, self.y + 0.3*self.height,
self.x + 0.2*self.width, self.y + 0.1*self.height,
self.x + 0.85*self.width, self.y + 0.72*self.height,
self.x + 0.31*self.width, self.y + 0.6*self.height,
self.x, self.top]
width: 1
Color:
rgba: 0, 0.9, 0.1, 1
Line:
points:
[self.x + self.width, self.y + self.height,
self.x + 0.35*self.width, self.y + 0.6*self.height,
self.x + 0.7*self.width, self.y + 0.15*self.height,
self.x + 0.2*self.width, self.y + 0.22*self.height,
self.x + 0.3*self.width, self.y + 0.92*self.height]
width: 2
<SpinnerRow>:
orientation: 'horizontal'
size_hint_y: None
height: dp(40)
text: ''
Label:
text: root.text
EffectSpinner:
on_text: root.update_effectwidget()
EffectSpinner:
on_text: root.update_effectwidget()
EffectSpinner:
on_text: root.update_effectwidget()
<EffectSpinner>:
text: 'none'
values:
['none', 'fxaa', 'monochrome',
'invert', 'mix',
'blur_h', 'blur_v',
'postprocessing', 'pixelate',]
''')
class EffectApp(App):
def build(self):
return example
EffectApp().run()

View File

@@ -0,0 +1,47 @@
'''
This is an example of creating your own effect by writing a glsl string.
'''
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.effectwidget import EffectWidget, EffectBase
# The effect string is glsl code defining an effect function.
effect_string = '''
vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords)
{
// Note that time is a uniform variable that is automatically
// provided to all effects.
float red = color.x * abs(sin(time*2.0));
float green = color.y; // No change
float blue = color.z * (1.0 - abs(sin(time*2.0)));
return vec4(red, green, blue, color.w);
}
'''
class DemoEffect(EffectWidget):
def __init__(self, *args, **kwargs):
self.effect_reference = EffectBase(glsl=effect_string)
super(DemoEffect, self).__init__(*args, **kwargs)
widget = Builder.load_string('''
DemoEffect:
effects: [self.effect_reference] if checkbox.active else []
orientation: 'vertical'
Button:
text: 'Some text so you can see what happens.'
BoxLayout:
size_hint_y: None
height: dp(50)
Label:
text: 'Enable effect?'
CheckBox:
id: checkbox
active: True
''')
runTouchApp(widget)

View File

@@ -0,0 +1,63 @@
'''
This example demonstrates creating and usind an AdvancedEffectBase. In
this case, we use it to efficiently pass the touch coordinates into the shader.
'''
from kivy.base import runTouchApp
from kivy.properties import ListProperty
from kivy.lang import Builder
from kivy.uix.effectwidget import EffectWidget, AdvancedEffectBase
effect_string = '''
uniform vec2 touch;
vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords)
{
vec2 distance = 0.025*(coords - touch);
float dist_mag = (distance.x*distance.x + distance.y*distance.y);
vec3 multiplier = vec3(abs(sin(dist_mag - time)));
return vec4(multiplier * color.xyz, 1.0);
}
'''
class TouchEffect(AdvancedEffectBase):
touch = ListProperty([0.0, 0.0])
def __init__(self, *args, **kwargs):
super(TouchEffect, self).__init__(*args, **kwargs)
self.glsl = effect_string
self.uniforms = {'touch': [0.0, 0.0]}
def on_touch(self, *args, **kwargs):
self.uniforms['touch'] = [float(i) for i in self.touch]
class TouchWidget(EffectWidget):
def __init__(self, *args, **kwargs):
super(TouchWidget, self).__init__(*args, **kwargs)
self.effect = TouchEffect()
self.effects = [self.effect]
def on_touch_down(self, touch):
super(TouchWidget, self).on_touch_down(touch)
self.on_touch_move(touch)
def on_touch_move(self, touch):
self.effect.touch = touch.pos
root = Builder.load_string('''
TouchWidget:
Button:
text: 'Some text!'
Image:
source: 'data/logo/kivy-icon-512.png'
allow_stretch: True
keep_ratio: False
''')
runTouchApp(root)

View File

@@ -0,0 +1,111 @@
'''
FBO example
===========
This is an example of how to use FBO (Frame Buffer Object) to speedup graphics.
An Fbo is like a texture that you can draw on it.
By default, all the children are added in the canvas of the parent.
When you are displaying thousand of widget, you'll do thousands of graphics
instructions each frame.
The idea is to do this drawing only one time in a Fbo, and then, draw the Fbo
every frame instead of all children's graphics instructions.
We created a FboFloatLayout that create his canvas, and a Fbo.
After the Fbo is created, we are adding Color and Rectangle instruction to
display the texture of the Fbo itself.
The overload of on_pos/on_size are here to update size of Fbo if needed, and
adapt the position/size of the rectangle too.
Then, when a child is added or removed, we are redirecting addition/removal of
graphics instruction to our Fbo. This is why add_widget/remove_widget are
overloaded too.
.. note::
This solution can be helpful but not ideal. Multisampling are not available
in Framebuffer. We will work to add the support of it if the hardware is
capable of, but it could be not the same.
'''
# needed to create Fbo, must be resolved in future kivy version
from kivy.core.window import Window
from kivy.graphics import Color, Rectangle, Canvas
from kivy.graphics.fbo import Fbo
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty
class FboFloatLayout(FloatLayout):
texture = ObjectProperty(None, allownone=True)
def __init__(self, **kwargs):
self.canvas = Canvas()
with self.canvas:
self.fbo = Fbo(size=self.size)
Color(1, 1, 1)
self.fbo_rect = Rectangle()
# wait that all the instructions are in the canvas to set texture
self.texture = self.fbo.texture
super(FboFloatLayout, self).__init__(**kwargs)
def add_widget(self, *largs):
# trick to attach graphics instruction to fbo instead of canvas
canvas = self.canvas
self.canvas = self.fbo
ret = super(FboFloatLayout, self).add_widget(*largs)
self.canvas = canvas
return ret
def remove_widget(self, *largs):
canvas = self.canvas
self.canvas = self.fbo
super(FboFloatLayout, self).remove_widget(*largs)
self.canvas = canvas
def on_size(self, instance, value):
self.fbo.size = value
self.texture = self.fbo.texture
self.fbo_rect.size = value
def on_pos(self, instance, value):
self.fbo_rect.pos = value
def on_texture(self, instance, value):
self.fbo_rect.texture = value
if __name__ == '__main__':
from kivy.uix.button import Button
from kivy.app import App
class TestFboApp(App):
def build(self):
# test with FboFloatLayout or FloatLayout
# comment/uncomment to test it
root = FboFloatLayout()
# root = FloatLayout()
# this part of creation can be slow. try to optimize the loop a
# little bit.
s = 30
size = (s, s)
sh = (None, None)
add = root.add_widget
print('Creating 5000 widgets...')
for i in range(5000):
x = (i % 40) * s
y = int(i / 40) * s
add(Button(text=str(i), pos=(x, y), size_hint=sh, size=size))
if i % 1000 == 1000 - 1:
print(5000 - i - 1, 'left...')
return root
TestFboApp().run()

View File

@@ -0,0 +1,98 @@
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.behaviors import FocusBehavior
from kivy.graphics import Color, Rectangle
class FocusWithColor(FocusBehavior):
''' Class that when focused, changes its background color to red.
'''
_color = None
_rect = None
def __init__(self, **kwargs):
super(FocusWithColor, self).__init__(**kwargs)
with self.canvas:
self._color = Color(1, 1, 1, .2)
self._rect = Rectangle(size=self.size, pos=self.pos)
self.bind(size=self._update_rect, pos=self._update_rect)
def _update_rect(self, instance, value):
self._rect.pos = instance.pos
self._rect.size = instance.size
def on_focused(self, instance, value, *largs):
self._color.rgba = [1, 0, 0, .2] if value else [1, 1, 1, .2]
class FocusLabel(FocusWithColor, Label):
'''A label, which in addition to turn red when focused, it also sets the
keyboard input to the text of the label.
'''
def keyboard_on_key_down(self, window, keycode, text, modifiers):
'''We call super before doing anything else to enable tab cycling
by FocusBehavior. If we wanted to use tab for ourselves, we could just
not call it, or call it if we didn't need tab.
'''
if super(FocusLabel, self).keyboard_on_key_down(window, keycode,
text, modifiers):
return True
self.text = keycode[1]
return True
class FocusGridLayout(FocusWithColor, GridLayout):
pass
class FocusBoxLayout(FocusWithColor, BoxLayout):
pass
class FocusApp(App):
def build(self):
root = FocusBoxLayout(padding=[10, 10], spacing=10)
self.grid1 = grid1 = FocusGridLayout(cols=4, padding=[10, 10],
spacing=10)
self.grid2 = grid2 = FocusGridLayout(cols=4, padding=[10, 10],
spacing=10)
root.add_widget(FocusLabel(text='Left', size_hint_x=0.4))
root.add_widget(grid1)
root.add_widget(grid2)
root.add_widget(FocusLabel(text='Right', size_hint_x=0.4))
for i in range(40):
grid1.add_widget(FocusLabel(text='l' + str(i)))
for i in range(40):
grid2.add_widget(FocusLabel(text='r' + str(i)))
# make elements 29, 9 un-focusable. The widgets are displayed in
# reverse order, so 9 = 39 - 10
grid2.children[30].text = grid1.children[14].text =\
grid2.children[15].text = grid1.children[34].text = 'Skip me'
grid2.children[15].is_focusable = False
grid2.children[30].is_focusable = False
# similarly, make 39 - 14 = 25, and 5 un-focusable
grid1.children[14].is_focusable = False
grid1.children[34].is_focusable = False
# don't move focus passed this element
grid2.children[35].focus_next = StopIteration
grid2.children[35].text = 'Stop forward'
# exchange the links between the sides so that it'll skip to the other
# side in the middle. Remember that children are displayed reversed
# in layouts.
grid1.children[10].focus_next = grid2.children[9]
grid2.children[10].focus_next = grid1.children[9]
grid1.children[10].text = '-->'
grid2.children[10].text = '<--'
return root
if __name__ == '__main__':
FocusApp().run()

View File

@@ -0,0 +1,31 @@
'''
Image mipmap
============
Difference between a mipmapped image and no mipmap image.
The lower image is normal, and the top image is mipmapped.
'''
import kivy
kivy.require('1.0.7')
from kivy.app import App
from kivy.uix.scatter import ScatterPlane
from kivy.uix.image import Image
from os.path import join
class LabelMipmapTest(App):
def build(self):
s = ScatterPlane(scale=.5)
filename = join(kivy.kivy_data_dir, 'logo', 'kivy-icon-256.png')
l1 = Image(source=filename, pos=(400, 100), size=(256, 256))
l2 = Image(source=filename, pos=(400, 356), size=(256, 256),
mipmap=True)
s.add_widget(l1)
s.add_widget(l2)
return s
if __name__ == '__main__':
LabelMipmapTest().run()

View File

@@ -0,0 +1,42 @@
import kivy
kivy.require('1.0.8')
from kivy.core.window import Window
from kivy.uix.widget import Widget
class MyKeyboardListener(Widget):
def __init__(self, **kwargs):
super(MyKeyboardListener, self).__init__(**kwargs)
self._keyboard = Window.request_keyboard(
self._keyboard_closed, self, 'text')
if self._keyboard.widget:
# If it exists, this widget is a VKeyboard object which you can use
# to change the keyboard layout.
pass
self._keyboard.bind(on_key_down=self._on_keyboard_down)
def _keyboard_closed(self):
print('My keyboard have been closed!')
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
self._keyboard = None
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
print('The key', keycode, 'have been pressed')
print(' - text is %r' % text)
print(' - modifiers are %r' % modifiers)
# Keycode is composed of an integer + a string
# If we hit escape, release the keyboard
if keycode[1] == 'escape':
keyboard.release()
# Return True to accept the key. Otherwise, it will be used by
# the system.
return True
if __name__ == '__main__':
from kivy.base import runTouchApp
runTouchApp(MyKeyboardListener())

View File

@@ -0,0 +1,28 @@
'''
Label mipmap
============
This show how to create a mipmapped label, and the visual difference between a
non mipmapped and mipmapped label.
'''
import kivy
kivy.require('1.0.7')
from kivy.app import App
from kivy.uix.scatter import ScatterPlane
from kivy.uix.label import Label
class LabelMipmapTest(App):
def build(self):
s = ScatterPlane(scale=.5)
l1 = Label(text='Kivy rulz', font_size=98, pos=(400, 100), mipmap=True)
l2 = Label(text='Kivy rulz', font_size=98, pos=(400, 328))
s.add_widget(l1)
s.add_widget(l2)
return s
if __name__ == '__main__':
LabelMipmapTest().run()

View File

@@ -0,0 +1,193 @@
"""
Label textsize
============
This example shows how to size a Label to its content (texture_size) and how
setting text_size controls text wrapping.
"""
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.properties import StringProperty, NumericProperty, BooleanProperty
# Copied from https://en.wikipedia.org/wiki/A_Tale_of_Two_Cities
# Published in 1859 and public domain.
# The newline after the title will help demonstrate halign
_example_title_text = 'A Tale of Two Cities, by Charles Dickens\n'
_example_text = """It was the best of times, it was the worst of times,
it was the age of wisdom, it was the age of foolishness, it was the epoch of
belief, it was the epoch of incredulity, it was the season of Light, it was
the season of Darkness, it was the spring of hope, it was the winter of
despair, we had everything before us, we had nothing before us, we were all
going direct to Heaven, we were all going direct the other way - in short,
the period was so far like the present period, that some of its noisiest
authorities insisted on its being received, for good or for evil, in the
superlative degree of comparison only.
"""
# Note: Many of the Widgets (StackLayout, ToggleButton, Spinner) have
# defaults set at the bottom of the KV, where DemoLabel and HeadingLabel
# are also defined.
_kv_code = """
BoxLayout:
orientation: 'vertical'
HeadingLabel:
text: 'These modify all demonstration Labels'
StackLayout:
# Button is a subclass of Label and can be sized
# to text in the same way
Button:
text: 'Reset'
on_press: app.reset_words()
ToggleButton:
text: 'Shorten'
on_state:
app.shorten=self.state=='down'
ToggleButton:
text: 'max_lines=3'
on_state:
app.max_lines=3 if self.state=='down' else 0
Spinner:
text: 'bottom'
values: 'bottom', 'middle', 'top'
on_text: app.valign=self.text
Spinner:
text: 'left'
values: 'left', 'center', 'right', 'justify'
on_text: app.halign=self.text
GridLayout:
id: grid_layout
cols: 2
height: cm(6)
size_hint_y: None
HeadingLabel:
text: "Default, no text_size set"
HeadingLabel:
text: 'text_size bound to size'
DemoLabel:
id: left_content
disabled_color: 0, 0, 0, 0
DemoLabel:
id: right_content
text_size: self.size
padding: dp(6), dp(6)
ToggleButton:
text: 'Disable left'
on_state:
left_content.disabled=self.state=='down'
# Need one Widget without size_hint_y: None, so that BoxLayout fills
# available space.
HeadingLabel:
text: 'text_size width set, size bound to texture_size'
text_size: self.size
size_hint_y: 1
DemoLabel:
id: bottom_content
# This Label wraps and expands its height to fit the text because
# only text_size width is set and the Label size binds to texture_size.
text_size: self.width, None
size: self.texture_size
padding: mm(4), mm(4)
size_hint_y: None
# The column heading labels have their width set by the parent,
# but determine their height from the text.
<HeadingLabel@Label>:
bold: True
padding: dp(6), dp(4)
valign: 'bottom'
height: self.texture_size[1]
text_size: self.width, None
size_hint_y: None
<ToggleButton,Button>:
padding: dp(10), dp(8)
size_hint: None, None
size: self.texture_size
# This inherits Button and the modifications above, so reset size
<Spinner>:
size: sp(68), self.texture_size[1]
<DemoLabel@Label>:
halign: app.halign
valign: app.valign
shorten: app.shorten
max_lines: app.max_lines
canvas:
Color:
rgb: 68/255.0, 164/255.0, 201/255.0
Line:
rectangle: self.x, self.y, self.width, self.height
<StackLayout>:
size_hint_y: None
spacing: dp(6)
padding: dp(6), dp(4)
height: self.minimum_height
"""
class LabelTextureSizeExample(App):
# All Labels use these properties, set to Label defaults
valign = StringProperty('bottom')
halign = StringProperty('left')
shorten = BooleanProperty(False)
max_lines = NumericProperty(0)
def build(self):
self._add_word_ev = None
return Builder.load_string(_kv_code)
def on_start(self):
widget_ids = self.root.ids
self.text_content_widgets = (widget_ids.left_content,
widget_ids.right_content,
widget_ids.bottom_content)
self.reset_words()
def reset_words(self):
if self._add_word_ev is not None:
self._add_word_ev.cancel()
self._add_word_ev = None
for content_widget in self.text_content_widgets:
content_widget.text = _example_title_text
# initialize words generator
self.words = (word for word in _example_text.split())
self.add_word()
def add_word(self, dt=None):
try:
word = next(self.words)
except StopIteration:
return
for content_widget in self.text_content_widgets:
content_widget.text += word + ' '
pause_time = 0.03 * len(word)
if word.endswith(','):
pause_time += 0.6
self._add_word_ev = Clock.schedule_once(self.add_word, pause_time)
if __name__ == '__main__':
LabelTextureSizeExample().run()

View File

@@ -0,0 +1,49 @@
'''
Label textsize
============
This example shows how the textsize and line_height property are used
to format label widget
'''
import kivy
kivy.require('1.0.7')
from kivy.app import App
from kivy.uix.label import Label
_long_text = ("""Lorem ipsum dolor sit amet, consectetur adipiscing elit. """
"""Phasellus odio nisi, pellentesque molestie adipiscing vitae, aliquam """
"""at tellus. Fusce quis est ornare erat pulvinar elementum ut sed """
"""felis. Donec vel neque mauris. In sit amet nunc sit amet diam dapibus"""
""" lacinia. In sodales placerat mauris, ut euismod augue laoreet at. """
"""Integer in neque non odio fermentum volutpat nec nec nulla. Donec et """
"""risus non mi viverra posuere. Phasellus cursus augue purus, eget """
"""volutpat leo. Phasellus sed dui vitae ipsum mattis facilisis vehicula"""
""" eu justo.\n\n"""
"""Quisque neque dolor, egestas sed venenatis eget, porta id ipsum. Ut """
"""faucibus, massa vitae imperdiet rutrum, sem dolor rhoncus magna, non """
"""lacinia nulla risus non dui. Nulla sit amet risus orci. Nunc libero """
"""justo, interdum eu pulvinar vel, pulvinar et lectus. Phasellus sed """
"""luctus diam. Pellentesque non feugiat dolor. Cras at dolor velit, """
"""gravida congue velit. Aliquam erat volutpat. Nullam eu nunc dui, quis"""
""" sagittis dolor. Ut nec dui eget odio pulvinar placerat. Pellentesque"""
""" mi metus, tristique et placerat ac, pulvinar vel quam. Nam blandit """
"""magna a urna imperdiet molestie. Nullam ut nisi eget enim laoreet """
"""sodales sit amet a felis.\n""")
class LabelTextSizeTest(App):
def build(self):
z = Label(
text=_long_text,
text_size=(600, None),
line_height=1.5
)
return z
if __name__ == '__main__':
LabelTextSizeTest().run()

View File

@@ -0,0 +1,21 @@
from kivy.app import App
from kivy.lang import Builder
root = Builder.load_string('''
Label:
text:
('[b]Hello[/b] [color=ff0099]World[/color]\\n'
'[color=ff0099]Hello[/color] [b]World[/b]\\n'
'[b]Hello[/b] [color=ff0099]World[/color]')
markup: True
font_size: '64pt'
''')
class LabelWithMarkup(App):
def build(self):
return root
if __name__ == '__main__':
LabelWithMarkup().run()

View File

@@ -0,0 +1,18 @@
# Dynamic kv classes
from kivy.lang import Builder
from kivy.base import runTouchApp
root = Builder.load_string('''
<ImageButton@Button>:
source: None
Image:
source: root.source
center: root.center
ImageButton:
source: 'kivy/data/logo/kivy-icon-512.png'
''')
runTouchApp(root)

View File

@@ -0,0 +1,64 @@
from kivy.base import runTouchApp
from kivy.lang import Builder
kv = '''
PageLayout:
BoxLayout:
canvas:
Color:
rgba: 216/255., 195/255., 88/255., 1
Rectangle:
pos: self.pos
size: self.size
orientation: 'vertical'
Label:
size_hint_y: None
height: 1.5 * self.texture_size[1]
text: 'page 1'
Button:
text: 'test'
on_press: print("test")
BoxLayout:
orientation: 'vertical'
canvas:
Color:
rgba: 109/255., 8/255., 57/255., 1
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'page 2'
AsyncImage:
source: 'http://kivy.org/logos/kivy-logo-black-64.png'
GridLayout:
canvas:
Color:
rgba: 37/255., 39/255., 30/255., 1
Rectangle:
pos: self.pos
size: self.size
cols: 2
Label:
text: 'page 3'
AsyncImage:
source: 'http://kivy.org/slides/kivyandroid-thumb.jpg'
Button:
text: 'test'
on_press: print("test last page")
AsyncImage:
source: 'http://kivy.org/slides/kivypictures-thumb.jpg'
Widget
AsyncImage:
source: 'http://kivy.org/slides/particlepanda-thumb.jpg'
'''
if __name__ == '__main__':
runTouchApp(Builder.load_string(kv))

View File

@@ -0,0 +1,35 @@
'''
Example to show a Popup usage with the content from kv lang.
'''
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.app import App
from kivy.lang import Builder
Builder.load_string('''
<CustomPopup>:
size_hint: .5, .5
auto_dismiss: False
title: 'Hello world'
Button:
text: 'Click me to dismiss'
on_press: root.dismiss()
''')
class CustomPopup(Popup):
pass
class TestApp(App):
def build(self):
b = Button(on_press=self.show_popup, text="Show Popup")
return b
def show_popup(self, b):
p = CustomPopup()
p.open()
TestApp().run()

View File

@@ -0,0 +1,119 @@
from random import sample
from string import ascii_lowercase
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
kv = """
<Row@BoxLayout>:
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
value: ''
Label:
text: root.value
<Test>:
canvas:
Color:
rgba: 0.3, 0.3, 0.3, 1
Rectangle:
size: self.size
pos: self.pos
rv: rv
orientation: 'vertical'
GridLayout:
cols: 3
rows: 2
size_hint_y: None
height: dp(108)
padding: dp(8)
spacing: dp(16)
Button:
text: 'Populate list'
on_press: root.populate()
Button:
text: 'Sort list'
on_press: root.sort()
Button:
text: 'Clear list'
on_press: root.clear()
BoxLayout:
spacing: dp(8)
Button:
text: 'Insert new item'
on_press: root.insert(new_item_input.text)
TextInput:
id: new_item_input
size_hint_x: 0.6
hint_text: 'value'
padding: dp(10), dp(10), 0, 0
BoxLayout:
spacing: dp(8)
Button:
text: 'Update first item'
on_press: root.update(update_item_input.text)
TextInput:
id: update_item_input
size_hint_x: 0.6
hint_text: 'new value'
padding: dp(10), dp(10), 0, 0
Button:
text: 'Remove first item'
on_press: root.remove()
RecycleView:
id: rv
scroll_type: ['bars', 'content']
scroll_wheel_distance: dp(114)
bar_width: dp(10)
viewclass: 'Row'
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
spacing: dp(2)
"""
Builder.load_string(kv)
class Test(BoxLayout):
def populate(self):
self.rv.data = [{'value': ''.join(sample(ascii_lowercase, 6))}
for x in range(50)]
def sort(self):
self.rv.data = sorted(self.rv.data, key=lambda x: x['value'])
def clear(self):
self.rv.data = []
def insert(self, value):
self.rv.data.insert(0, {'value': value or 'default value'})
def update(self, value):
if self.rv.data:
self.rv.data[0]['value'] = value or 'default new value'
self.rv.refresh_from_data()
def remove(self):
if self.rv.data:
self.rv.data.pop(0)
class TestApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TestApp().run()

View File

@@ -0,0 +1,128 @@
'''
QuickReference for Rst
======================
This is a markup example: [b]Hello[/b] [i]world[/i]
And if i really want to write my code: &amp;bl; Hello world &amp;br;
And video widget
----------------
.. video:: cityCC0.mpg
Inline Markup
-------------
- *emphasis*
- **strong emphasis**
- `interpreted text`
- ``inline literal``
- reference_
- `phrase reference`_
- anonymous__
- _`inline internal target`
.. _top:
Internal crossreferences, like example_, or bottom_.
Image
-----
Woot!
What about a little image ?
.. image:: kivy/data/logo/kivy-icon-256.png
Grid
----
+------------+------------+-----------+
| Header 1 | Header 2 | Header 3 |
+============+============+===========+
| body row 1 | column 2 | column 3 |
+------------+------------+-----------+
| body row 2 | column 2 | column 3 |
+------------+------------+-----------+
| body row 3 | column 2 | column 3 |
+------------+------------+-----------+
Term list
---------
:Authors:
Tony J. (Tibs) Ibbs,
David Goodger
(and sundry other good-natured folks)
.. _example:
:Version: 1.0 of 2001/08/08
:Dedication: To my father.
Definition list
---------------
what
Definition lists associate a term with a definition.
how
The term is a one-line phrase, and the definition is one or more paragraphs
or body elements, indented relative to the term. Blank lines are not allowed
between term and definition.
Block quotes
------------
Block quotes are just:
Indented paragraphs,
and they may nest.
Admonitions
-----------
.. warning::
This is just a Test.
.. note::
And this is just a note. Let's test some literal::
$ echo 'Hello world'
Hello world
Ordered list
------------
#. My item number one
#. My item number two with some more content
and it's continuing on the second line?
#. My third item::
Oh wait, we can put code!
#. My four item::
No way.
.. _bottom:
Go to top_'''
from kivy.uix.rst import RstDocument
from kivy.app import App
class RstApp(App):
def build(self):
return RstDocument(text=__doc__)
if __name__ == '__main__':
RstApp().run()

View File

@@ -0,0 +1,53 @@
#:kivy 1.0
<MyScatter>:
canvas:
Color:
hsv: 0, 1, .5
Rectangle:
size: self.size
canvas.after:
Color:
hsv: .1, 1, .5
a: .2
Rectangle:
pos: self.pos
size: self.bbox[1]
Color:
rgb: 0, 1, 0
Line:
points: [self.x, self.top, self.right, self.top]
Line:
points: [self.x, self.y, self.x, self.top]
Line:
points: [self.center_x, self.y, self.center_x, self.top]
Line:
points: [self.x, self.center_y, self.right, self.center_y]
Line:
points: [self.center[0], self.center[1], self.right, self.top]
BoxLayout:
size: root.size
orientation: 'vertical'
Label:
text: 'Position\n' + str(root.pos)
text_size: (root.width, None)
Label:
text: 'Size\n' + str(root.size)
text_size: (root.width, None)
Label:
text: 'Center\n' + str(root.center)
text_size: (root.width, None)
Label:
text: 'Bounding Box\n' + str(root.bbox)
text_size: (root.width, None)
Label:
text: 'Top\n' + str(root.top)
text_size: (root.width, None)
Label:
text: 'Right\n' + str(root.right)
text_size: (root.width, None)

View File

@@ -0,0 +1,16 @@
from kivy.uix.scatter import Scatter
from kivy.app import App
class MyScatter(Scatter):
pass
class ScatterApp(App):
def build(self):
s = MyScatter(size=(400, 400), size_hint=(None, None))
s.top = 500
return s
ScatterApp().run()

View File

@@ -0,0 +1,106 @@
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import NumericProperty
from kivy.lang import Builder
Builder.load_string('''
#:import random random.random
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
#:import SwapTransition kivy.uix.screenmanager.SwapTransition
#:import WipeTransition kivy.uix.screenmanager.WipeTransition
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
#:import RiseInTransition kivy.uix.screenmanager.RiseInTransition
#:import FallOutTransition kivy.uix.screenmanager.FallOutTransition
#:import NoTransition kivy.uix.screenmanager.NoTransition
<CustomScreen>:
hue: random()
canvas:
Color:
hsv: self.hue, .5, .3
Rectangle:
size: self.size
Label:
font_size: 42
text: root.name
Button:
text: 'Next screen'
size_hint: None, None
pos_hint: {'right': 1}
size: 150, 50
on_release: root.manager.current = root.manager.next()
Button:
text: 'Previous screen'
size_hint: None, None
size: 150, 50
on_release: root.manager.current = root.manager.previous()
BoxLayout:
size_hint: .5, None
height: 250
pos_hint: {'center_x': .5}
orientation: 'vertical'
Button:
text: 'Use SlideTransition with "up" direction'
on_release: root.manager.transition = \
SlideTransition(direction="up")
Button:
text: 'Use SlideTransition with "down" direction'
on_release: root.manager.transition = \
SlideTransition(direction="down")
Button:
text: 'Use SlideTransition with "left" direction'
on_release: root.manager.transition = \
SlideTransition(direction="left")
Button:
text: 'Use SlideTransition with "right" direction'
on_release: root.manager.transition = \
SlideTransition(direction="right")
Button:
text: 'Use SwapTransition'
on_release: root.manager.transition = SwapTransition()
Button:
text: 'Use WipeTransition'
on_release: root.manager.transition = WipeTransition()
Button:
text: 'Use FadeTransition'
on_release: root.manager.transition = FadeTransition()
Button:
text: 'Use FallOutTransition'
on_release: root.manager.transition = FallOutTransition()
Button:
text: 'Use RiseInTransition'
on_release: root.manager.transition = RiseInTransition()
Button:
text: 'Use NoTransition'
on_release: root.manager.transition = NoTransition(duration=0)
''')
class CustomScreen(Screen):
hue = NumericProperty(0)
class ScreenManagerApp(App):
def build(self):
root = ScreenManager()
for x in range(4):
root.add_widget(CustomScreen(name='Screen %d' % x))
return root
if __name__ == '__main__':
ScreenManagerApp().run()

View File

@@ -0,0 +1,16 @@
#:kivy 1.0.4
<ScrollView>:
canvas:
Color:
rgb: 1, 0, 0
Rectangle:
pos: self.pos
size: self.size
<GridLayout>:
canvas:
Color:
rgb: 1, 1, 0
Rectangle:
pos: self.pos
size: self.size

View File

@@ -0,0 +1,40 @@
import kivy
kivy.require('1.0.8')
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
class ScrollViewApp(App):
def build(self):
# create a default grid layout with custom width/height
layout = GridLayout(cols=1, padding=10, spacing=10,
size_hint=(None, None), width=500)
# when we add children to the grid layout, its size doesn't change at
# all. we need to ensure that the height will be the minimum required
# to contain all the childs. (otherwise, we'll child outside the
# bounding box of the childs)
layout.bind(minimum_height=layout.setter('height'))
# add button into that grid
for i in range(30):
btn = Button(text=str(i), size=(480, 40),
size_hint=(None, None))
layout.add_widget(btn)
# create a scroll view, with a size < size of the grid
root = ScrollView(size_hint=(None, None), size=(500, 320),
pos_hint={'center_x': .5, 'center_y': .5}, do_scroll_x=False)
root.add_widget(layout)
return root
if __name__ == '__main__':
ScrollViewApp().run()

View File

@@ -0,0 +1,3 @@
title=main
author=seesaw
orientation=portrait

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

View File

@@ -0,0 +1,63 @@
#:kivy 1.0.9
<AnimatedButton>:
canvas.before:
Color:
rgb: (1, 1, 1)
BorderImage:
border: root.border if root.border else (16, 16, 16, 16)
pos: self.pos
size: self.size
texture: self.texture_background
<gifScatter>
on_size: self.center = win.Window.center
size: imag.size
size_hint: None, None
Image:
id: imag
source: 'data/images/simple_cv_joint_animated.gif'
on_touch_down: root.parent.parent.parent.currentObj = self
<zipScatter>
on_size: self.center = win.Window.center
size: imag.size
size_hint: None, None
Image:
id: imag
source: 'data/images/cube.zip'
anim_delay: 0.05
on_touch_down: root.parent.parent.parent.currentObj = self
<jpgScatter>
on_size: self.center = win.Window.center
size: imag.size
size_hint: None, None
Image:
id: imag
source: 'data/images/bird.zip'
on_touch_down: root.parent.parent.parent.currentObj = self
<Right_Frame>
size_hint: (.2, 1)
padding: 10
cols: 1
canvas:
Color:
rgba: .1,.45,.31,.9
Rectangle:
pos: self.pos
size:self.size
Label:
halign: 'center'
text_size: self.size
text: root.currentObj.source if root.currentObj else 'click on a Image to change it\'s properties'
Label:
id: spdlbl
halign: 'center'
text_size: self.size
text: 'No Image selected' if not root.currentObj else 'Animation speed: %f FPS' %(1/root.currentObj.anim_delay) if root.currentObj.anim_delay > 0 else 'Animation speed: 0 FPS'
Slider:
min:0
max: 100 if root.currentObj else 0
value: (1/root.currentObj.anim_delay) if (root.currentObj and root.currentObj.anim_delay>0) else 0
on_value: root.on_value(self, args[1], spdlbl)

View File

@@ -0,0 +1,150 @@
import kivy
kivy.require('1.0.8')
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from uix.custom_button import AnimatedButton
from kivy.uix.scatter import Scatter
from kivy.properties import ObjectProperty
class gifScatter(Scatter):
def __init__(self, **kwargs):
super(gifScatter, self).__init__()
class zipScatter(Scatter):
def __init__(self, **kwargs):
super(zipScatter, self).__init__()
class jpgScatter(Scatter):
def __init__(self, **kwargs):
super(jpgScatter, self).__init__()
class Right_Frame(GridLayout):
currentObj = ObjectProperty(None)
def __init__(self, **kwargs):
super(Right_Frame, self).__init__()
def on_value(self, *l):
if self.currentObj:
if abs(l[1]) <= 0:
self.currentObj.anim_delay = -1
l[2].text = 'Animation speed: %f FPS' % 0
else:
self.currentObj.anim_delay = 1 / l[1]
l[2].text = 'Animation speed: %f FPS' % (
1 / self.currentObj.anim_delay)
else:
l[0].max = 0
l[2].text = 'No Image selected'
class mainclass(FloatLayout):
currentObj = ObjectProperty(None)
def __init__(self, **kwargs):
super(mainclass, self).__init__()
# initialize variables
self.sign = .10
# setup Layouts
layout = GridLayout(size_hint=(1, 1), cols=3, rows=1)
left_frame = GridLayout(size_hint=(.25, 1), cols=1)
client_frame = FloatLayout(size_hint=(1, 1))
self.right_frame = Right_Frame()
# setup buttons in left frame
but_load_gif = AnimatedButton(text='load gif', halign='center')
but_load_zip_png = AnimatedButton(text='load zipped\n png/s',
halign='center')
but_load_zip_jpg = AnimatedButton(text='load zipped\n jpg/s',
halign='center')
but_animated = AnimatedButton(text='animated button\n'
'made using\nSequenced Images\n press to animate',
halign='center',
background_normal='data/images/button_white.png',
background_down='data/images/button_white_animated.zip')
but_animated_normal = AnimatedButton(text='borderless\n'
'animated button\npress to stop',
halign='center',
background_down='data/images/button_white.png',
background_normal='data/images/button_white_animated.zip')
but_animated_borderless = AnimatedButton(text='Borderless',
background_normal='data/images/info.png',
background_down='data/images/info.zip', halign='center')
but_animated_bordered = AnimatedButton(text='With Border',
background_normal='data/images/info.png',
background_down='data/images/info.zip', halign='center')
# Handle button press/release
def load_images(*l):
if l[0].text == 'load gif' or l[0].text == 'load gif\n from cache':
l[0].text = 'load gif\n from cache'
sctr = gifScatter()
if (l[0].text == 'load zipped\n png/s' or
l[0].text == 'load zipped\n png/s from cache'):
l[0].text = 'load zipped\n png/s from cache'
sctr = zipScatter()
if (l[0].text == 'load zipped\n jpg/s' or
l[0].text == 'load zipped\n jpg/s from cache'):
l[0].text = 'load zipped\n jpg/s from cache'
sctr = jpgScatter()
client_frame.add_widget(sctr, 1)
# position scatter
sctr.pos = (240 + self.sign, 200 + self.sign)
self.sign += 10
if self.sign > 200:
self.sign = 10
sctr.pos = (300, 200 - self.sign)
# bind function on on_release
but_load_gif.bind(on_release=load_images)
but_load_zip_png.bind(on_release=load_images)
but_load_zip_jpg.bind(on_release=load_images)
# add widgets to left frame
left_frame.add_widget(but_load_gif)
left_frame.add_widget(but_load_zip_png)
left_frame.add_widget(but_load_zip_jpg)
left_frame.add_widget(but_animated)
left_frame.add_widget(but_animated_normal)
left_frame.add_widget(but_animated_borderless)
left_frame.add_widget(but_animated_bordered)
# set/remove border for borderless widgets (16,16,16,16) by default
but_animated_normal.border = \
but_animated_borderless.border = (0, 0, 0, 0)
# add widgets to the main layout
layout.add_widget(left_frame)
layout.add_widget(client_frame)
layout.add_widget(self.right_frame)
# add main layout to root
self.add_widget(layout)
def on_currentObj(self, *l):
self.right_frame.currentObj = self.currentObj
class mainApp(App):
def build(self):
upl = mainclass()
upl.size_hint = (1, 1)
upl.pos_hint = {'top': 0, 'right': 1}
return upl
if __name__ == '__main__':
mainApp().run()

View File

@@ -0,0 +1,7 @@
'''
UIX
===
The `uix` contains all the class for creating and arranging Custom Widgets.
A widget is an element of a graphical user interface.
'''

View File

@@ -0,0 +1,101 @@
__all__ = ('AnimatedButton')
from kivy.factory import Factory
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.graphics import *
from kivy.properties import StringProperty, OptionProperty, \
ObjectProperty, BooleanProperty
class AnimatedButton(Label):
state = OptionProperty('normal', options=('normal', 'down'))
allow_stretch = BooleanProperty(True)
keep_ratio = BooleanProperty(False)
border = ObjectProperty(None)
anim_delay = ObjectProperty(None)
background_normal = StringProperty(
'atlas://data/images/defaulttheme/button')
texture_background = ObjectProperty(None)
background_down = StringProperty(
'atlas://data/images/defaulttheme/button_pressed')
def __init__(self, **kwargs):
super(AnimatedButton, self).__init__(**kwargs)
self.register_event_type('on_press')
self.register_event_type('on_release')
# borderImage.border by default is ...
self.border = (16, 16, 16, 16)
# Image to display depending on state
self.img = Image(
source=self.background_normal,
allow_stretch=self.allow_stretch,
keep_ratio=self.keep_ratio,
mipmap=True)
# reset animation if anim_delay is changed
def anim_reset(*l):
self.img.anim_delay = self.anim_delay
self.bind(anim_delay=anim_reset)
self.anim_delay = .1
# update self.texture when image.texture changes
self.img.bind(texture=self.on_tex_changed)
self.on_tex_changed()
# update image source when background image is changed
def background_changed(*l):
self.img.source = self.background_normal
self.anim_delay = .1
self.bind(background_normal=background_changed)
def on_tex_changed(self, *largs):
self.texture_background = self.img.texture
def _do_press(self):
self.state = 'down'
def _do_release(self):
self.state = 'normal'
def on_touch_down(self, touch):
if not self.collide_point(touch.x, touch.y):
return False
if repr(self) in touch.ud:
return False
touch.grab(self)
touch.ud[repr(self)] = True
_animdelay = self.img.anim_delay
self.img.source = self.background_down
self.img.anim_delay = _animdelay
self._do_press()
self.dispatch('on_press')
return True
def on_touch_move(self, touch):
return repr(self) in touch.ud
def on_touch_up(self, touch):
if touch.grab_current is not self:
return
assert(repr(self) in touch.ud)
touch.ungrab(self)
_animdelay = self.img._coreimage.anim_delay
self.img.source = self.background_normal
self.anim_delay = _animdelay
self._do_release()
self.dispatch('on_release')
return True
def on_press(self):
pass
def on_release(self):
pass
Factory.register('AnimatedButton', cls=AnimatedButton)

View File

@@ -0,0 +1,93 @@
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.uix.settings import (SettingsWithSidebar,
SettingsWithSpinner,
SettingsWithTabbedPanel)
from kivy.properties import OptionProperty, ObjectProperty
class SettingsApp(App):
display_type = OptionProperty('normal', options=['normal', 'popup'])
settings_popup = ObjectProperty(None, allownone=True)
def build(self):
paneltype = Label(text='What kind of settings panel to use?')
sidebar_button = Button(text='Sidebar')
sidebar_button.bind(on_press=lambda j: self.set_settings_cls(
SettingsWithSidebar))
spinner_button = Button(text='Spinner')
spinner_button.bind(on_press=lambda j: self.set_settings_cls(
SettingsWithSpinner))
tabbed_button = Button(text='TabbedPanel')
tabbed_button.bind(on_press=lambda j: self.set_settings_cls(
SettingsWithTabbedPanel))
buttons = BoxLayout(orientation='horizontal')
buttons.add_widget(sidebar_button)
buttons.add_widget(spinner_button)
buttons.add_widget(tabbed_button)
displaytype = Label(text='How to display the settings?')
display_buttons = BoxLayout(orientation='horizontal')
onwin_button = Button(text='on window')
onwin_button.bind(on_press=lambda j: self.set_display_type('normal'))
popup_button = Button(text='in a popup')
popup_button.bind(on_press=lambda j: self.set_display_type('popup'))
display_buttons.add_widget(onwin_button)
display_buttons.add_widget(popup_button)
instruction = Label(text='Click to open the settings panel:')
settings_button = Button(text='Open settings')
settings_button.bind(on_press=self.open_settings)
layout = BoxLayout(orientation='vertical')
layout.add_widget(paneltype)
layout.add_widget(buttons)
layout.add_widget(displaytype)
layout.add_widget(display_buttons)
layout.add_widget(instruction)
layout.add_widget(settings_button)
return layout
def on_settings_cls(self, *args):
self.destroy_settings()
def set_settings_cls(self, panel_type):
self.settings_cls = panel_type
def set_display_type(self, display_type):
self.destroy_settings()
self.display_type = display_type
def display_settings(self, settings):
if self.display_type == 'popup':
p = self.settings_popup
if p is None:
self.settings_popup = p = Popup(content=settings,
title='Settings',
size_hint=(0.8, 0.8))
if p.content is not settings:
p.content = settings
p.open()
else:
super(SettingsApp, self).display_settings(settings)
def close_settings(self, *args):
if self.display_type == 'popup':
p = self.settings_popup
if p is not None:
p.dismiss()
else:
super(SettingsApp, self).close_settings()
if __name__ == '__main__':
SettingsApp().run()

View File

@@ -0,0 +1,80 @@
'''
Demonstrate shorten / number of line in label
=============================================
--------------- ------- -------------------------------------------------------
Number of lines Shorten Behavior
--------------- ------- -------------------------------------------------------
0 (unlimited) False Default behavior
1 False Display as much as possible, at least one word
N False Display as much as possible
0 (unlimited) True Default behavior (as kivy <= 1.7 series)
1 True Display as much as possible, shorten long word.
N True Display as much as possible, shorten long word.
--------------- ------- -------------------------------------------------------
'''
from kivy.app import App
from kivy.lang import Builder
kv = '''
<LabeledSlider@Slider>:
step: 1
Label:
text: '{}'.format(int(root.value))
size: self.texture_size
top: root.center_y - sp(20)
center_x: root.value_pos[0]
BoxLayout:
orientation: 'vertical'
BoxLayout:
spacing: '10dp'
padding: '4dp'
size_hint_y: None
height: '48dp'
LabeledSlider:
id: slider
value: 500
min: 25
max: root.width
on_value: self.value = int(self.value)
ToggleButton:
id: shorten
text: 'Shorten'
LabeledSlider:
id: max_lines
value: 0
min: 0
max: 5
AnchorLayout:
RelativeLayout:
size_hint: None, None
size: slider.value, 50
canvas:
Color:
rgb: .4, .4, .4
Rectangle:
size: self.size
Label:
size_hint: 1, 1
text_size: self.size
shorten: shorten.state == 'down'
max_lines: max_lines.value
valign: 'middle'
halign: 'center'
color: (1, 1, 1, 1)
font_size: 22
text: 'Michaelangelo Smith'
'''
class ShortenText(App):
def build(self):
return Builder.load_string(kv)
ShortenText().run()

View File

@@ -0,0 +1,17 @@
from kivy.uix.spinner import Spinner
from kivy.base import runTouchApp
spinner = Spinner(
text='Home',
values=('Home', 'Work', 'Other', 'Custom'),
size_hint=(None, None), size=(100, 44),
pos_hint={'center_x': .5, 'center_y': .5})
def show_selected_value(spinner, text):
print('The spinner', spinner, 'has text', text)
spinner.bind(text=show_selected_value)
runTouchApp(spinner)

View File

@@ -0,0 +1,74 @@
from kivy.base import runTouchApp
from kivy.lang import Builder
bl = Builder.load_string('''
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint_y: None
height: sp(60)
Label:
text: 'keep_within_parent?'
CheckBox:
id: in_parent_box
active: False
Label:
text: 'rescale_with_parent?'
CheckBox:
id: rescale_box
active: False
BoxLayout:
orientation: 'horizontal'
Button:
text: 'left btn'
size_hint_x: 0.3
BoxLayout:
orientation: 'vertical'
Button:
text: "Btn0"
BoxLayout:
Splitter:
sizable_from: 'right'
keep_within_parent: in_parent_box.active
rescale_with_parent: rescale_box.active
Button:
text: 'Btn5'
Button:
text: 'Btn6'
BoxLayout:
sizable_from: 'top'
BoxLayout:
orientation: 'horizontal'
BoxLayout:
orientation: 'vertical'
Button:
text: "Btn1"
Splitter:
sizable_from: 'top'
keep_within_parent: in_parent_box.active
rescale_with_parent: rescale_box.active
Button:
text: "Btn2"
Splitter:
sizable_from: 'left'
keep_within_parent: in_parent_box.active
rescale_with_parent: rescale_box.active
Button:
text: "Btn3"
BoxLayout:
orientation: 'vertical'
size_hint_x: 0.3
Button:
text: 'right btn'
Splitter:
sizable_from: 'bottom'
keep_within_parent: in_parent_box.active
rescale_with_parent: rescale_box.active
Button:
text: 'Btn7'
Button:
text: 'right btn'
''')
runTouchApp(bl)

View File

@@ -0,0 +1,317 @@
'''
TabbedPanel
============
Test of the widget TabbedPanel showing all capabilities.
'''
from kivy.app import App
from kivy.animation import Animation
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelHeader
from kivy.factory import Factory
class StandingHeader(TabbedPanelHeader):
pass
class CloseableHeader(TabbedPanelHeader):
pass
Factory.register('StandingHeader', cls=StandingHeader)
Factory.register('CloseableHeader', cls=CloseableHeader)
from kivy.lang import Builder
Builder.load_string('''
<TabShowcase>
but: _but
Button:
id: _but
text: 'Press to show Tabbed Panel'
on_release: root.show_tab()
<StandingHeader>
color: 0,0,0,0
disabled_color: self.color
Scatter:
do_translation: False
do_scale: False
do_rotation: False
auto_bring_to_front: False
rotation: 70
size_hint: None, None
size: lbl.size
center_x: root.center_x
center_y: root.center_y
Label:
id: lbl
text: root.text
size: root.size
color: 1, 1, 1, .5 if self.disabled else 1
pos: 0,0
<PanelLeft>
size_hint: (.45, .45)
pos_hint: {'center_x': .25, 'y': .55}
# replace the default tab with our custom tab class
default_tab_cls: sh.__class__
do_default_tab: True
default_tab_content: default_content.__self__
tab_width: 40
tab_height: 70
FloatLayout:
RstDocument:
id: default_content
text: '\\n'.join(("Standing tabs", "-------------",\
"Tabs in \\'%s\\' position" %root.tab_pos))
Image:
id: tab_2_content
source: 'data/images/defaulttheme-0.png'
Image:
id: tab_3_content
source: 'data/images/image-loading.gif'
StandingHeader:
id: sh
content: tab_2_content.__self__
text: 'tab 2'
StandingHeader:
content: tab_3_content
text: 'tab 3'
<CloseableHeader>
color: 0,0,0,0
disabled_color: self.color
# variable tab_width
text: 'tabx'
size_hint_x: None
width: self.texture_size[0] + 40
BoxLayout:
pos: root.pos
size_hint: None, None
size: root.size
padding: 3
Label:
id: lbl
text: root.text
BoxLayout:
size_hint: None, 1
orientation: 'vertical'
width: 22
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
default_tab: def_tab
# allow variable tab width
tab_width: None
FloatLayout:
RstDocument:
id: default_content
text: '\\n'.join(("Closeable tabs", "---------------",\
"- The tabs above are also scrollable",\
"- Tabs in \\'%s\\' position" %root.tab_pos))
Image:
id: tab_2_content
source: 'data/images/defaulttheme-0.png'
BoxLayout:
id: tab_3_content
BubbleButton:
text: 'Press to add new tab'
on_release: root.add_header()
BubbleButton:
text: 'Press set this tab as default'
on_release: root.default_tab = tab3
CloseableHeader:
id: def_tab
text: 'default tab'
content:default_content.__self__
panel: root
CloseableHeader:
text: 'tab2'
content: tab_2_content.__self__
panel: root
CloseableHeader:
id: tab3
text: 'tab3'
content: tab_3_content.__self__
panel: root
CloseableHeader:
panel: root
CloseableHeader:
panel: root
CloseableHeader:
panel: root
CloseableHeader:
panel: root
CloseableHeader:
panel: root
CloseableHeader:
panel: root
CloseableHeader:
panel: root
<PanelbLeft>
tab_pos: 'bottom_left'
size_hint: (.45, .45)
pos_hint: {'center_x': .25, 'y': .02}
do_default_tab: False
TabbedPanelItem:
id: settings
text: 'Settings'
RstDocument:
text: '\\n'.join(("Normal tabs", "-------------",\
"Tabs in \\'%s\\' position" %root.tab_pos))
TabbedPanelItem:
text: 'tab2'
BubbleButton:
text: 'switch to settings'
on_press: root.switch_to(settings)
TabbedPanelItem:
text: 'tab3'
Image:
source: 'data/images/image-loading.gif'
<PanelbRight>
tab_pos: 'right_top'
size_hint: (.45, .45)
pos_hint: {'center_x': .75, 'y': .02}
default_tab: def_tab
tab_height: img.width
FloatLayout:
RstDocument:
id: default_content
text: '\\n'.join(("Image tabs","-------------",\
"1. Normal image tab","2. Image with Text","3. Rotated Image",\
"4. Tabs in \\'%s\\' position" %root.tab_pos))
Image:
id: tab_2_content
source: 'data/images/defaulttheme-0.png'
VideoPlayer:
id: tab_3_content
source: 'cityCC0.mpg'
TabbedPanelHeader:
id: def_tab
content:default_content.__self__
border: 0, 0, 0, 0
background_down: 'cityCC0.png'
background_normal:'sequenced_images/data/images/info.png'
TabbedPanelHeader:
id: tph
content: tab_2_content.__self__
BoxLayout:
pos: tph.pos
size: tph.size
orientation: 'vertical'
Image:
source: 'sequenced_images/data/images/info.png'\
if tph.state == 'normal' else 'cityCC0.png'
Label:
text: 'text & img'
TabbedPanelHeader:
id: my_header
content: tab_3_content.__self__
Scatter:
do_translation: False
do_scale: False
do_rotation: False
auto_bring_to_front: False
rotation: 90
size_hint: None, None
size: img.size
center: my_header.center
Image:
id: img
source: 'sequenced_images/data/images/info.png'\
if my_header.state == 'normal' else 'cityCC0.png'
size: my_header.size
allow_stretch: True
keep_ratio: False
''')
class Tp(TabbedPanel):
# override tab switching method to animate on tab switch
def switch_to(self, header):
anim = Animation(opacity=0, d=.24, t='in_out_quad')
def start_anim(_anim, child, in_complete, *lt):
_anim.start(child)
def _on_complete(*lt):
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.current_tab.content:
start_anim(anim, self.current_tab.content, False)
else:
_on_complete()
class PanelLeft(Tp):
pass
class PanelRight(Tp):
def add_header(self):
self.add_widget(CloseableHeader(panel=self))
class PanelbLeft(Tp):
pass
class PanelbRight(Tp):
pass
class TabShowcase(FloatLayout):
def show_tab(self):
if not hasattr(self, 'tab'):
self.tab = tab = PanelLeft()
self.add_widget(tab)
self.tab1 = tab = PanelRight()
self.add_widget(tab)
self.tab2 = tab = PanelbRight()
self.add_widget(tab)
self.tab3 = tab = PanelbLeft()
self.add_widget(tab)
self.but.text = \
'Tabs in variable positions, press to change to top_left'
else:
values = ('left_top', 'left_mid', 'left_bottom', 'top_left',
'top_mid', 'top_right', 'right_top', 'right_mid',
'right_bottom', 'bottom_left', 'bottom_mid', 'bottom_right')
index = values.index(self.tab.tab_pos)
self.tab.tab_pos = self.tab1.tab_pos = self.tab2.tab_pos\
= self.tab3.tab_pos = values[(index + 1) % len(values)]
self.but.text = 'Tabs in \'%s\' position,' % self.tab.tab_pos\
+ '\n press to change to next pos'
class TestTabApp(App):
def build(self):
return TabShowcase()
if __name__ == '__main__':
TestTabApp().run()

View File

@@ -0,0 +1,50 @@
'''
TabbedPanel
============
Test of the widget TabbedPanel.
'''
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.lang import Builder
Builder.load_string("""
<Test>:
size_hint: .5, .5
pos_hint: {'center_x': .5, 'center_y': .5}
do_default_tab: False
TabbedPanelItem:
text: 'first tab'
Label:
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."))
""")
class Test(TabbedPanel):
pass
class TabbedPanelApp(App):
def build(self):
return Test()
if __name__ == '__main__':
TabbedPanelApp().run()

View File

@@ -0,0 +1,49 @@
#:kivy 1.0
<BoundedLabel>:
canvas.before:
Color:
rgb: 1, 0, 0
Rectangle:
pos: self.pos
size: self.size
<Selector>:
grid: _grid
Label:
pos_hint: {'top': 1}
size_hint_y: None
height: 50
font_size: 16
text: 'Demonstration of text valign and halign'
GridLayout:
id: _grid
rows: 3
cols: 3
spacing: 10
size_hint: (None, None)
pos_hint: {'center_x': .5, 'center_y': .5}
BoxLayout:
size_hint_y: None
height: 50
ToggleButton:
halign: 'center'
group: 'case'
text: 'label.text_size =\n(None, None)'
on_release: root.app.select(0)
state: 'down'
ToggleButton:
halign: 'center'
group: 'case'
text: 'label.text_size =\n(label.width, None)'
on_release: root.app.select(1)
ToggleButton:
halign: 'center'
group: 'case'
text: 'label.text_size =\n(None, label.height)'
on_release: root.app.select(2)
ToggleButton:
halign: 'center'
group: 'case'
text: 'label.text_size =\n(label.width, label.height)'
on_release: root.app.select(3)

View File

@@ -0,0 +1,48 @@
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty
class BoundedLabel(Label):
pass
class Selector(FloatLayout):
app = ObjectProperty(None)
grid = ObjectProperty(None)
class TextAlignApp(App):
def select(self, case):
for _child in self.selector.grid.children[:]:
self.selector.grid.remove_widget(_child)
for valign in ('bottom', 'middle', 'top'):
for halign in ('left', 'center', 'right'):
label = BoundedLabel(text='V: %s\nH: %s' % (valign, halign),
size_hint=(None, None),
size=(150, 150),
halign=halign, valign=valign)
if case == 0:
label.text_size = (None, None)
elif case == 1:
label.text_size = (label.width, None)
elif case == 2:
label.text_size = (None, label.height)
else:
label.text_size = label.size
self.selector.grid.add_widget(label)
self.selector.grid.bind(minimum_size=self.selector.grid.setter('size'))
def build(self):
self.root = FloatLayout()
self.selector = Selector(app=self)
self.root.add_widget(self.selector)
self.grid = None
self.select(0)
return self.root
TextAlignApp().run()

Some files were not shown because too many files have changed in this diff Show More