console — コンソール画面への表示と各種システムサービスのユーティリティー

 console モジュールはPythonistaの文字出力画面とキーボード入力をコントロールする関数を提供します。

 また、簡易な形式のダイアローグボックスを動作させたり、「Open in...」のようなメニューやQuickLookのようなサービスにアクセスするための関数もあります。

console.clear()

 コンソール画面の出力をクリアします。

console.set_font([name, size])

 コンソール出力に用いるフォントの種類とサイズを設定します。引数を省略して呼び出すと、デフォルト値にリセットします。

console.set_color(r, g, b)

 コンソール出力のRGB色を設定します。引数は、それぞれ0.0〜1.0の間の浮動小数型です。

console.secure_input([prompt])

 この関数は、pythonの標準関数であるinputに似ていますが、ユーザーの入力値が画面表示されないので、パスワードやその他の重要な情報の入力に適しています。

console.show_image(image_path)

 ファイルから画像を読み込んで、コンソール画面の出力エリアに表示します。

console.alert(title[, message, button1, button2, button3, hide_cancel_button=False])

 最大3つのボタンを持った警告ダイヤログボックスを表示します。選んだボタンは整数型で返されます。(ボタン1の時に戻り値1など)hide_cancel_button が真(True)でない場合には、警告ダイヤログボックスのキャンセルボタンは KeyboardInterrupt(キーボード割込)を発生させます。

console.input_alert(title[, message, input, ok_button_title, hide_cancel_button=False])

 1行の文字列エリアを持つダイアログボックスを表示します。文字列エリアは予め引数 input で与えた文字列を表示することもできます。この関数はユーザーが入力した文字列を返します。キャンセルボタンを押すとKeyboardInterrupt(キーボード割込)を発生させます。

console.password_alert(title[, message, password, ok_button_title, hide_cancel_button=False])

 パスワード入力エリアを持ったダイアログを表示します。パスワード入力エリアは予め引数passwordで与えた文字列を表示することもできます。この関数は、ユーザーが入力したパスワードを返します。キャンセルボタンを押すと通常はスクリプトの実行を止める KeyboardInterrupt(キーボード割込)を発生させます。

console.login_alert(title[, message, login, password, ok_button_title])

 ログイン用とパスワード用の2つの文字列エリアを持つダイヤログを表示します。文字列エリアはloginとpasswordの2つの引数で指定した文字列を予め表示させることもできます。この関数は入力したログインとパスワードのタプルを返します。キャンセルボタンを押すと通常はスクリプトの実行を止めるKeyboardInterrupt(キーボード割込)を発生させます。

console.show_activity()

 ステータスバーに「ネットワーク・アクティビティ・インジケーター」をアニメーション表示します。回転するインジケーターは、スクリプトが終了すると自動的に隠されます。回転インジケーターが既に表示されている場合には、この関数を呼び出しても変化はありません。

console.hide_activity()

 ステータスバーの「ネットワーク・アクティビティ・インジケーター」を隠します。回転するインジケーターは、スクリプトが終了すると自動的に隠されます。回転インジケーターが既に表示されている場合には、この関数を呼び出しても変化はありません。

(注 pythonista3のヘルプ画面には、このように記述されていますが、そもそも「インジケーターを隠す」関数なので、2行目以降は上記のshow_activity()の説明文をうっかりコピペしてしまったものであり、無視すべきだと思います)

console.hud_alert(message[, icon, duration])

 引数messageで与えたメッセージ付きのHUD形式の警告表示をします。メッセージの上に表示するアイコンは、「成功」(デフォルトのチェックマーク表示)にも「エラー」(バツの表示)にもできます。

 引数durationは画面上にどの位の時間警告表示をするかを決めます。0.25から5.0秒の間で選べます。デフォルトでは1.8秒です。この関数は警告が消えるまで次のスクリプトに進みません。

