Casio Python - テキスト出力関数の追加

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     - テキスト出力関数の追加:locate() をユーザーモジュールに累加 
目次


初版:2020/07/13
追記修正:2020/11/03
前の記事 - 6. グラフィックス出力関数の追加 |  次の記事 - 8. シェル画面入力の工夫


fx-CG50 OS3.40 以降専用


7. テキスト出力関数の追加:locate() をユーザーモジュール に追加

Casio Python の現在の言語仕様では、Casio Basic で作った実用プログラムを完全に移植できないレベルの貧弱な仕様で、発展途上と言えます。Casio Basic で実用プログラムが作れる最大の要因は、望む位置に数値や文字列を出力できる Locate コマンドと電卓のほぼ全てのキー入力を取得可能な Getkey コマンドの存在です。一方 Casio Python には LocateGetkey に相当するものがありません。Getky 相当の機能は、カシオによる OSアップデートを待つしかありませんが、Locae 相当の関数は自作できます。

casioplot モジュールには draw_string() 関数があり、グラフィックス画面(描画画面) にアスキー文字(列)を好みの位置に出力できます。但し、その出力位置は、文字列の最初の文字の左上のピクセルの座標で指定する必要があり、ちょっと面倒です。

さて、fx-CG50 のマニュアルにある draw_string() の説明は下記の通りです。 
draw_string_manual 

グラフィックス画面のピクセル座標で位置指定する代わりに、Casio BasicLocateコマンドのように、文字や数値を文字の大きさに併せて桁と行で指定できる locate() 関数を作ろうと思います。


7.1 locate() 関数の作成

具体的には、以下の仕様にします;
locate(column, row, obj, color=1, size='m', show=1)
  • column: 出力開始桁 (横方向)、0から始まる整数
  • row: 出力行 (縦方向)、0から始まる整数
  • obj: 出力する数値や文字、文字列
  • color: 省略すればデフォルトの黒、grp_color(color) (ココを参照) を利用
  • size: 's', 'm', 'l' と1文字の文字列でサイズを指定 (入力が楽)
  • show: VRAMからグラフィックス画面への出力指定、デフォルトの1で出力、0で出力しない 
この関数内では、最終的に casioplot で提供されている draw_string() で出力します。
draw_string() は、第三引数で色を指定可能(省略時のデフォルトは黒)、第四引数で文字サイズ 'small', 'midium', 'large' のいずれかを指定可能(省略時のデフォルトは 'midium') となっています。これを locate() 関数でフル活用します。

以下がこれから作る locate() 関数の骨格です。

def locate(column, row, obj, color=1, size='m', show=1):
 #1) column から x を算出
 #2) row から y を算出
 #3) size から draw_string() が受け取れる sz ('small', 'medium', 'large' のどれか) に変換

 draw_string(x, y, str(obj), grp_color(color), sz)
 if show:
  show_screen()


#1), #2), #3) を具体的に書けば、locate() 関数の完成となります。


7.1.1 フォントピッチ dx, dy の設定

draw_string() で文字をグラフィックス画面に出力する際には、文字フォントの左上の座標 (x, y) を指定します。
左上座標 (x, y) にある文字の右隣の文字は (x + dx, y) の位置、直下の文字は (x, y + dy) の位置にフォントを描画することになります。
draw_string() では大、中、小と3つの異なるサイズの文字を出力できるので、それぞれサイズのフォントごとにフォントピッチ dx と dy を決めてやれば、フォントの出力位置を桁と行に置き換えることができます。

ある程度の試行錯誤の結果、以下のような収まりの良い結果が得られました。

'small' フォント
dx (x ピッチ):8
dy (y ピッチ):12
横方向の最大桁数 (1行の文字数):48
縦方向の最大行数 (1列の文字数):16
small_font 
'small' フォントでは、dx=8dy=12 とすれば、1画面に 48桁×16行 の文字がうまく収まります。

