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

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

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

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

4328閲覧

複数Windowで動画再生

退会済みユーザー

退会済みユーザー

総合スコア0

Python 3.x

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2018/01/16 13:46

###前提・実現したいこと
下記それぞれのPATHに30fpsの画像(YYYYMMDD_HHMMSS.mmm.jpg ...)が1000枚ずつ格納されている。
'./src/img/0/'
'./src/img/1/'
'./src/img/2/'
'./src/img/3/'

この格納された画像PATHごとにViewerを作り、4つのViewerで30fpsの動画再生を同時に行う。

###発生している問題・エラーメッセージ

一つの画像Viewerでは動画再生ができたものの複数Windowを作り 同時再生するためにはどのようにすべきかわからない。

###該当のソースコード

python

1# -*- coding: UTF-8 -* 2from tkinter import * 3import tkinter 4import PIL.Image 5import PIL.ImageTk 6import os 7# import pygame 8# import re, sys 9 10# フレーム速度 [ms] 11TIME = 33 12# ファイル格納場所 13PATH = './src/img/0/' 14 15class App(Frame): 16 def __init__(self, master=None): 17 Frame.__init__(self, master) 18 # ディクレクトリ内のファイルのリストを取得する 19 self.ls = os.listdir(PATH) 20 21 # ディクレクトリ内のファイルリストで余分なファイルを削除 22 # b = self.ls.remove(os.path.basename(__file__)) 23 24 # numはリストの番号情報を保持 25 self.num = 0 26 # startedは再生しているかどうかを保持 27 self.started = False 28 29 # フレームの設定 30 self.la = Label(self) 31 self.la.pack() 32 self.pack() 33 self.bind_all('<1>', self.play) 34 self.bind_all('<3>', self.reset) 35 self._setting() 36 37 def reset(self, event): 38 self.num = 0 39 if not self.started: 40 self._setting() 41 42 def play(self, event): 43 # 右クリックでスタートとストップを切り替える 44 if self.started: 45 self.started = False 46 else: 47 self._setting() 48 self.after(TIME, self.start) 49 self.started = True 50 51 def start(self): 52 if self.started: 53 self.num += 1 54 if self.num < len(self.ls): 55 self._setting() 56 self.after(TIME, self.start) 57 else: 58 self.num = 0 59 self.started = False 60 61 def _setting(self): 62 # 画像を読み込み、タイトルを変える 63 self.image = PIL.ImageTk.PhotoImage(PIL.Image.open(PATH + self.ls[self.num])) 64 self.la.configure(image=self.image) 65 self.master.title(self.ls[self.num]) 66 67if __name__ == '__main__': 68 app = App() 69 app.mainloop()

###試したこと

###補足情報(言語/FW/ツール等のバージョンなど)
IDE:pycharm
OS:Windows

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

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

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

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

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

guest

回答1

0

ベストアンサー

Windowを分けたいという要望なため、TopLevelWindowを使用して改造。

※10のコメントの箇所は改善するとしたらThreadPoolExecutorを使用するという形になると思うので、興味があるならぐぐってみてくださいな。
申し訳ないのですが、途中でモチベーションが下がってしまったので、
回答のソースコード解説の要求はスルー致します><

Python

