mirror of https://github.com/kivy/kivy.git
Add a new showcase example that allows interactive editing of Kivy language code to see how it affects the widgets.
This commit is contained in:
parent
305bf9e839
commit
cdb11c4aa9
Binary file not shown.
|
@ -0,0 +1,20 @@
|
|||
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:
|
||||
* StackLayout is misbehaving
|
||||
* The DropDown item I had tested completely crashes Kivy
|
||||
* Scatter seems to do some weird translation on multitouch. This is probably an Accordion related bug
|
||||
* 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
|
|
@ -0,0 +1,15 @@
|
|||
#:kivy 1.4
|
||||
|
||||
AnchorLayout:
|
||||
anchor_x: "right"
|
||||
anchor_y: "bottom"
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 2"
|
||||
size_hint: .4, .2
|
||||
|
||||
Button:
|
||||
text: "Button 3"
|
||||
size_hint: .2, .2
|
|
@ -0,0 +1,14 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
padding: 20
|
||||
spacing: 10
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint: 1, None
|
||||
Button:
|
||||
text: "Button 2"
|
||||
size_hint: 1, 0.5
|
||||
Button:
|
||||
text: "Button 3"
|
|
@ -0,0 +1,27 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
cols: 2
|
||||
Button:
|
||||
text: "Button 1"
|
||||
Button:
|
||||
text: "Button 2"
|
||||
font_size: 24
|
||||
Button:
|
||||
text: "Button 3"
|
||||
background_color: .7, .7, 1, 1
|
||||
Button:
|
||||
text: "Button 4"
|
||||
on_press: self.text = 'pressed'
|
||||
on_release: self.text = 'Button 4'
|
||||
ToggleButton:
|
||||
text: "A toggle button"
|
||||
ToggleButton:
|
||||
text: "a toggle button in a group"
|
||||
group: "money"
|
||||
ToggleButton:
|
||||
text: "A toggle in the down state"
|
||||
state: "down"
|
||||
ToggleButton:
|
||||
text: "another toggle button in a group"
|
||||
group: "money"
|
|
@ -0,0 +1,27 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
cols: 2
|
||||
CheckBox:
|
||||
Label:
|
||||
text: "A checkbox"
|
||||
active: True
|
||||
CheckBox:
|
||||
Label:
|
||||
text: "Another checkbox"
|
||||
CheckBox:
|
||||
group: "money"
|
||||
Label:
|
||||
text: "A radio in a group"
|
||||
CheckBox:
|
||||
group: "money"
|
||||
Label:
|
||||
text: "Another radio in same group"
|
||||
active: True
|
||||
Switch:
|
||||
Label:
|
||||
text: "A Switch"
|
||||
Switch:
|
||||
active: True
|
||||
Label:
|
||||
text: "An active switch"
|
|
@ -0,0 +1,19 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
# Double as a Tabbed Panel Demo!
|
||||
TabbedPanel:
|
||||
tab_pos: "top_right"
|
||||
default_tab_text: "List View"
|
||||
default_tab_content: list_view_tab
|
||||
|
||||
TabbedPanelHeader:
|
||||
text: 'Icon View'
|
||||
content: icon_view_tab
|
||||
|
||||
FileChooserListView:
|
||||
id: list_view_tab
|
||||
|
||||
FileChooserIconView:
|
||||
id: icon_view_tab
|
||||
show_hidden: True
|
|
@ -0,0 +1,16 @@
|
|||
#:kivy 1.4
|
||||
|
||||
FloatLayout:
|
||||
Button:
|
||||
text: "Button 1"
|
||||
pos: 100, 100
|
||||
size_hint: .2, .4
|
||||
Button:
|
||||
text: "Button 2"
|
||||
pos: 200, 200
|
||||
size_hint: .4, .2
|
||||
|
||||
Button:
|
||||
text: "Button 3"
|
||||
pos_hint: {'x': .8, 'y': .6}
|
||||
size_hint: .2, .2
|
|
@ -0,0 +1,20 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
cols: 2
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint_x: None
|
||||
width: 100
|
||||
Button:
|
||||
text: "Button 2"
|
||||
Button:
|
||||
text: "Button 3"
|
||||
size_hint_x: None
|
||||
Button:
|
||||
text: "Button 4"
|
||||
Button:
|
||||
text: "Button 5"
|
||||
Button:
|
||||
text: "Button 6"
|
||||
size_hint_x: None
|
|
@ -0,0 +1,21 @@
|
|||
#:kivy 1.4
|
||||
|
||||
GridLayout:
|
||||
rows: 2
|
||||
Label:
|
||||
text: "Label 1"
|
||||
Label:
|
||||
text: "Label with\nmultiple lines"
|
||||
Label:
|
||||
text: "Label [color=ff3333]with[/color] [color=3333ff][b]markup[/b][/color]"
|
||||
markup: True
|
||||
Label:
|
||||
text: "Label with [ref=reference]reference[/ref]"
|
||||
markup: True
|
||||
on_ref_press: self.text = "ref clicked"
|
||||
Label:
|
||||
text: "different font"
|
||||
bold: True
|
||||
font_name: "DroidSansMono.ttf"
|
||||
font_size: 32
|
||||
valign: "bottom"
|
|
@ -0,0 +1,9 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
Image:
|
||||
source: "../../widgets/softboy.png"
|
||||
Video:
|
||||
source: "../../widgets/softboy.avi"
|
||||
state: "play"
|
|
@ -0,0 +1,4 @@
|
|||
#:kivy 1.4
|
||||
|
||||
Label:
|
||||
text: "Paste your Kivy code in here and render!"
|
|
@ -0,0 +1,23 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
Bubble:
|
||||
size_hint: (None, None)
|
||||
size: (150, 50)
|
||||
pos_hint: {'center_x': .5, 'y': .6}
|
||||
arrow_pos: 'bottom_mid'
|
||||
orientation: 'horizontal'
|
||||
BubbleButton:
|
||||
text: 'Click'
|
||||
BubbleButton:
|
||||
text: 'A'
|
||||
BubbleButton:
|
||||
text: 'Bubble'
|
||||
Popup:
|
||||
id: popup
|
||||
title: "An example popup"
|
||||
content: popupcontent
|
||||
Label:
|
||||
id: popupcontent
|
||||
text: "Some text\nin the popup"
|
|
@ -0,0 +1,17 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
padding: 50
|
||||
ProgressBar:
|
||||
id: bar
|
||||
value: 140
|
||||
max: 300
|
||||
Slider:
|
||||
id: slider
|
||||
max: 200
|
||||
value: 140
|
||||
on_value: bar.value = self.value
|
||||
Slider:
|
||||
orientation: 'vertical'
|
||||
on_value: slider.value = self.value
|
|
@ -0,0 +1,5 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
RstDocument:
|
||||
text: ".. _top:\n\nHello world\n===========\n\nThis is an **emphased text**, some ``interpreted text``.\nAnd this is a reference to top_::\n\n $ print 'Hello world'\n"
|
|
@ -0,0 +1,16 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
Scatter:
|
||||
size_hint: None, None
|
||||
size: 100, 100
|
||||
pos: 100, 100
|
||||
Image:
|
||||
source: 'softboy.png'
|
||||
Scatter:
|
||||
size_hint: None, None
|
||||
size: 100, 100
|
||||
pos: 100, 100
|
||||
do_rotation: False
|
||||
Label:
|
||||
text: "something"
|
|
@ -0,0 +1,10 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
Spinner:
|
||||
text: "Work"
|
||||
values: "Work", "Home", "Mobile", "Skype"
|
||||
size_hint: (None, None)
|
||||
size: (100, 44)
|
||||
# Wanted to put DropDown here, too, but it seems not to be working too well when loaded from .kv
|
|
@ -0,0 +1,25 @@
|
|||
#:kivy 1.4
|
||||
|
||||
StackLayout:
|
||||
orientation: 'tb-lr'
|
||||
padding: 10
|
||||
spacing: 5
|
||||
Button:
|
||||
text: "Button 1"
|
||||
size_hint: .2, .5
|
||||
width: 100
|
||||
Button:
|
||||
text: "Button 2"
|
||||
size_hint: .2, .5
|
||||
Button:
|
||||
text: "Button 3"
|
||||
size_hint: .2, .5
|
||||
Button:
|
||||
text: "Button 4"
|
||||
size_hint: .2, .5
|
||||
Button:
|
||||
text: "Button 5"
|
||||
size_hint: .2, .5
|
||||
Button:
|
||||
text: "Button 6"
|
||||
size_hint: .2, .5
|
|
@ -0,0 +1,20 @@
|
|||
#:kivy 1.4
|
||||
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
TextInput:
|
||||
text: "Single Line Input"
|
||||
multiline: False
|
||||
TextInput:
|
||||
text: "Text Input, start typing here\nmultiline\nsupport"
|
||||
background_color: .8, .8, 0, 1
|
||||
size_hint: 1, 3
|
||||
TextInput:
|
||||
text: "Password (but you can't see it)"
|
||||
password: True
|
||||
multiline: False
|
||||
on_text: viewer.text = self.text
|
||||
TextInput:
|
||||
id: viewer
|
||||
read_only: True
|
||||
text: "edit the password to see it here"
|
|
@ -0,0 +1,161 @@
|
|||
#:kivy 1.4
|
||||
|
||||
|
||||
<Catalog>:
|
||||
language_box: language_box
|
||||
BoxLayout:
|
||||
spacing: 5
|
||||
TabbedPanel:
|
||||
size_hint: .6, 1
|
||||
tab_pos: "left_top"
|
||||
default_tab_text: "Introduction"
|
||||
default_tab_content: introduction_tab
|
||||
on_default_tab: root.show_kv(*args)
|
||||
|
||||
|
||||
Accordion:
|
||||
id: introduction_tab
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "Playground"
|
||||
kv_container: playground
|
||||
PlaygroundContainer:
|
||||
id: playground
|
||||
AccordionItem:
|
||||
title: "Welcome"
|
||||
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.\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."
|
||||
|
||||
TabbedPanelHeader:
|
||||
text: 'Layouts'
|
||||
content: layout_tab
|
||||
on_state: root.show_kv(*args)
|
||||
TabbedPanelHeader:
|
||||
text: 'UX Widgets'
|
||||
content: basic_widgets
|
||||
on_state: root.show_kv(*args)
|
||||
TabbedPanelHeader:
|
||||
text: 'Complex'
|
||||
content: complex_widgets
|
||||
on_state: root.show_kv(*args)
|
||||
|
||||
Accordion:
|
||||
id: layout_tab
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "FloatLayout"
|
||||
kv_container: floatlayoutcontainer
|
||||
FloatLayoutContainer:
|
||||
id: floatlayoutcontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "BoxLayout"
|
||||
kv_container: boxlayoutcontainer
|
||||
BoxLayoutContainer:
|
||||
id: boxlayoutcontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "AnchorLayout"
|
||||
kv_container: anchorlayoutcontainer
|
||||
AnchorLayoutContainer:
|
||||
id: anchorlayoutcontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "GridLayout"
|
||||
kv_container: gridlayoutcontainer
|
||||
GridLayoutContainer:
|
||||
id: gridlayoutcontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "StackLayout"
|
||||
kv_container: stacklayoutcontainer
|
||||
StackLayoutContainer:
|
||||
id: stacklayoutcontainer
|
||||
Accordion:
|
||||
id: basic_widgets
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "Buttons"
|
||||
kv_container: buttoncontainer
|
||||
ButtonContainer:
|
||||
id: buttoncontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "Labels"
|
||||
kv_container: labelcontainer
|
||||
LabelContainer:
|
||||
id: labelcontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "Booleans"
|
||||
kv_container: checkboxcontainer
|
||||
CheckBoxContainer:
|
||||
id: checkboxcontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "Progress Bar"
|
||||
kv_container: progressbarcontainer
|
||||
ProgressBarContainer:
|
||||
id: progressbarcontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "Media"
|
||||
kv_container: mediacontainer
|
||||
MediaContainer:
|
||||
id: mediacontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "Text"
|
||||
kv_container: textcontainer
|
||||
TextContainer:
|
||||
id: textcontainer
|
||||
Accordion:
|
||||
id: complex_widgets
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "Popups"
|
||||
kv_container: popupcontainer
|
||||
PopupContainer:
|
||||
id: popupcontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "Selectors"
|
||||
kv_container: selectorscontainer
|
||||
SelectorsContainer:
|
||||
id: selectorscontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "FileChoosers"
|
||||
kv_container: filechoosercontainer
|
||||
FileChooserContainer:
|
||||
id: filechoosercontainer
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "Scatter"
|
||||
kv_container: scatter
|
||||
ScatterContainer:
|
||||
id: scatter
|
||||
AccordionItem:
|
||||
on_collapse: root.show_kv(*args)
|
||||
title: "ReST"
|
||||
kv_container: rest
|
||||
RestContainer:
|
||||
id: rest
|
||||
|
||||
BoxLayout:
|
||||
id: bl
|
||||
orientation: "vertical"
|
||||
size_hint: .4, 1
|
||||
TextInput:
|
||||
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)
|
|
@ -0,0 +1,138 @@
|
|||
import os
|
||||
from kivy.app import App
|
||||
from kivy.factory import Factory
|
||||
from kivy.lang import Builder, Parser, ParserException
|
||||
from kivy.properties import ObjectProperty
|
||||
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.popup import Popup
|
||||
from kivy.uix.label import Label
|
||||
|
||||
'''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')]
|
||||
|
||||
|
||||
def factoryable(class_name, parents, attrs):
|
||||
'''Metaclass that automatically records the resultant class in the Factory.
|
||||
This allows the class to be accessed inside the .kv language file in the
|
||||
Builder.
|
||||
'''
|
||||
cls = type(class_name, parents, attrs)
|
||||
Factory.register(class_name, cls)
|
||||
return cls
|
||||
|
||||
|
||||
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.
|
||||
'''
|
||||
__metaclass__ = factoryable
|
||||
|
||||
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 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()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(Catalog, self).__init__(**kwargs)
|
||||
self.kv_container = None
|
||||
from kivy.clock import Clock
|
||||
Clock.schedule_once(self.show_kv)
|
||||
|
||||
def show_kv(self, object, collapsed=None):
|
||||
'''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 collapsed == "down": # a tabbed panel was clicked, not an accordion
|
||||
object = object.content.children[0]
|
||||
collapsed = False
|
||||
if collapsed is False and hasattr(object, "kv_container"):
|
||||
with open(object.kv_container.kv_file) as file:
|
||||
self.language_box.background_color = (1, 1, 1, 1)
|
||||
self.language_box.readonly = False
|
||||
self.language_box.text = file.read()
|
||||
self.kv_container = object.kv_container
|
||||
else:
|
||||
self.language_box.background_color = (1, 1, 1, .5)
|
||||
self.language_box.text = ""
|
||||
self.language_box.readonly = True
|
||||
self.kv_container = None
|
||||
|
||||
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.'''
|
||||
if self.kv_container:
|
||||
try:
|
||||
parser = Parser(content=self.language_box.text.encode('utf8'))
|
||||
self.kv_container.clear_widgets()
|
||||
widget = Factory.get(parser.root.name)()
|
||||
Builder._apply_rule(widget, parser.root, parser.root)
|
||||
self.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()
|
Loading…
Reference in New Issue