'midium' フォント
dx (x ピッチ):12
dy (y ピッチ):16
横方向の最大桁数 (1行の文字数):32
縦方向の最大行数 (1列の文字数):12
midium_font 
'midium' フォントでは、dx=12dy=16 にすれば、1画面に 32桁×12行でうまく収まります。

'large' フォント
dx (x ピッチ):16
dy (y ピッチ):24
横方向の最大桁数 (1行の文字数):24
縦方向の最大行数 (1列の文字数):8
large_font 
'large' フォントでは、dx=16dy=24 とすれば、1画面に 24桁×8行で旨く収まります。
これは、シェル画面での桁数と行数と同じです。

ちなみに、上記の出力と条件は locate.py を使って、試行錯誤して得ました。
locate.py のダウンロード

スクリプト内の #small font#midium font#large font とあるそれぞれのセクションのうち、2つをコメントアウトし、コメントを外したフォントサイズで、それぞれ出力したのが、上記の出力画面です。


7.1.2 column から x を、row から y を算出

locate(column, row, obj, color=1, size='m', show=1) 関数の size 引数で指定される 's', 'm', 'l' から、出力位置を示すフォントの左上の座標を算出します。

上の検討から、各フォントサイズの応じたフォントピッチ dxdy を決めました。

size と dx の関係
key's''m''l'
value81216

locate() の引数 size (= 's' or 'm' or 'l') に対応する dx は、この表の通りです。
この関係を使えば、size から dx を得るのに if文で簡単に記述できます。今回は、Casio Pyton の辞書型(dict型) シーケンスを利用して、簡潔な記述を試みます。

辞書型 (dict型) は、シーケンス型の一種で、要素を コンマ , で区切って列挙します。辞書型の要素は、keyvalue をコロン : で区切って、key:value のように記述したものです。さらに辞書型は、複数の key:value  (要素)を コンマ , 句切りで列挙したものを波括弧 { } で囲んで定義します。上の sizedx の関係を 辞書型オブジェクト dx とすると、dx は以下のように定義できます。

dx = {'s':8, 'm':12, 'l':16}

そして、dx[size] と記述すると、key の 's', 'm', 'l' に対応した value は、それぞれ 8, 12, 16 になります。辞書の見出し語 's' を探すと、そこには 8 という説明があるという感覚です。このように key に関連づけられた値 value を簡単に得られるのが、辞書型の便利なところです。何行にもわたる if文を書く代わりに、上の1行の定義を行うだけで、欲しい value の値は dx[size] で得られるわけです。

さて、draw_strring() の第一引数 x は、フォントの左上の x 座標です。locate() の第一引数 column を使えば、

x = column*dx[size]

のようにして、求める x 座標が得られます。ここで、column は 0 から始まる整数です。

同様にして、sizedy の関係を 辞書型オブジェクト dy で定義し、フォントの右上の y 座標を求めます。

size と dy の関係
key's''m''l'
value121624

dy = {'s':12, 'm':16, 'l':24}

と定義すれば、key に対応した値は、dy[size] で得られます。すると、locate() の第二引数 row を用いて、y 座標は以下のようになります。row は、0 から始まる整数です。

y = row*dy[size]

従って、draw_string() 関数の第一引数と第二引数は、上記の xy を使えます。あるいは変数 x, y を用いずに、以下のょうに引数として、式を直接書いても問題ありません。

draw_string(column*dx[size], row*dy[size], str(obj), grp_color(color), sz)


7.1.3 フォントサイズ指定の処理

draw_string() の最後の引数 sz を、locate() 関数の 引数 size (= 's' or 'm' or 'l') からどうやって得るかを考えます。
この引数は、draw_string() の引数 ('small' or 'midium' or 'large')と同じ設定にすれば良いのでしょうが、電卓での文字入力が面倒なので、できるだけ文字数を減らしたいと考えて、1文字で指定するように決めたので、1文字から文字列へ変換が必要になります。

