質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Kivy

Kivyは、Pythonを用いたNUI開発のためのオープンソースフレームワーク。マルチタッチなど多くの入力に対応したNUIアプリなどを開発することができます。多くの環境で動作するクロスプラットフォームです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

1840閲覧

kivyのcarouselにおいて読み込んだwidgetの順次表示

ulthar

総合スコア8

Kivy

Kivyは、Pythonを用いたNUI開発のためのオープンソースフレームワーク。マルチタッチなど多くの入力に対応したNUIアプリなどを開発することができます。多くの環境で動作するクロスプラットフォームです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2021/07/28 08:11

python3.8.0、Kivyを用いて簡単な画像ビューアプリを作成しています。
画像の入ったzipを読み込み、PIL、Textureを用いてKivyのImageにのせ、Carouselにadd_widgetしています。
質問はこの方法をとった場合、Carouselは画像の全てを読み込んでからしか表示されず、画像枚数が多い場合に待ち時間が長くなってしまいます。
画像の一枚目を読み込んだ時点でCarouselを表示し、それと並行して順次Imageを読み込んで行って欲しいのですがどのようなファクターを用いれば達成できるでしょうか。

pyファイル

main

1from kivy.app import App 2from kivy.uix.carousel import Carousel 3from kivy.uix.boxlayout import BoxLayout 4from kivy.properties import ObjectProperty 5from kivy.graphics.texture import Texture 6from kivy.uix.image import Image as Img 7import zipfile 8import io 9from PIL import Image 10 11import time 12 13 14class Cartest(App): 15 def __init__(self, **kwargs): 16 super(Cartest,self).__init__(**kwargs) 17 self.title="test" 18 19class ImageCell(Carousel): 20 pass 21 22class MainDis(BoxLayout): 23 imagecell=ObjectProperty() 24 def imageload(self): 25 self.imagecell.clear_widgets() 26 ziplist=zipfile.ZipFile("画像の複数枚入ったzipfile") 27 ziplist=zipone.namelist() 28 imagecount=0 29 for i in ziplist: 30 time.sleep(3) 31 img=zipone.open(i) 32 img=io.BytesIO(img.read()) 33 img=Image.open(img) 34 img=img.convert("RGB") 35 texture=Texture.create(size=img.size) 36 texture.blit_buffer(img.tobytes()) 37 texture.flip_vertical() 38 self.imagecell.add_widget(Img(texture=texture,allow_stretch=True)) 39 imagecount+=1 40 print(imagecount) 41 42 43if __name__=="__main__": 44 Cartest().run()

kvファイル

cartest

1<ImageCell> 2<MainDis> 3 imagecell: imagecell 4 BoxLayout: 5 orientation:"vertical" 6 ImageCell: 7 id: imagecell 8 size_hint_y:.9 9 Button: 10 text: "test" 11 size_hint_y:.1 12 on_press: root.imageload() 13MainDis

このコードでは便宜上、画像読み込み時に3秒待っています。一枚目を読み込んだ後、2枚目の待ち時間にすでに一枚目を見れるようにしたいです。
調べた限りでは非同期処理の勉強をすべきかと思ったのですが、もしスマートに達成できそうな方法があれば教えていただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gottadiveintopy

2021/07/28 16:00

Clock.schedule_interval()を用いると一定間隔で関数を呼んでくれるので、それを利用して例えば一秒間隔でCarouselに少しずつ画像を加えていくと良いと思いますよ
guest

回答1

0

ベストアンサー

多くのGUI programにおいて普通main thread内ではtime.sleep()は使えないので代わりにGUI libraryが提供してくれているtimer系の機能を使わないといけないです。KivyではClock.schedule_once()Clock.schedule_interval()等がそれに当たります。ただ今回これらを用いる場合には少し工夫が必要で、現在はcodeの構造は

python

1 def imageload(self): 2 ... 3 for i in iterable: 4 time.sleep(3) 5 # 繰り返し行いたい処理

となってますけど、これを例えば

def imageload(self): ... iterator = iter(iterable) def callback(dt): try: i = next(iterator) except StopIteration: return False # 繰り返し行いたい処理 Clock.schedule_interval(callback, 3)

といった形に組み替えないといけないです。こういった感じでCUI programとは異なった形のcode構造をとらないといけないのがGUI programで、これがGUI programmingを難しくしている要因の一つです(と私は思ってます)。

でもこの問題を解決する方法が存在していてそれがasync/await構文になります。手前味噌なんですがasynckivyを用いる事で元の構造を保ったまま以下のように書けます。

python

1import asynckivy 2 3class MainDis(BoxLayout): 4 async def imageload(self): 5 ... 6 for i in iterable: 7 await asynckivy.sleep(3) 8 # 繰り返し行いたい処理

kivy

1#:import asynckivy asynckivy 2<MainDis> 3 BoxLayout: 4 Button: 5 on_press: asynckivy.start(root.imageload())

Clock.schedule_interval()asynckivy、お好きな方をどうぞ。

投稿2021/07/29 02:58

編集2021/07/29 17:34
gottadiveintopy

総合スコア736

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ulthar

2021/07/29 04:45

いつもありがとうございます。 取り急ぎテストコードで試してみたらClock.schedule_interval()、asynckivyともに想定通り動きました。 テストコードではasynckivyの方が早そうな気がします。本番のアプリで適応してみて良さそうな方を使ってみようと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問