🐈‍⬛

Python + Kivy で作ってみた【Ⅰ】

2023/06/21に公開

UI構成

お試しだから凝ってもしょうがないので…

  • ヘッダー
  • 表示部
  • フッター

の単純構成
それぞれにkivyのwidgetクラスを割りあて、
全体のkivyのwidgetクラス(CtrlPanelWidget)にぶら下げる

CtrlPanelWidget
├─HeaderWidget
├─ViewAreaWidget
└─FooterWidget

ヘッダーにはファイル名を表示、フッターには終了ボタンを置く予定
なお、各部の高さは1:8:1とした

PDFの表示

PDFを表示するにはどうするか…
PDF ⇒ Imageに変換できれば話は早いが、できるのか?
Googl先生にお伺いを立ててみると
Pythonでpdf2imageを使用しPDFファイルを画像に変換する
というブログ記事のご神託をいただいた

popplerというライブラリーをWindowsにインストールしないといけないのは気になるが、記事を参考にしてPDF変換モジュールを作っていく

from kivy.graphics.texture  import Texture
from pypdf                  import PdfReader
from pdf2image.pdf2image    import convert_from_path

def pdf_to_texture( filepath, p_dpi = 200 ) :
    with open( filepath, 'rb' ) as f :
        objPdf = PdfReader( f )
        countPdf = len( objPdf.pages )
        print( countPdf )

    pages = convert_from_path( filepath, last_page=1, poppler_path='C:\\poppler\\bin', dpi=p_dpi )
    img = pages[ 0 ]
       
    texture = Texture.create( size=img.size )
    
    texture.blit_buffer( img.tobytes(), colorfmt='rgb' )
    texture.flip_vertical()

    return texture

引数はPDFファイル名と解像度(これは後付け)
返値はkivy.graphics.textureオブジェクトとした

当初の予定ではkivyのImageに表示させるつもりだったが、
Widgetのcanvasのtextureに設定しても画像が表示できるため、
kivy.graphics.textureオブジェクトを返すようにした

モジュール中の「texture.flip_vertical」は、
画像(texture)を上下反転させている
これは、kivyの座標系が左下が原点となっているため
textureは上下反対の状態で生成されてしまうから

ひとまず完成とするが、popplerはなんとかしたい…

Widgetへpythonから画像設定

ViewAreaWidgetにPDFの画像を表示させる
まず、UIを記述するkvファイルには

ViewAreaWidget:
    canvas:
    Rectangle:
        texture:        self.image_texture

と記述する

それに対応するpythonのコード部は

from lib.library            import pdf_to_texture

class ViewAreaWidget( Widget ) :
    image_texture   = ObjectProperty( None )

    def on_kv_post( self, base_widget ) :
        self.image_texture = pdf_to_texture( self.filename )

と記述する

ViewAreaWidgetにimage_textureというオブジェクトプロパティを設定する
on_kv_postはViewAreaWidgetがインスタンス化されたタイミングで呼ばれる
そのタイミングでPDFの画像(kivy.graphics.textureオブジェクト)を設定する

これで実行すると、ViewAreaWidget内に収まるようにPDFが表示される
表示領域より大きければ縮小、反対に小さければそのままの大きさとなる
常にそのままの大きさで表示させるにはどうしたらよいか…

ViewAreaWidgetのcanvasのRectangleの大きさを
textureの大きさに設定すればいいのではないか?
と考えて、次のように変更した

ViewAreaWidget:
    canvas:
    Rectangle:
        texture:        self.image_texture
        size:           self.image_width, self.image_height
from lib.library            import pdf_to_texture

class ViewAreaWidget( Widget ) :
    image_texture   = ObjectProperty( None )
    image_width     = NumericProperty( 0 )
    image_height    = NumericProperty( 0 )

    def on_kv_post( self, base_widget ) :
        di_texture = pdf_to_texture( self.filename )
        self.image_width    = di_texture.width
        self.image_height   = di_texture.height
        self.image_texture  = di_texture

image_width、image_heightという画像サイズのプロパティを追加した

これで実行すると、そのままの大きさで表示されるようにはなった
しかし、

  1. 位置が正しくない
  2. 画像がヘッダー部にはみ出して表示される

という問題が生じた
1の問題は位置を指定すれば良さそうだが、2の問題は見当がつかない


しばらく考えることにするので、今回はここまで

Discussion