【Python×Kivy】Kinoppy(紀伊国屋書店アプリ)を真似してみた

  • URLをコピーしました!

本記事は [個人開発 Advent Calendar 2019]の14日目の記事です。

Python×Kivyというフレームワークを使用して、Windowsアプリを作成しています。

背景

  1. 紙本を自炊してPDFにした。スッキリ!
  2. さぁ、iPadで読もう
  3. 子供にiPad取られた・・・
  4. Surface買った!さぁ、Surfaceで読もう
  5. iPadと違ってWindows用の良いアプリ無いな
  6. Kinoppy(紀伊国屋書店アプリ)良いね!
  7. これ今勉強中のKivyで作れるかな。

Kinoppy(紀伊国屋書店アプリ)はとても良いアプリで、おすすめです。

アプリ概要

本棚とPDFビューワ機能を持っています。
pdfapp2-min.gif

開発環境

AnacondaNavigator
VSCode
Python3.7
Kivy1.11

使用ライブラリ等

他人に頼りすぎて沢山ありますが、メインで使用しているものは以下です。
PDFレンダリング:pdf2image (https://github.com/Belval/pdf2image)
設定ファイル:ruamel.yaml
アイコンフォント:iconfonts (https://github.com/kivy-garden/garden.iconfonts)

大変お世話になったサイト

Kinoppy (https://k-kinoppy.jp/)
Kivy (https://kivy.org/)
stackoverflow (https://stackoverflow.com/)
荒川光線ブログ 本館 (https://koh-sen.jp/)
そして
Qiita:Kivy (https://qiita.com/tags/kivy)

Todo

結構奥が深くて志半ばですが、以下を目指してます。遠い。。

  • ★済★ PDF読込(ローカルPC)
  • ☆未☆ PDF読込(DropBox)
  • ★済★ 本棚管理(本棚追加&削除)
  • ★済★ D&Dで本の移動(本棚内)
  • ☆未☆ D&Dで本の移動(別の本棚)
  • ★済★ ビューワ機能(1or2ページ表示、右or左開き指定)
  • ☆未☆ ビューワ機能(自動目次作成)
  • ☆未☆ ビューワ機能(検索)

ソースコード他

以下のKivyのソースコードを2つ抜粋して紹介します。

  1. Scatterによるサムネイルのドラッグアンドドロップ
  2. Sleiderの右→左の実現
  3. (おまけ)本棚の作り方

①Scatterによるサムネイルのドラッグアンドドロップ

サムネイル(本棚に表示される画像)を何秒か掴んだらドラッグアンドドロップします、という事で、画像枠に色を付けます。もしドラッグアンドドロップに入る前に離したら、普通のクリックと見なしてビューワに遷移します。

<DraggableThumbnail@Scatter>:
image_name: ''
image_path: ''
image: image_id
shelf_row: None
shelf_col: None
do_rotation: False
do_scale: False
auto_bring_to_front: True
do_collide_after_children: True
background_color: 0,0,0,0
background_normal: ''
Image:
id: image_id
source: root.image_path
allow_stretch:True
keep_ratio: True
canvas:
Color:
rgb: (1, 1, 1)
Rectangle:
texture: self.texture
pos: self.pos
size: self.size
view raw Library.kv hosted with ❤ by GitHub

class DraggableThumbnail(Scatter):
image_name = StringProperty(None)
image_path = StringProperty(None)
shelf_row = NumericProperty(None)
shelf_col = NumericProperty(None)
state = OptionProperty('released',options=['grabed','released'])
img_touched = StringProperty(None)
t = NumericProperty(0)
def __init__(self,**kwargs):
super(DraggableThumbnail,self).__init__(**kwargs)
Clock.schedule_once(self.drag_after_init)
# self.bind(size=self.update_canvas)
def drag_after_init(self, dt):
# print('DraggableThumbnail drag_after_init 1 : %s'% self.image.size)
self.size_hint = None,None
self.size = self.image.size
# print('DraggableThumbnail drag_after_init 2 : %s'% self.size)
with self.canvas:
self.color = Color(rgba = (1,1,1,0))
self.frame = Line(rectangle=(0,0,self.image.width,self.image.height))
def on_state(self,*args):
if self.state == 'grabed':
self.color.rgba = (0.5,0.5,0.5,1)
elif self.state == 'released':
self.color.rgba = (1,1,1,0)
def time_count(self,*args):
self.t += 0.1
def on_t(self,*args):
if self.t >=0.5:
Clock.unschedule(self.time_count)
self.t = 0
self.state = 'grabed'
self.img_touched = ''
def on_touch_down(self, touch):
self.on_state(touch)
if self.collide_point(*touch.pos):
Clock.schedule_interval(self.time_count, 0.1)
self.img_touched = self.image_name
print('DraggableThumbnail on_touch_down: %s' % self.img_touched)
# if the touch collides with our widget, let's grab it
touch.grab(self)
# and accept the touch.
return True
def on_touch_up(self, touch):
Clock.unschedule(self.time_count)
self.t = 0
# you just need to check if it's a grabbed touch event
if touch.grab_current is self:
print('DraggableThumbnail on_touch_up : %s' % self.image_name)
if self.img_touched == self.image_name:
self.img_touched = ''
if self.state == 'released':
app= App.get_running_app()
app.root.chgdisp_viewer(self.image_name)
else:
print('DraggableThumbnail set_thumbnail')
app= App.get_running_app()
app.root.Library.lineup_thumbnail(self,touch)
# don't forget to ungrab ourself, or you might have side effects
touch.ungrab(self)
self.state = 'released'
# and accept the last up
return True
def on_touch_move(self, touch):
Clock.unschedule(self.time_count)
self.t = 0
if self.state == 'grabed':
# print('DraggableThumbnail on_touch_move : %s' % self.image_name)
self.pos = touch.x - self.image.width / 2, touch.y - self.image.height / 2
return True
else:
self.img_touched = ''
view raw Library.py hosted with ❤ by GitHub

②Sleiderの右→左の実現

海外のPDFViewerで不便に思うのが縦書き(右→左)に対応していない事です。Kivyのスライダーは左→右(下→上)は実現できますが、右から左の設定がありません。あとスライドしている時にページ数も欲しかったのでこちらは部品化しました。ソースはGithubにアップしてあります。こうやって標準部品をカスタマイズするのかーと勉強になりました。もし良ければソースご覧ください。

Example.gif

③(おまけ)本棚の作り方

ちょうどいい本棚画像が無かったので、作りました。この画像の事です。
shelf2.png

作り方はこちらのページにて、プログラムとは関係ありませんし、どこにも需要が無さそうですが。

あわせて読みたい
Inkscape(0.92.4)で本棚を作る PythonとKivyで自炊したPDFを読むアプリを作っているのですが、 本棚の画像をどうしても入れたくて、色々探した(無料のやつね)んですけど、 思ったものが無かったので...

  • URLをコピーしました!

コメント

コメントする

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)