1# -*- coding: UTF-8 -* 2from tkinter import * 3# ※1 上記行と同じ事をしているためコメントアウト 4# import tkinter 5import PIL.Image 6import PIL.ImageTk 7import os 8import functools 9from collections import Counter 10# import pygame 11# import re, sys 12# フレーム速度 [ms] 13TIME = 33 14# ※2_settingの処理時間計測用 15times = Counter() 16 17 18def on_application_exit(param): 19 # ※3 終了処理はexitを呼び出し! 20 sys.exit(0) 21 22# ※4 Frame→Toplevelに変更 23class App(Toplevel): 24 # startedは再生しているかどうかを保持 25 started = False 26 # ※5 viewerの参照を保持 27 viewers = [] 28 29 def __init__(self, master, path=''): 30 super().__init__() 31 App.viewers.append(self) 32 # ※6 ウィンドウを閉じたときの終了イベントを追加 33 self.protocol('WM_DELETE_WINDOW', functools.partial(on_application_exit, param=1)) 34 # ディクレクトリ内のファイルのリストを取得する 35 self.image_path = path 36 37 self.ls = os.listdir(path) 38 # ※7 listdirではファイルの取得順序は保証されていない!のでソート処理を追加 39 self.ls = sorted(self.ls) 40 # ディクレクトリ内のファイルリストで余分なファイルを削除 41 # b = self.ls.remove(os.path.basename(__file__)) 42 43 # ※8 Progressクラスを新規追加し、進捗を管理 44 class Progress(object): 45 def __init__(self, maximum=0): 46 self.minimum = 0 47 self.maximum = maximum 48 self.value = 0 49 50 def perform_step(self): 51 if self.maximum == self.value: 52 return 53 self.value += 1 54 55 def reset(self): 56 self.value = self.minimum 57 self.progress = Progress(len(self.ls)) 58 # ラベルの設定 59 self.la = Label(self) 60 self.la.pack() 61 #※9 self.packをコメントアウト 62 #self.pack() 63 self.bind_all('<1>', App.viewer_click) 64 self.bind_all('<3>', App.all_reset) 65 self._setting() 66 67 def reset(self, event): 68 self.progress.reset() 69 self._setting() 70 71 def next_image(self): 72 if not self.started: 73 return 74 self.progress.perform_step() 75 if self.progress.value < self.progress.maximum: 76 self._setting() 77 else: 78 self.reset(None) 79 80 def _setting(self): 81 # ※10 time.perf_counter()で計測すると_setting内の処理時間が30fpsを余裕でオーバーしている 82 import time 83 start = time.perf_counter() 84 # 画像を読み込み、タイトルを変える 85 filename = self.image_path + self.ls[self.progress.value] 86 img = PIL.Image.open(filename) 87 self.image = PIL.ImageTk.PhotoImage(img) 88 elapsed_time = time.perf_counter() - start 89 # ※2 90 times[round(elapsed_time * 1000, 3)] += 1 91 self.la.configure(image=self.image) 92 self.title(os.path.basename(filename)) 93 94 @staticmethod 95 def viewer_click(event): 96 # マウスクリックでスタートとストップを切り替える 97 App.started = not App.started 98 if App.started: 99 image_update() 100 return 101 102 @staticmethod 103 def all_reset(event): 104 for app in App.viewers: 105 app.reset(event) 106 107 108def image_update(): 109 for app in App.viewers: 110 app.next_image() 111 if App.started: 112 root.after(TIME, decorated) 113 114 115root = Tk() 116decorated = functools.update_wrapper(functools.partial(image_update), image_update) 117 118 119def main(): 120 # ※11 root windowを非表示 121 root.withdraw() 122 root.protocol('WM_DELETE_WINDOW', functools.partial(on_application_exit, param=0)) 123 viewer_params = [ 124 {'path': './src/img/0/', 'x': 50, 'y': 50}, 125 {'path': './src/img/1/', 'x': 50, 'y': 460}, 126 {'path': './src/img/2/', 'x': 460, 'y': 50}, 127 {'path': './src/img/3/', 'x': 460, 'y': 460} 128 ] 129 for para in viewer_params: 130 app = App(root, para['path']) 131 # ※12 他のwindowとの位置をgeometryで設定 132 # geometry width*height+x+y 133 app.geometry("{0}x{1}+{2}+{3}".format(400, 400, para['x'], para['y'])) 134 root.mainloop() 135 136 137if __name__ == '__main__': 138 main()

投稿2018/01/17 22:21

編集2018/01/17 22:50
umyu

総合スコア5846

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

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

退会済みユーザー

退会済みユーザー

2018/01/22 00:13

詳しい解説ありがとうございました、参考にさせていただきます。 ご回答いただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問