スクリーンショットを撮る/タイマーを使う

端末のスクリーンショットを撮る機能、Nexus7-2013では[電源]+[音量小]を同時に0.3秒くらい押すと撮れますが、まあこれがやりにくい。失敗してボリューム表示まで撮れてしまったり…
Kivy自体にもスクリーンショットを取る機能があって、「from kivy.modules import keybinding」とインポートすると「F12」キーを押して撮れます。でもいつもキー入力できるとは限らないし、「ボタンを押したら撮る」だとボタンそのものが写ってしまいます。
ここでは「2013-12-09 画面転換」でスクリーンショットを撮るため、アプリ自体にセルフタイマーつきのスクリーンショット機能を追加してみます。

解説

タイマーについて

ワンショットタイマー (schedule_once) をkv言語側で使ってみました。Clockクラスはkv言語の組み込みではないのでimportが必要ですが、メソッドが増えるよりはいいかなと…
注意点としてはタイマーのコールバックは1つ引数を取るってところでしょうか。dtはシステム時間っぽいです。まあ全然使わないけど引数の数を合わせないといけないので…

スクリーンショット

特にファイル名を指定しなければ「scheenshot0001.png」という形式で、main.pyと同じフォルダに保存してくれます。ただ保存に時間がかかるので、画面が一瞬固まるのが分かると思います。

Home画面とSetting画面。Settingの下から2番目が「5秒後にスクリーンショットを撮る」ボタン。


ワイプとフェード。


スライド(垂直方向と水平方向)。



(/sdcard/kivy/capture/)

android.txt お約束
main.py 5行追加しただけ ほとんど使い回し

(android.txt)

title=capture
author=cheeseshop
orientation=portrait

(main.py)

from kivy.app import App
from kivy.properties import StringProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.screenmanager import ShaderTransition, SlideTransition, FadeTransition, WipeTransition
from kivy.core.window import Window

FADEINOUT_TRANSITION_FS = '''$HEADER$
uniform float t;
uniform sampler2D tex_in;
uniform sampler2D tex_out;

void main(void) {
float t1 = 0.45;
float t2 = 0.55;
vec4 cin = vec4(texture2D(tex_in, tex_coord0.st));
vec4 cout = vec4(texture2D(tex_out, tex_coord0.st));
vec4 frag_col = t < t1 ? vec4*1
            on_text: app.settr(self.text)
        Button:
            pos_hint: {'center_x':0.5, 'top':0.4}
            size_hint: (None, None)
            size: (200, 50)
            text: 'Capture after 5sec'
            on_press: Clock.schedule_once(app.capture, 5)
        Button:
            pos_hint: {'center_x':0.5, 'top':0.2}
            size_hint: (None, None)
            size: (200, 50)
            text: 'Back to home'
            on_press: root.manager.transition = app.tr1; root.manager.current = 'home'
''')

class FadeInOutTransition(ShaderTransition):
    fs = StringProperty(FADEINOUT_TRANSITION_FS)

class HomeScreen(Screen):
    pass

class SettingScreen(Screen):
    pass

class ScreenApp(App):

    trs = {
        'Slide_H': (SlideTransition(direction='right'),
                    SlideTransition(direction='left')),
        'Slide_V': (SlideTransition(direction='up'),
                    SlideTransition(direction='down')),
        'Fade':     FadeTransition(),
        'Wipe':     WipeTransition(),
        'FadeIO':   FadeInOutTransition(),
    }

    def settr(self, tr):
        trs = self.trs[tr]
        if isinstance(trs, tuple):
            self.tr0 = trs[0]
            self.tr1 = trs[1]
        else:
            self.tr0 = trs
            self.tr1 = trs

    def capture(self, dt):
        Window.screenshot()

    def build(self):
        self.sm = ScreenManager()
        self.sm.add_widget(HomeScreen(name='home'))
        self.sm.add_widget(SettingScreen(name='setting'))
        self.settr('Fade')
        return self.sm

if __name__ == '__main__':
    ScreenApp().run()

*1:1.0 - t / t1) * cout) : t > t2 ? vec4((t - t2) / (1.0 - t2) * cin) : vec4(0.0); gl_FragColor = frag_col; } ''' from kivy.lang import Builder Builder.load_string(''' #:import Clock kivy.clock.Clock : canvas.before: Color: rgb: 0.4, 0.3, 0.2, 1 Rectangle: pos: self.pos size: self.size FloatLayout: Label: pos_hint: {'center_x':0.5, 'top':0.8} size_hint: (None, None) size: (200, 50) text: 'Home' Button: pos_hint: {'center_x':0.5, 'top':0.2} size_hint: (None, None) size: (200, 50) text: 'Goto setting' on_press: root.manager.transition = app.tr0; root.manager.current = 'setting' : canvas.before: Color: rgb: 0.2, 0.3, 0.4, 1 Rectangle: pos: self.pos size: self.size FloatLayout: Label: pos_hint: {'center_x':0.5, 'top':0.8} size_hint: (None, None) size: (200, 50) text: 'Setting' Spinner: pos_hint: {'center_x':0.5, 'top':0.6} size_hint: (None, None) size: (200, 50) text: 'Slide_H' values: sorted(app.trs.keys(