Merge pull request #746 from buchuki/master

Revised example Kivy script
This commit is contained in:
qua-non 2012-10-23 03:42:38 -07:00
commit 29bae666e2
21 changed files with 581 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,18 @@
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
To use it, you'll need to install Kivy and it's dependencies
a la http://kivy.org/docs/installation/installation.html Then run
python main.py and browse or edit widgets to your heart's content.
Known bugs:
* The DropDown item I had tested completely crashes Kivy
* The GridLayout example could use some extra features
* If you try to start the app with focused set to true, weird stuff happens.
but it works fine if you set focused to true and press render.
* Video playback doesn't work for me, but this may be a dependency issue
* Popups are displayed inline
* Some widgets are still missing

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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: "DroidSansMono.ttf"
font_size: 32
valign: "bottom"

View File

@ -0,0 +1,9 @@
#:kivy 1.4
BoxLayout:
orientation: "vertical"
Image:
source: "../../widgets/softboy.png"
Video:
source: "../../widgets/softboy.avi"
state: "play"

View File

@ -0,0 +1,6 @@
#:kivy 1.4
Label:
text_size: self.width-60, self.height-60
valign: "middle"
text: "The 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."

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -0,0 +1,120 @@
#:kivy 1.4
[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
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:
text_size: self.width-20, self.height-20
font_name: "DroidSansMono.ttf"
valign: "top"
id: language_box
text: "This box will display the kivy language for whatever has been selected"
Button:
size_hint: 1, None
height: 50
text: "Render"
on_press: root.change_kv(*args)

View File

@ -0,0 +1,153 @@
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.textinput import TextInput
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(TextInput):
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()
def change_kv(self, button):
'''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:
content = Label(text=str(e), text_size=(350, None))
popup = Popup(title="Parse Error in Kivy Language Markup",
content=content, text_size=(350, None),
size_hint=(None, None), size=(400, 400))
popup.open()
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)),
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()