【修正】スライドっぽいものを作る - Kivy Advent Calendar 2013
Carouselというウィジェットは、ドラッグしてウィジェットを次々と表示できます。すでに2日目 (Tofu issue) で何の解説もなく使ってますが...
これとRstDocumentを組み合わせればスライドっぽいものができますね。
ということで作ってみました。横方向にスライドすれば次の画面が出てきます。
(一部白い斑点がありますが、これはAndroidの開発者オプションでタップ位置を表示しているものです)
(/sdcard/kivy/slides/)
docutils.zip | docutils-*.tar.gzの中の「docutils」ディレクトリをZIP圧縮したもの |
android.txt | Androidの場合必要 |
fonts_ja.py | 2日目「Tofu issue」のfonts_ja.pyと同じ |
main.py | |
slides.kv | |
title.txt | スライド表紙 |
page01.rst | 1ページ目 |
page02.rst | 2ページ目 |
page03.rst | 3ページ目 |
(android.txt)
title=slides author=cheeseshop orientation=landscape
(main.py)
# -*- coding: utf-8 -*- import os, sys sys.path.insert(0, os.path.join(os.getcwd(), 'docutils.zip')) from kivy.app import App from kivy.uix.carousel import Carousel from kivy.uix.label import Label from kivy.uix.rst import RstDocument from kivy.uix.textinput import TextInput from kivy.uix.popup import Popup import codecs import fonts_ja class TLabel(Label): def __init__(self, **kwargs): if kwargs.has_key('source'): kwargs['text'] = codecs.open(kwargs['source'], 'r', 'utf-8').read() del kwargs['source'] super(TLabel, self).__init__(**kwargs) class Rst(RstDocument): source_encoding = 'utf-8' def on_touch_up(self, touch): if not self.parent.current_slide is self: return if touch.is_double_tap: popup = Popup( title='Source', content=TextInput(text=self.text), auto_dismiss=True, size_hint=(0.8, 0.8)) popup.open() def __init__(self, **kwargs): if kwargs.has_key('source'): kwargs['text'] = codecs.open(kwargs['source'], 'r', 'utf-8').read() del kwargs['source'] super(Rst, self).__init__(**kwargs) class SlidesApp(App): def build(self): carousel = Carousel(direction='right') carousel.add_widget(TLabel(source='title.txt')) carousel.add_widget(Rst(source='page01.rst')) carousel.add_widget(Rst(source='page02.rst')) carousel.add_widget(Rst(source='page03.rst')) return carousel if __name__ == '__main__': SlidesApp().run()
(slides.kv)
: font_size: '20pt' halign: 'center' valign: 'middle' color: 0.2, 0.2, 0.0, 1 canvas.before: Color: rgb: 0.9, 0.9, 0.8 Rectangle: pos: self.pos size: self.size : font_size: '28pt' halign: 'center' valign: 'middle' color: 0.2, 0.2, 0.0, 1 : cols: 1 content: content size_hint_y: None height: content.texture_size[1] + 30 canvas: Color: rgb: parse_color('#cccccc') Rectangle: pos: self.x - 1, self.y - 1 size: self.width + 2, self.height + 2 Color: rgb: parse_color('#eeeeee') Rectangle: pos: self.pos size: self.size Label: id: content markup: True text_size: self.width - 10, None font_name: '/system/fonts/DroidSansFallback.ttf' color: (0, 0, 0, 1)
(title.txt)
Kivy / Python for Androidでプレゼンツール 2013.12.05 http://d.hatena.ne.jp/cheeseshop/
(page01.rst)
================================================ CarouselとScreenManagerの違い ================================================ Carousel
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
(page02.rst)
================================================ このプレゼンツールのポイント ================================================ Tofu issue + 等幅フォントのところだけ化けるのに対応
(page03.rst)
================================================ まとめ ================================================ .. image:: .kivy/icon/kivy-icon-128.png
解説
docutils.zip
2日目でRstDocument使ったときは「docutilsをそのままプロジェクトにつっこんで」とか書きましたが、1MB以上あるんですね。Androidへの転送は面倒だし。
今回はライブラリ本体だけZIP圧縮しておいています。Pythonはこの手が使えるので便利ですね。
ただこれでも480KBくらいありますので、他のプロジェクトと共通で使うのなら、KivyLauncherをビルドしてdocutilsを最初から入れていた方がいいかもしれません。
source引数
TLabelとRstでsourceにファイル名を入れていますが、なぜかその場でファイルを読んでtextに入れ直しています。
これはRstDocumentウィジェットは「source_encoding='utf-8'」としているのに、全然設定が渡されておらず、docutilsは「input_encoding='ascii'」でrstファイルを読もうとしてUnicodeエラーに。
いろいろ試行錯誤しましたが時間切れのため、codecs.openで読み込んでtextにUnicode文字列をつっこむ方法を取っています(Unicode文字列を渡せば正しくレンダリングするのですが)。
ひょっとしたらSphinxの日本語パッチか何かで、スマートな解決方法をやっているのかもしれません。
ダブルタップ
ページをダブルタップをするとTextInputが開き、reSTソースが表示されます(グレーアウトした背景をタップすれば閉じます)。
本当は「プレゼン中にその場で編集→即時更新」なんてかっこいいこと考えたのですが、これも時間切れ。今はただ表示するだけです。
ちなみに最後のreturn Trueを忘れると挙動がおかしくなるようです。ダブルタップのイベントが他のページにも渡されてしまうのかもしれません。
(追記 2013-12-13) ごめんなさい。イベント処理についての知識が足りてなかったです。この件について後で解説します。
(追記 2013-12-21) http://d.hatena.ne.jp/cheeseshop/20131221 で解説を書きました
(追記 2013-12-21) 上のmain.pyを修正しました。今はスライド自身のreSTソースが表示されているはずです。
追記
あーやっと理解しました。
masterブランチでは直っていますが、KivyLaucher 1.7.2はdocutilsにエンコーディングを渡してないです(preloadメソッドにencoding引数がない!)
この問題も1.8.0リリース待ちですかね...
https://twitter.com/mathieuvirbel/status/407950627046948864
昨日、作者さんが「うまくいけば今週中にKivy 1.8出すよ、しかもPython 3コンパチだ」とか呟いてるし。
期待していいんだね? Python for Androidだけ遅れるとかないよね?