size と sz の関係
key's''m''l'
value'small''midium''large'

実は、これも辞書型オブジェクトで簡単に処理できます。

sz = {'s':'small', 'm':'midium', 'l':'large'}

と定義すれば、sz[size] が求めたい文字列を与えます。

これで、draw_string() の全ての引数が決まりました。

draw_string(column*dx[size], row*dy[size], str(obj), grp_color(color), sz[size])


7.1.4 locate() の完成

これまでの検討をまとめて、完成した locate() の定義を以下に示します。

from casioplot import *
from u import *

def
locate(column, row, obj, color=1, size='m', show=1):
 # set fontsize & pitch
 dx = {'s':8, 'm':12, 'l':16}
 dy = {'s':12, 'm':16, 'l':24}
 sz = {'s':'small', 'm':'midium', 'l':'large'}

 #data transfer to VRAM
 draw_string(column*dx[size], row*dy[size], str(obj), grp_color(color), sz[size])

 if show: #data transfer to screen
  show_screen
()


意外にシンプルな関数定義になりました。


7.2 locate() をユーザーモジュールに追加

前回作ったユーザーモジュール u.py ver 1.2 に今回作った locate() の定義をを追加して、ver 1.3 とします。

ユーザーモジュール ver 1.3 - u.py のダウンロード


7.3 locate() の動作確認 - ckLocate.py

ckLocate.py のダウンロード

ckLocate.py は、シェル画面で必要な入力を行い、その後グラフィックス画面に出力する構造にしています。

シェル画面では、大、中、小の3通りにフォントサイズから1つを選択させます。この入力処理は、while 1: で無限ループにしており、[1][2][3] キーを押したときだけそのメニュー番号を取得して break でループを抜けます。それ以外のキーを押した時は、その入力を無視して continuewhile ループを回り続けます。シェル画面で入力を行う良いサンプルになっていると思いますので、参考にしてください。

入力により変数 m に 0, 1, 2 のいずれかの値が入ります。この m をリストのインデックスとして使います。
リストは、col_rangerow_range, size の3つあり、インデックス 0  は 'small' フォントに関する値、インデックス 1 は 'midium' フォントに関する値、インデックス 2 は 'large' フォントに関する値にしています。

そして、col_range[m]row_range[m] は、2つの for 文の反復回数を決める range() の引数に使い、size[m]locate() 関数で指定するフォントサイズとして 's', 'm', 'l' のいずれかの文字を与えます。

locate() を反復実行して、0 から 9 までの数字で順に画面を埋め尽くし、同時にカラーコード 1 から 7 までを順に繰り返し指定するようにしています。詳しくは、以下のスクリプトをご覧下さい。

from u import *

num_str '1234567890'
0

while 1:
 print('Text Drawing Test')
 print()
 print('1:small font')
 print('2:medium font')
 print('3:large font')
 print()
 inp input('Input menu #:')
 if inp.isdigit():
  m int(inp)
  m -= 1
  if not(0<=m<=2):
   continue
  else:
   break
 else:
  continue

col_range [483224]
row_range [16128]
size ['s''m''l']

clear_screen()
for j in range(row_range[m]):
 k j
 k %= 10
 for i in range(col_range[m]):
  locate(ijnum_str[k], (i+j)%7+1size[m])
  k += 1
  k %= 
10



このスクリプトを実行すると、シェル画面に以下のように出力されます。
ckLocate_in 

[1] ~ [3] 以外のキーを押してから、[EXE] を押すと無視され、再びこの画面が表示されます。

[1] + [EXE} を押せば、small フォントで埋め尽くされます。
ckLocate_1_in ckLocate_1_out 

グラフィックス画面に出力された後、[EXIT] を押せば、スクリプトを実行させた時の画面に戻ります。

[2] + [EXE] を押せば、midium フォントで埋め尽くされます。
ckLocate_2_in ckLocate_2_out 