(例 console.hud_alert('書き込みは禁止されています‘,'error',5.0) )

console.write_link(title, link_url)

 コンソール画面に引数titleとlink_urlで指定した、タップ可能なリンクを表示します。このリンクは(httpやhttps、ファイルのURLを)Safariで開くことができるほか、(あれば)他のアプリで開く事も可能です。

 set_color()を使って文字の色をカスタマイズすれば、リンク文字の色も変えられます。指定しなければデフォルトの色が使われます。

console.hide_output()

 コンソール画面の出力エリアを(右にスワイプするような)スライドするアニメーションで隠します。

console.quicklook(file_path)

 引数 file_path で指定したパスにあるファイル(複数あれば複数)の全画面サイズのプレビューを表示します。一度に複数のファイルのプレビューを表示するために、例えばリスト形式で一連のパスを引数として設定することも可能です。この関数はプレビューを消した段階で終了します。

 多くのファイル形式をサポートしています:

  • iWork 文書
  • マイクロソフトオフィス文書(Office ‘97 又はそれ以降)
  • リッチ・テキスト・フォーマット(RTF)文書
  • PDF ファイル
  • 画像
  • MacOSデータ識別形式であるUniform Type Identifier(UTI)のテキストファイルで「public.text」タイプに適合させた文書
  • CSV形式のファイル

console.open_in(file_path)

 特定のファイルに対して iOS の “Open in...” メニューを表示します。

 メニューの中からアプリを選ぶと、アプリに関連付けられたIDを返します。(例えば、'com.getdropbox.Dropbox'など)メニューがキャンセルされた場合やそのファイルを開くことのできるアプリがインストールされていない場合には、None値を返します。

console.set_idle_timer_disabled(flag)

 一定の時間操作がない場合にiPhone(やiPad)をスリープ状態にする「アイドル・タイマー」をオン/オフします。

console.is_in_background()

 アプリがバックグラウンドで実行されている場合に True を返します。その他の場合には False を返します。

 

clipboard — コピー&ペースト

 clipboardモジュールは、iOS上の文字のクリップボードからの読込みとクリップボード(別名 ペーストボード)への書込みという2つのシンプルな機能を定義しています。

 以下に例を示します。

#クリップボードの文字列の大文字/小文字変換
import clipboard
text = clipboard.get() # クリップボードから文字列を取得
if text == '':         # クリップボードに文字列がなかった場合
    print('No text in clipboard')
else:
    uppercase = text.upper()
    # クリップボードから取得した文字列と、それを大文字に変換したものを比較
    if uppercase != text: # 等しくなかったら、大文字に変換したものを採用
        new_clip = uppercase
    else:                 # 等しかったら、小文字に変換したものを採用
        #already uppercase, convert to lowercase
        new_clip = text.lower()
    clipboard.set(new_clip) # 採用した文字列をクリップボードに書き込む
    print(new_clip)

clipboard モジュールの関数:

clipboard.get()

 クリップボードの内容をユニコードの文字列として返します。

clipboard.set(string)

 クリップボードの内容として、新しい文字列又はユニコード文字列として設定します。

clipboard.get_image(idx=0)

 クリップボードから画像をPIL形式で返します。クリップボードに複数の画像がある場合には、引数idxで取り出す画像を指定することができます。idxの値が、クリップボードに保管されている画像の数より大きい場合には、Noneが返されます。

clipboard.set_image(image, format='png', jpeg_quality=0.75)

 引数のimageが示すPIL形式の画像データをクリップボードに保管します。フォーマットを示す引数としては、「png」と「jpeg」が指定可能です。引数のjpeg_qualityは、「png」形式の時は無視されます。その他の場合、この値は0.0から1.0の浮動小数型でなくてはいけません。

cb — Bluetooth LE 機器への接続

 cb(Core  Bluetooth)モジュールを使えば、テキサスインスツルメンツ社製センサータグ(赤外線温度計や加速度計など、多くの種類のセンサーを含む、小型で安価なBluetooth LE機器)のようなBluetooth  LE(Low  Energy:低消費電力)の機器に接続することができるようになります。

 このマニュアルにあげる例では、標準的なBluetooth LE 心拍数モニターや、テキサスインスツルメンツ社製センサータグを取り上げますが、モジュール自体はその他のタイプのBluetooth LE機器にも適用可能です。マイク付きヘッドホンやキーボードなどの、いわゆる「古典的な」Bluetoothについては対応していませんのでご注意下さい。

 このモジュールはアップル社が提供しているCoreBluetoothフレームワークを使用していますが、その機能の全てをカバーしている訳ではありません。フレームワークの主たる役割のみ提供します。すなわち、機器への接続は可能ですが、機器そのもののデバイスの制御はサポートしていません。

クイックスタート

 Bluetooth LE機器への接続やデータの読込みのための基本的な手順は以下の段階のようになっています。

 見つけた機器やデバイス、サービス、サービス特性に通知や呼出しをするためのデリゲートなオブジェクトを定義します。実行できるコールバックの手法については後述します。

 scan_for_peripherals()を呼び出してスキャンを開始します。多くの場合、デバイスを見つけられるように操作する必要があります。テキサスインスツルメンツ社製センサータグの場合、本体横のボタンを押す必要があります。

 did_discover_peripheralコールバックをデリゲートオブジェクトが受け取ったら、デバイスの名前やUUID(Universally Unique IDentifier:デバイスの識別子)を調べた上で、接続したい周辺機器を見つけた場合にはconnect_peripheral()を呼び出します。接続を維持するために、見つかった周辺機器の名前やUUIDは持ち続けておく必要があります。さもなければ、オブジェクトがガーベージコレクションされた際に接続が遮断されてしまいます。

 全てがスムーズに進んだ場合、the did_connect_peripheralコールバックが呼び出されます。この時点で、Peripheral.discover_services()を呼び出すことにより、周辺機器のサービス一覧を見ることができるようになります。

 周辺機器のサービス一覧を見つけたら、did_discover_servicesコールバックを受け取ることになります。この段階で周辺機器のサービス属性にアクセスできるようになるので、目的のサービスを実行するためにPeripheral.discover_characteristics()を呼び出します。

 もうお分かりかも知れませんが、これはdid_discover_characteristicsコールバックの結果です。この段階で(値をうまく読み込めた他のコールバックの結果として)Peripheral.read_characteristic_value()を呼び出すことで値を読み込んだり、Peripheral.set_notify_value()により通知を受けることが可能になります。

 以下のコードは、Bluetooth LE 心拍数モニターにどのように接続するかを示しています。この例は、Polar社のデバイスを対象としていますが、他のブランドの心拍数モニターにも簡単に応用できるでしょう。(did_discover_peripheralメソッドを適宜変更するだけです):

import cb
import sound
import time
import struct
from __future__ import print_function

class HeartRateManager (object):
    def __init__(self):
        self.peripheral = None

    def did_discover_peripheral(self, p):
        if p.name and 'Polar' in p.name and not self.peripheral:
            self.peripheral = p
            print('Connecting to heart rate monitor...')
            cb.connect_peripheral(p)

    def did_connect_peripheral(self, p):
        print('Connected:', p.name)
        print('Discovering services...')
        p.discover_services()

    def did_fail_to_connect_peripheral(self, p, error):
        print('Failed to connect: %s' % (error,))

    def did_disconnect_peripheral(self, p, error):
        print('Disconnected, error: %s' % (error,))
        self.peripheral = None

    def did_discover_services(self, p, error):
        for s in p.services:
            if s.uuid == '180D':
                print('Discovered heart rate service, discovering characteristitcs...')
                p.discover_characteristics(s)

    def did_discover_characteristics(self, s, error):
        print('Did discover characteristics...')
        for c in s.characteristics:
            if c.uuid == '2A37':
                self.peripheral.set_notify_value(c, True)

    def did_update_value(self, c, error):
        heart_rate = struct.unpack('<B', c.value[1])[0]
        self.values.append(heart_rate)
        print('Heart rate: %i' % heart_rate)

mngr = HeartRateManager()
cb.set_central_delegate(mngr)
print('Scanning for peripherals...')
cb.scan_for_peripherals()

try:
    while True: pass
except KeyboardInterrupt:
    cb.reset()

 次の例はテキサスインスツルメンツ社製センサータグにどのように接続するかを示しています。温度センサーの(先ほどの心拍数モニターの例に良く似ていますが、1秒間に1回)値を記録し、センサータグのどれか2つのボタンが押されたら音を鳴らすというものです:

import cb
import sound
import struct

class MyCentralManagerDelegate (object):
    def __init__(self):
        self.peripheral = None

    def did_discover_peripheral(self, p):
        print('+++ Discovered peripheral: %s (%s)' % (p.name, p.uuid))
        if p.name and 'Sensor Tag' in p.name and not self.peripheral:
            # Keep a reference to the peripheral, so it doesn't get garbage-collected:
            self.peripheral = p
            cb.connect_peripheral(self.peripheral)

    def did_connect_peripheral(self, p):
        print('*** Connected: %s' % p.name)
        print('Discovering services...')
        p.discover_services()

    def did_fail_to_connect_peripheral(self, p, error):
        print('Failed to connect')

    def did_disconnect_peripheral(self, p, error):
        print('Disconnected, error: %s' % (error,))
        self.peripheral = None

    def did_discover_services(self, p, error):
        for s in p.services:
            if 'AA00' in s.uuid:
                print('+++ IR Thermometer found')
                p.discover_characteristics(s)
            elif 'FFE0' in s.uuid:
                print('+++ Simple Key Service found')
                p.discover_characteristics(s)

    def did_discover_characteristics(self, s, error):
        if 'AA00' in s.uuid:
            for c in s.characteristics:
                if 'AA02' in c.uuid:
                    print('Enabling temperature sensor...')
                    self.peripheral.write_characteristic_value(c, chr(0x01), True)
                elif 'AA01' in c.uuid:
                    # Enable notification for the temperature sensor:
                    print('Enabling temperature sensor notifications...')
                    self.peripheral.set_notify_value(c, True)
        elif 'FFE0' in s.uuid:
            print('Enabling notifications for Simple Key Service...')
            key_characteristic = s.characteristics[0]
            self.peripheral.set_notify_value(key_characteristic, True)

    def did_write_value(self, c, error):
        # The temperature sensor has been activated (see did_discover_characteristic)
        print('Did enable temperature sensor')

    def did_update_value(self, c, error):
        if 'FFE1' == c.uuid:
            # A button on the SensorTag was pressed (or released):
            print('Button value: %s' % c.value.encode('hex'))
            sound.play_effect('Beep')
        else:
            # The temperature sensor has sent an updated value:
            tobj, mtmpamb = self.convert_temperature(c.value)
            print('Object temperature: %f -- Ambient: %f' % (tobj, mtmpamb))

    def convert_temperature(self, raw_data):
        # This will convert the raw sensor data to temperature values in Celsius.
        # The details of this algorithm aren't important for this example, you can
        # find more information about this in the SensorTag user guide:
        # http://processors.wiki.ti.com/index.php/SensorTag_User_Guide
        rawT = struct.unpack('<h', raw_data[:2])[0]
        tmpAmb = struct.unpack('<H', raw_data[2:])[0]
        vobj2 = float(rawT) * 0.00000015625
        mtmpamb = float(tmpAmb) / 128.0
        tdie2 = mtmpamb + 273.15
        s0, a1, a2 = 6.4E-14, 1.75E-3, -1.678E-5
        b0, b1, b2, c2 = -2.94E-5, -5.7E-7, 4.63E-9, 13.4
        Tref = 298.15
        S = s0 * (1.0+a1*(tdie2 - Tref) + a2 * pow((tdie2 - Tref), 2))
        vos = b0 + b1*(tdie2-Tref) + b2*pow((tdie2-Tref), 2)
        fobj = (vobj2 - vos) + c2 * pow((vobj2 - vos), 2)
        tobj = pow(pow(tdie2, 4) + (fobj/S), 0.25) - 273.15
        return tobj, mtmpamb

delegate = MyCentralManagerDelegate()
print('Scanning for peripherals...')
cb.set_central_delegate(delegate)
cb.scan_for_peripherals()

# Keep the connection alive until the 'Stop' button is pressed:
try:
    while True: pass
except KeyboardInterrupt:
    # Disconnect everything:
    cb.reset()

関数

cb.set_central_delegate(delegate)

 機器を見つけた場合や、データを受け取った場合など、イベントのコールバックを受け取るためのオブジェクトを設定します。

 引数部分の「delegate」は以下の方法で、その後の各メソッドの引数として使用できます:

class MyDelegate (object):
    def did_update_state(self):
        # State was updated (e.g. Bluetooth powered on/off)
        pass

    def did_discover_peripheral(self, p):
        # You would typically check the peripheral's name/uuid here,
        # and connect via cb.connect_peripheral(p).
        # You should also keep a reference to p (e.g. self.peripheral = p),
        # so that it doesn't get garbage-collected.
        # Note that this may get called multiple times for a single peripheral.
        pass

    def did_connect_peripheral(self, p):
        # You would typically call p.discover_services() here
        pass

    def did_fail_to_connect_peripheral(self, p, error):
        # `error` is a tuple of error code (integer) and description (string)
        pass

    def did_disconnect_peripheral(self, p, error):
        # error is a tuple of error code (integer) and description (string)
        pass

    def did_discover_services(self, p, error):
        # Here you would typically call discover_characteristics
        # for the services you're interested in.
        pass

    def did_discover_characteristics(self, s, error):
        # You can now read or write the characteristic's value
        pass

    def did_write_value(self, c, error):
        pass

    def did_update_value(self, c, error):
        # You can now access the characteristic value with c.value
        pass

cb.set_verbose(flag)

 Trueに設定すると、コールバックイベントのデリゲート(set_central_delegate()を参照) が適用されたか否かを問わず、全てのコールバックイベントがコンソール画面に記録されます。これはデバッグに便利です。

cb.scan_for_peripherals()

 アドバタイズされているサービスの周辺機器のスキャンを開始します。

cb.stop_scan()

 周辺機器のスキャンを終了します。

cb.connect_peripheral(peripheral)

 周辺機器(peripheral)と接続します。一般的にこの関数はdid_discover_peripheralコールバック処理から呼び出されます。

cb.cancel_peripheral_connection(peripheral)

 アクティブな、又は中断している周辺機器(peripheral)との接続をキャンセルします。

cb.get_state()

 セントラルマネージャーの現在の状態を返します。(どんな値があるかは Constants を参照)

cb.reset()

 全ての周辺機器との接続を切断します。この関数は同時にセントラル・デリゲートをNoneに設定してしまうので、全てのコールバックを受け付けなくなります。

クラス

(注意 このモジュールのクラス群は、直接インスタンス化することを意図していません。代わりに、デリゲート実行するコールバック関数へのパラメーターとして異なるクラス群のインスタンスを取得します。(set_central_delegate()を参照))

周辺機器(Peripheral)

class cb.Peripheral

 Peripheralクラスは scan_for_peripherals() 経由で見つけた周辺機器デバイスを表すクラスです。周辺機器は、UUID(Universally Unique IDentifiers)で識別されます。周辺機器は一つないし複数のサービス(Serciceオブジェクトで表せます)を実行できます。

周辺機器(Peripheral)メソッド

Peripheral.discover_services()

 周辺機器のサービスを見つけます。見つけ終わると、セントラル・デリゲートはdid_discover_servicesコールバックを受け取ります。

Peripheral.discover_characteristics(service)

 引数「service」で指定されたサービスの持つ「characteristic」を見つけます。このメソッドは、一般的にはdid_discover_servicesコールバックから呼び出されます。「characteristic」が見つかったら、セントラル・デリゲートはdid_discover_characteristicsコールバックを受け取ります。

Peripheral.set_notify_value(characteristic, flag=True)

 引数のcharacteristicに関する通知のオン/オフを設定します。(注 全てのcharacteristicsに対応しているわけではありません)通知がオンの場合、セントラル・デリゲートでdid_update_valueコールバックで受け取ることができます。(set_central_delegate()を参照)

Peripheral.write_characteristic_value(characteristic, data, with_response)

 Characteristic の値を書き込みます。引数の data は、1バイトの文字列でなければなりません。引数 with_response によって、書込みがが完了した時(又は失敗した時)にdid_write_valueコールバックが呼び出されるか否かを指定します。応答なしに書き込める値の全てをサポートしている訳ではないことにご注意下さい。

Peripheral.read_characteristic_value(characteristic)

 引数characteristicで与えられる値を検索します。読み込まれたことがある値の場合は、セントラル・デリゲートは、characteristicの値の属性とともに値にアクセスできるポイントで、did_update_valueコールバックを受け取ります。全てのcharacteristicについて読込可能な値があるとは限りません。

周辺機器(Peripheral)の属性

Peripheral.manufacturer_data

 周辺機器のアドバタイジングデータ(周辺機器が親機に対して発する存在をアピールする信号)の一部である、メーカーを特定するデータです。周辺機器との接続が確立しなくても読むことができます。(一般的には、did_discover_peripheral コールバック中で使用)

Peripheral.name

 周辺機器の名称です。(文字列の場合とNoneの場合があります)

Peripheral.uuid

 周辺機器のUUIDです。(16進数の文字列です)

Peripheral.state

 周辺機器との接続の状態です。(0:未接続、1:接続中、2:接続済)

Peripheral.services

 周辺機器から示されたサービスのリストです。(Serviceオブジェクトのリストです)このリストは通常、Peripheral.discover_services()を呼び出すまで(そしてdid_discover_servicesコールバックを受け取るまで)空の状態であることにご注意下さい。

サービス

class cb.Service

 サービス(Service)オブジェクトは、周辺機器(Peripheral)のサービス、すなわちデバイス(あるいはその一部)の機能や特徴を実現するためのデータや関連する動作の集合体、を示します。サービス・オブジェクトは最初、あるいは二番目、ないしはCharacteristicクラスの中に含まれます。

サービスの属性

Service.characteristics

 サービスのキャラクタリスティックです。(Characteristicオブジェクトのリストで、見つからないうちは空のリストになります)

Service.primary

 サービスが1番目か2番目かを示す、ブール型のフラグです。

Service.uuid

 サービスのUUIDです。(16進数の文字列)

キャラクタリスティック

class cb.Characteristic

 Characteristic オブジェクトは周辺機器のサービスについての詳細情報を示します。一つのキャラクタリスティックは一つの値を持ちます。キャラクタリスティックの属性により、キャラクタリスティックの値がどのように使われるかが決まります。

キャラクタリスティックの属性

Characteristic.uuid

 キャラクタリスティックのUUIDです。(16進数の文字列)

Characteristic.value

 キャラクタリスティックの現在の値です。(1バイト文字列の場合もあれば、読み込む前や値がない時にはNone値となる場合もあります)

Characteristic.notifying

 このキャラクタリスティックの通知を許可するか否かのフラグです。(リードオンリーにする場合は Peripheral.set_notify_value() を使って設定します)

Characteristic.properties

 キャラクタリスティックの属性に対するビットマスクです。(後述の定数CH_PROP_*を参照)

定数

 get_state() は以下の値のいずれかを返します:

cb.CM_STATE_UNKNOWN
 
cb.CM_STATE_RESETTING
 
cb.CM_STATE_UNSUPPORTED
 
cb.CM_STATE_UNAUTHORIZED
 
cb.CM_STATE_POWERED_OFF
 
cb.CM_STATE_POWERED_ON
 

 Characteristicの属性です。(注 これらの値はビットマスクとして組合わせることができます。):

cb.CH_PROP_BROADCAST
 
cb.CH_PROP_READ
 
cb.CH_PROP_WRITE_WITHOUT_RESPONSE
 
cb.CH_PROP_WRITE
 
cb.CH_PROP_NOTIFY
 
cb.CH_PROP_INDICATE
 
cb.CH_PROP_AUTHENTICATED_SIGNED_WRITES
 
cb.CH_PROP_EXTENDED_PROPERTIES
 
cb.CH_PROP_NOTIFY_ENCRYPTION_REQUIRED
 
cb.CH_PROP_INDICATE_ENCRYPTION_REQUIRED

canvas — ベクターグラフィクス

はじめに

 canvas モジュールはiOS上の非インタラクティブな2次元ベクターグラフィクスを生成するための関数群からなっています。シンプルなグラフィックやグラフ、ラインアートに適しています。

 全ての関数はPythonistaの出力画面の一枚のキャンパス上で動作します。この方法で生成される画像は,目下のところプログラムではできませんが、手動で、デバイスのフォトライブラリーに出力するか、クリップボードにコピーすることができます。

 座標系は左下の角を原点とした浮動小数型です。色は一般的には0.0から1.0の範囲の要素からなるRGB(A)で指定します。(注 RGB:赤、緑、青。A:透明度。0に近いほど透明)

 

赤い円を描く最小限の例は以下の通りです:

#画面いっぱいに赤で塗りつぶされた円を書く
import canvas
w = h = 512
canvas.set_size(w, h)
canvas.set_fill_color(1, 0, 0)
canvas.fill_ellipse(0, 0, w, h)

キャンバスの設定

 以下の関数は、キャンバス上の描画設定に使うことができます。一般的には、何を描くにせよ、まずset_size()を呼び出すことになります。

 描画の処理速度を改善したい場合には、描画開始前にbegin_updates()を呼び出し、描画終了後にend_updates() を呼び出すと良いでしょう。これらの関数により、描画の中間段階の表示を省いて処理速度を向上させ、一方で、描画のコーディング作業中は中間段階の結果を確認しやすくすることができます。

canvas.clear()

 canvasをクリアします。なお、全ての描画コマンド(例 変形、塗りつぶしなど)をリセットできるset_size()関数でもcanvasをクリアできます。

canvas.get_size()

 canvasのサイズを幅と高さのタプルの形で返します。

canvas.set_size(widthheight)

 canvasのサイズ(最小で16×16、最大で2048×2048)を設定し、全ての描画コマンド(例 変形、塗りつぶしなど)をリセットします。

canvas.begin_updates()

 描画コマンドのグループの先頭で呼び出します。描画結果はend_updates()を呼び出すまで画面には表示されません。この一連の手続きにより処理速度を著しく改善することができます。

canvas.end_updates()

 画面に表示せずメモリー上でバッファリングされていた描画結果を画面上に表示します。(begin_updates()を参照)

canvas.save_png(filename)

 現在のcanvas上の最新の描画内容をPNGファイルに保存します。

描画のパラメーターの設定

 以下の関数の使用は、全ての描画処理に影響を与えます。例えば、赤を指定してset_fill_color()を呼び出すと、別の色を設定するまで、その後に続くどのfill_rect()でも赤い長方形を描画することになります。

canvas.set_aa_enabled(flag)

 アンチエリアシングのオン/オフ

canvas.set_alpha(alpha)

 描画要素全体の透明度設定

(set_blend_mode()も参照)

canvas.set_blend_mode(mode)

 ブレンドモードの設定。末尾のBlend Modesのリストから一つを選択。

(set_alpha()も参照)

canvas.set_fill_color(rgb[, a])

 塗り潰し色の設定

canvas.set_line_width(width)

 線幅の設定

(set_stroke_color()も参照)

canvas.set_stroke_color(rgb[, a])

 縁取り(輪郭)色の設定

(set_line_width()も参照)

ベクター描画関数

 以下に示す関数はベクター形式のパス(ひと連なりの線や曲線からなる図形)や図形を描画するために使用します。

 canvasには常にadd_から始まる関数で操作できる「現在のパス」があります。add_line()add_curve()などを使って作った任意の複雑なパスを、fill_path()や draw_path()で塗り潰したり描画したりすることができます。線を塗り潰したい場合には、最初にclose_path()で線を閉じてください。パスの塗り潰しや描画をすると、「現在のパス」ではなくなります。

 

 下記の例はいくつかのパラメーターを設定して星の形を書くスクリプトです。

 

#Draw a star
import canvas
from math import sin, cos, pi

def draw_star(x, y, inner_r, outer_r, jags):
  canvas.move_to(w / 2, h / 2 + inner_r)
  for i in range(jags * 2):
    angle = (2 * pi / jags) * i / 2
    r = inner_r if i % 2 == 0 else outer_r
    x = w / 2 + r * sin(angle)
    y = h / 2 + r * cos(angle)
    canvas.add_line(x, y)
  canvas.close_path()
  canvas.set_line_width(3)
  canvas.draw_path()
w = h = 600
jags = 7 #Number of jags
inner_r = 120 #Inner radius
outer_r = 250 #Outer radius
canvas.set_size(w, h)
draw_star(w/2, h/2, inner_r, outer_r, jags)
canvas.add_curve(cp1xcp1ycp2xcp2yxy)

 パス上の現在の位置を始点とし、終点(x,y)との間に、制御点1(cp1x,cp1y)と制御点2(cp2x,cp2y)による3次元ベジェ曲線を追加します。

(begin_path()draw_path()fill_path()も参照)

canvas.add_ellipse(xywidthheight)

 現在のパスに長方形を追加します。

(begin_path()draw_path()fill_path()も参照)

canvas.add_line(xy)

 現在のパスに直線を追加します。

(begin_path()draw_path()fill_path()move_to()も参照)

canvas.add_quad_curve(cpxcpyxy)

 現在のパスの点(x,y)にコントロールポイント(cpx,cpy)による2次元ベジェ曲線を追加します。

(begin_path()draw_path()fill_path()も参照)

canvas.add_rect(xywidthheight)

 現在のパスに長方形を追加します。

(begin_path()draw_path()fill_path()も参照)

canvas.begin_path()

 新しいパスを開始します。add_line()add_rect()などを使用することによって、このパスに図形を加え、draw_path() やfill_path()で実際に描画します。

canvas.clip()

 表示済みの現在のパスに続いて描画される要素を消します。(表示済あらかじめの内容は消さない)

(begin_path()も参照)

canvas.close_path()

 現在のパスを閉じます。(最後の点から最初の点までを直線で結び閉じたパスにします)

(begin_path()draw_path()fill_path()も参照)

canvas.draw_ellipse(xywidthheight)

 パラメーターで指定された長方形の中に楕円を書きます。

(set_stroke_color()set_line_width()も参照)

canvas.draw_line(x1y1x2y2)

 2点を結ぶ直線を描きます。

(set_stroke_color()set_line_width()も参照)

canvas.draw_path()

 指定した線幅と色で、現在のpathを線で描画します。

(begin_path()fill_path()set_stroke_color()set_line_width()も参照)

canvas.draw_rect(xywidthheight)

 長方形を描画します。

(set_stroke_color()set_line_width()も参照)

canvas.fill_ellipse(xywidthheight)

 左下の頂点座標が(x,y)で、幅がwidth、高さがheightの長方形の中に楕円を描き、塗り潰します。

(draw_ellipse()も参照)

canvas.fill_path()

 現在のパスで囲まれた図形を、あらかじめ指定してある色で塗り潰します。

(begin_path()draw_path()set_fill_color()も参照)

canvas.fill_pixel(xy)

 (x,y)にあるピクセルを、あらかじめ指定してある色で塗り潰します。

canvas.fill_rect(xywidthheight)

 左下の頂点座標が(x,y)で、幅がwidth、高さがheightの長方形の領域を塗り潰します。

canvas.move_to(xy)

 「ペン」を点(x,y)へ移動します。

(add_line()も参照)

変形

 以下の変形機能を使うことにより、キャンバス上の「現在の変形マトリクス(Current Transformation Matrix:CTM)」を操作することができます。これは、例えば図形を回転させたり拡大縮小させたりするのに利用できます。キャンバスを変形すると、本質的には、後述する変化を及ぼすように座標系を変化させることになります。

 一時的にのみ変形を適用することが、便利なことがしばしばあります。これは、2つの関数save_gstate() とrestore_gstate()を使えば実現できます。save_gstate()は現在の変形のスナップショットを撮り、そして、(その他のグラフィックの状態を示す、塗り潰し色のようなパラメーターも)後入れ先出しのスタック領域で保存します。スタック領域に最後に保存した内容は、関数restore_gstate()を呼び出すことで復旧することができます。

 画像の状況を保存しないで、変形を完全にリセットしたい場合は、set_size()関数を使うことができます。

 下記は、数字を回転させた時計の文字盤を描画する例です。

# Draw a clock face
import canvas
from math import pi

canvas.set_size(600, 600)
canvas.set_fill_color(0.7, 0.7, 0.7)
canvas.fill_ellipse(0, 0, 600, 600)
canvas.set_fill_color(0, 0, 0)
canvas.fill_ellipse(290, 290, 20, 20)

for i in range(12):
    canvas.save_gstate()
    canvas.translate(300, 300)
    canvas.rotate(-2 * pi / 12.0 * i)
    canvas.set_fill_color(0, 0, 0)
    s = 40
    fnt = 'Helvetica-Bold'
    n = str(12 if i == 0 else i)
    w, h = canvas.get_text_size(n, fnt, s)
    canvas.draw_text(n, -w/2, 240, fnt, s)
    canvas.restore_gstate()
canvas.restore_gstate()

save_gstate()関数で最後に保存した状態を、現在の描画条件として設定します。

canvas.rotate(angle)

現在の変形マトリックスに回転を加えます。

(save_gstate()restore_gstate()も参照)

canvas.save_gstate()

 描画条件のスタック領域に、現在の描画条件(変形、選択色など)のコピーを保存します。

(restore_gstate()も参照)

canvas.scale(sxsy)

 現在の変形マトリックスに拡大縮小倍率(x軸方向にsx倍、y軸方向にsy倍)を設定します。

(save_gstate()restore_gstate()も参照)

canvas.translate(txty)

 現在の変形マトリックスの原点を(tx,ty)に設定します。

(save_gstate()restore_gstate()も参照)

ビットマップ画像の描画

 そもそもはベクターグラフィクスのためにデザインされたcanvasモジュールですが、sceneモジュールと同様の、ビットマップ描画のための関数もいくつかあります。名前の付けられた画像やクリップボードに保管されている現在のコンテンツを描画することができます。

 

canvas.draw_image(image_namexy[, widthheight])

 名前の付けられた画像を、(x,y)を左下にし、幅width、高さheightの長方形の中に描画します。

widthやheightを省略した場合には、イメージは元のサイズで描画されます。

canvas.draw_clipboard(xywidthheight)

 クリップボードに保管されている画像を、(x,y)を左下にし、幅width、高さheightの長方形の中に描画します。

canvas.get_clipboard_size()

 クリップボードに保管されている画像のサイズをポイント単位で、幅と高さのタプルの形で返します。ラティナディスプレイでは、2ピクセルを1ポイントとしてカウントします。クリップボードが空の場合には、(0,0)を返します。

canvas.get_image_size(image_name)

 名前がつけられている画像のサイズをポイント単位で、幅と高さのタプルの形で返します。ラティナディスプレイでは、2ピクセルを1ポイントとしてカウントします。名前に該当する画像がない場合には、(0,0)を返します。

文字の描画

 canvasモジュールには文字の描画とサイズを測る2つの簡便な関数があります。

 draw_text()で描画される文字の色は、前もって呼び出したset_fill_color()によって決まります。

 

canvas.draw_text(textxyfont_name='Helvetica'font_size=16.0)

 1行分のテキストを点(x,y)を左下端とする行として描画します。

canvas.get_text_size(textfont_name='Helvetica'font_size=16.0)

 draw_text()関数で描画した場合と同じように、文字の行のサイズを幅と高さのタプルの形式で返します。

ブレンド・モード

 set_blend_mode()では、以下のブレンド・モードを使用することができます。

canvas.BLEND_NORMAL
canvas.BLEND_MULTIPLY
canvas.BLEND_DIFFERENCE
canvas.BLEND_SCREEN
canvas.BLEND_OVERLAY
canvas.BLEND_DARKEN
canvas.BLEND_LIGHTEN
canvas.BLEND_COLOR_DODGE
canvas.BLEND_COLOR_BURN
canvas.BLEND_SOFT_LIGHT
canvas.BLEND_HARD_LIGHT
canvas.BLEND_DIFFERENCE
canvas.BLEND_EXCLUSION
canvas.BLEND_HUE
canvas.BLEND_SATURATION
canvas.BLEND_COLOR
canvas.BLEND_LUMINOSITY
canvas.BLEND_CLEAR
canvas.BLEND_COPY
canvas.BLEND_SOURCE_IN
canvas.BLEND_SOURCE_OUT
canvas.BLEND_SOURCE_ATOP
canvas.BLEND_DESTINATION_OVER
canvas.BLEND_DESTINATION_ATOP
canvas.BLEND_XOR
canvas.BLEND_PLUS_DARKER
canvas.BLEND_PLUS_LIGHTER

appex — Pythonista用「アプリ・エクステンション」ユーティリティー

 appexモジュールは、iOS上の他のアプリ中でPythonスクリプトを使用できるよう、Pythonistaから「アプリ・エクステンション」で共有する機能を提供します。

Pythonista 3は、このモジュールで、シェア・エクステンションと、ウィジットの2種類の「アプリ・エクステンション」の方法を提供します。

シェア・エクステンション

( Pythonista Shortcuts / Share Extension もご覧下さい)

 

 Pythonistaのシェア・エクステンションは、一般的なiOSシェアシートを介して、他のアプリからのデータの処理をすることが可能です。

 最初に使う際には、シェア拡張をサポートしているアプリ(例えばSafari)からシェアシートを呼び出す必要があります。シェアシートの「More...」(iOS12以前)又は「Edit Actions...」(iOS13以降)をタップし、「Run Pythonista Script」を起動して下さい。この手続きは一回だけ行えば、その後は、「Run Pythonista Script」が自動的に表示されるようになります。

 アクティベートした後は、シェアシートを使えるどのアプリからも「Mini Pythonista」を呼び出すことが可能になります。シェア・エクステンションは、対話形式のコンソールと基本的なスクリプトエディタを含んでいるほか、お好みのスクリプトを素早く実行するためのショートカット・アイコンを追加することができます。

 アプリがシェアシートを使っている時は、通常、何らかのデータを「Mini Pythonista」に渡しています。例えば、Safariの開いていたページのURLとか、Notesのテキストデータとか、Photosの映像データなどです。このモジュールの関数を使って、それらのデータにアクセスしたり処理したりすることができます。関数の例としてはappex.get_url()appex.get_text()などがあります。

 シェア・エクステンションでスクリプトを実行する際には、以下にご注意下さい。:

  • ui.Viewを表示している場合(ui.View.present()を使って表示している場合)には、表示形式は無視されます。iPhoneでは、表示は常に「full-screen」モードですが、iPadの場合は、アプリ・エクステンションの主画面を覆い隠してしまうため、「full-screen」モードは使えません。
  • いくつかの関数、最も重要なものではwebbrowser.open()はシェア・エクステンションのスクリプトでは実行できません。notificationモジュールも実行不可です。
  • カメラはアプリ・エクステンションを使えないので、photos.capture_image() は動作しません。

トゥディ・ウィジット

 トゥディ・ウィジットは、プルダウンした通知センター(の中のTodayタブ)や、ホーム画面の最初のページから、又はロック画面を右側にスワイプすることで、iOSのどこからも素早くアクセスして単独のスクリプトを実行することができます。

 トゥディ・ウィジットをアクティベートするには、「Today画面」の編集ボタンをタップして、Pythonistaウィジットを選ぶ必要があります。また、Pythonistaの設定でウィジットで実行するスクリプトを選ぶ必要があります。手始めに、Examples/Widgetフォルダにあるスクリプトから一つを試して見ると良いでしょう。

(注 トゥディ・ウィジットはiOS10以降のみの機能で、Python 3でのみサポートしています)

 

 選んだスクリプトは、ウィジットが表示されている時にはいつでも実行可能です。一般的に、ウィジットでは、uiモジュールで生成された)シンプルなユーザーインターフェイスを表示するためにset_widget_view()関数が使われます。

 シェア・エクステンションと比べて、トゥディ・ウィジットでできる事は限定的です。Pythonistaの APIのサブセットだけが実行可能で、メインアプリやシェア・エクステンションに比べてはるかに少ないメモリー領域しか使えません。

 

トゥデイ・ウィジットでスクリプトを実行する際には、特に以下に留意する必要があります:

(警告 ウィジットの記憶領域はとても限られています。もし、メインアプリで動作するスクリプトであっても、ウィジットでは「読み込めません」というメッセージを眼にすること(又はウィジットが空になっていること)があります。その場合、スクリプトが大量の記憶領域を消費して、システムから強制終了されているのです。この現象が発生した場合には、デバイスの再起動を試してみて下さい。)

  • dialogsconsole.alert()などにある全てのダイアローグは使用できません。
  • ui.View.present()メソッドは使用できません。ウィジットでユーザーインターフェイスを表示するには、set_widget_view()関数を使う必要があります。
  • ウィジットの動作が止まってしまった場合、2本の指で3秒間タップしてそのままホールドすると実行を終了させることができます。

関数

appex.is_running_extension()

 アプリ・エクステンション(シェア・エクステンション又はウィジット)中でスクリプトが動作している場合、Trueを返します。その他の場合はFalseを返します。

 メインアプリ上でスクリプトを試してみたい場合、例えば、この関数を使いシェア・シートの入力の代わりにダミーデータを読み込ませることができます。

appex.is_widget()

 スクリプトがトゥデイ・ウィジットで動作している場合、Trueを返します。その他の場合はFalseを返します。

appex.finish(js=None)

 シェア・シート・エクステンションを終了させます。省略可能なパラメーターであるjsは、Safariでのエクステンションの時だけ意味を持ちます。Pythonistaシートが閉じられた後、見ていたウェブページのコンテンツの中で実行されるジャバスクリプトコードを指定します。この関数はメインアプリで呼び出される場合には意味を持ちません。

appex.get_attachments(uti='public.data')

 与えられたタイプの識別子に該当する添付のリストを返します。多くの場合、get_image()get_url()のようなタイプが固定された関数を使用するよりもずっと簡単に使えます。

appex.get_images(image_type='pil')

 シェア・シートに入力された画像のリストを返します。image_typeには、‘ui’又は‘pil’が選べます。‘ui’の場合、ui.Imageインスタンスが、それ以外の場合、PIL(Pythonイメージライブラリー)の画像が返されます。入力に画像がない場合、空のリストが返されます。

appex.get_image(image_type='pil)

 シェア・シートに入力された最初の画像を返します。image_typeには、‘ui’又は‘pil’が選べます。‘ui’の場合、ui.Imageインスタンスが、それ以外の場合、PIL(Pythonイメージライブラリー)の画像が返されます。入力に画像がない場合、空のリストが返されます。

appex.get_image_data()

 シェア・シートに入力された最初の画像の生画像データを返します。このデータはバイト列として返されます。入力に画像がない場合、None値を返します。

appex.get_images_data()

 シェア・シートに入力された全ての画像の生画像データを返します。このデータはバイト列として返されます。入力に画像がない場合、空のリストを返します。

appex.get_text()

 シェア・シートの文字列入力をユニコード列として返します。入力に文字列がない場合、None値を返します。

appex.get_urls()

 シェア・シートに入力されたURLのリストを返します。URLの入力がない場合には、空のリストを返します。

appex.get_url()

 シェア・シートに入力されたURLを返します。URLの入力がない場合には、None値を返します。

appex.get_file_paths()

 シェア・シートに入力されたファイルパスのリストを返します。ファイルパスがない場合には、空のリストを返します。

appex.get_file_path()

 シェア・シートに入力されたファイルパスを返します。ファイルパスがない場合には、None値を返します。

appex.get_vcards()

 シェア・シートに入力されたVCardレコードのリストを返します。各レコードは文字列として記述されます。入力にVcardがない場合には、空のリストを返します。

appex.get_vcard()

 シェア・シートに入力された最初のVCardレコードを返します。レコードは文字列として記述されます。入力にVcardがない場合には、None値を返します。

appex.get_web_page_info()

 Safariでシェア・シートを呼び出した場合、現在読み込んでいるページの情報を返します。返す値は辞書型で、普通は以下の内容を含んでいます。(全て、ユニコード文字列です):

  • 'url': ページのフルURL(document.URL) – もし、この値だけが必要な場合、代わりに get_url() (他のアプリでも動作可能)を使うことができます。
  • 'title': ページのタイトル(document.title)
  • 'html': ページのHTMLソースコード – このソースコードはdocument.documentElement.outerHTMLから生成されており、必ずしもサーバーから読み込まれたものと正確に同一とは限らないことに注意して下さい。(例えば、ジャバスクリプト経由のDOM(ドキュメントオブジェクトモデル)マニピュレーションなど)
  • 'selection_html': 選択したテキスト (HTMLフォーマットや、保存用書式、リンクなど)
  • 'selection_text': 選択したテキスト(プレーンテキストとして)
  • 'cookie': document.cookieの値
  • 'referrer': document.referrerの値

 欠けている値は空の文字列で表現されます。

 シェア・シートがSafari以外のアプリから表示された場合、又は現在のページの情報が呼び出せない場合には、空の辞書型を返します。

appex.get_widget_view()

 トゥディ・ウィジットに現在表示されているビュー形式を返します。(set_widget_view()によりセットされたビュー形式がない場合にはNoneを返します。)

appex.set_widget_view(view)

 ウィジットのビュー形式をui.Viewオブジェクトとして設定します。ビュー形式は自動的にウィジット全体を覆うようにサイズ調整され、ビューの現在の高さは、“Show More”ボタンをタップした時の、ウィジットの拡張された高さとして使用されます。ビューの高さが120以下の場合、ウィジットには“Shore More”ボタンは表示されず、コンパクトなウィジットディスプレイモードが使用されます。

 ビューオブジェクトの代わりにNoneを渡せば、ウィジットから現在のビューを消すことができます。このスクリプトをメインアプリ中で実行した場合には、ウィジットビューがシミュレーションして表示されます。

 iPhoneやiPadで動作するプログラミング言語Pythonの環境であるPythonista3について、標準的なPythonのコマンドについては、日本語化プロジェクトがありますが、iOSやiPadOS特有のコマンドの日本語版マニュアルについては、現在までのところ見つけられていません。

 なければ作ってしまえ、ということで、以下に作ってみます。

 

Pythonistaのモジュール

 以下のモジュールはiOS特有の機能を提供する目的でPythonistaに搭載されています。

その他の情報

サードパーティ製モジュール

 以下の、一般的に良く使われているサードパーティ製のモジュールについてもPythonistaで使用可能です。Pythonの標準ライブラリには入っていませんが、iOS

特有という訳でもありません。

ドキュメントなしのモジュール

 以下のサードパーティ製モジュールについてはPythonistaで使えますが、現在のところ、アプリ内にフルドキュメントを用意していません。

 以下には、簡単な記述と詳細な情報へのリンクを示します。