[3] + [EXE] を押せば、large フォントで埋め尽くされます。
ckLocate_3_in ckLocate_3_out 


7.4 モンテカルロ法(3) - monteca3.py

以前作成したモンテカルロ法(2) - monteca2.py は、スクリプト内に grp_color() 関数 と circle() 関数の定義を記述しました。これらの関数定義に加えて今回作った locate() 関数の定義も、アップデートした ユーザーモジュール u.py ver 1.3 に含めました。そこで、以前作ったモンテカルロ法(2) - monteca2.py を修正して、ユーザーモジュール - u.py ver 1.3 を呼び出して使うようにして、スクリプトファイル名を monteca3.py とします。 汎用のユーザーモジュールを使うことで、スクリプトがとてもスッキリしました。

モンテカルロ法(3) - monteca3.py のダウンロード

"""Sample script

Exercise;
porting from Casio Basic
"Monte Carlo Method"
ver 3.0

by Krtyski/e-Gadget
"""

from random import *
from u import
*

#initializing
n_try 500
ins 0outs 0
prev_outs 0
prev_pai 0
90 #radius
dx 290dy 96 #center

#dislay menu to select try#
while 1:
 print('\nMonte Carlo: calc Pi')
 print('\n# of try:' + str(n_try))
 print('[EXE] to start.')
 temp_try = input('\nChange the #?:')
 if temp_try.isdigit():
  n_try = int(temp_try)
  break
 elif temp_try == '':
  break
 else:
  continue

#display graphics
clear_screen()
circle(290, 96, 90, 'red') #red circle
locate(1, 0, 'C=')
locate(0, 1, 'pi=')
locate(0, 10, '# of try:' + str(n_try))
locate(0, 11, 'AC:Quit')

while outs<n_try
:

 x = 1 - 2*random()
 y = 1 - 2*random()
 set_pixel(int(dx+r*x), int(dy+r*y), grp_color('blue')) #blue plots
 if (x**2+y**2)<1:
  ins+=1
 outs+=1
 locate(3, 0, str(prev_outs), color=0, show=0)
 locate(3, 1, str(prev_pai), color=0, show=0)
 pai = round(4*ins/outs, 11)
 prev_outs = outs
 prev_pai = pai
 locate(3, 0, str(outs), show=0)
 locate(3, 1, str(pai))

locate(0, 11, 'AC:Quit', color=0)
locate(0, 11, 'Finish=>[EXIT]'
)



draw_string()locate() に置き換えられました。locate() の引数に color=0show=0 と書いていますが、この2つは単に 0 と記述しても問題ありません。但し、明示的に白で出力することを示すため color=0 としました。また、VRAMから画面へのデータ転送を行わない場合は、これを明示的に示すために show=0 としました。show パラメータ (引数) を省略すれば、デフォルトの show=1 となり、VRAMから画面へ出力します。

実行した結果のグラフィックス画面への出力は monteca2.py と同じです (当然ではあります)。

monteca2 




目 次

前の記事 - 6. グラフィックス出力関数の追加

次の記事 - 8. シェル画面入力の工夫





応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラム関数電卓

リンク集 | ブログ内マップ


関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

コメントの投稿

非公開コメント

最新記事
検索フォーム
最新コメント
カテゴリ
C# (3)
Visitors
Online Counter
現在の閲覧者数:
プロフィール

やす (Krtyski)

Author:やす (Krtyski)
since Oct 30, 2013


プログラム電卓は、プログラムを作って、使ってナンボ!

プログラム電卓を実際に使って気づいたこと、自作プログラム、電卓での Casio Basic や Casio Python プログラミングについて書いています。

なお管理人はカシオ計算機の関係者ではなく、Casio Basicが面白いと感じる1ユーザーです。


写真: 「4駆で泥んこ遊び@オックスフォード郊外」

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

ブロとも申請フォーム

この人とブロともになる

QRコード
QR