前提・実現したいこと
wxpythonでgif動画を再生するデスクトップアプリを作っています。
gif動画の一方を透過色が入ったもので、2重に再生し、ボタンも表示したい。
ソースコード
同フォルダにあるgif画像を10秒おきに入れ替え再生していますが、同時に再生したいと思っております。
python
1import os 2import sys 3import time 4from threading import Thread 5 6import wx 7from wx.adv import Animation, AnimationCtrl 8from wx.lib.newevent import NewEvent 9 10UpdateImageEvent, EVT_UPDATE_IMAGE = NewEvent() 11 12 13class CountTimer(Thread): 14 daemon = True 15 16 def __init__(self, win): 17 super().__init__() 18 19 # イベント通知対象のウィジェット。(MainWindow) 20 self.win = win 21 22 # 次の画像ファイルを所得する関数 (仮: カレントディレクトリの gif ファイルが対象) 23 from glob import glob 24 from itertools import cycle 25 from functools import partial 26 self.nextImageFile = partial(next, cycle(glob("*.gif"))) 27 28 def run(self): 29 num = 0 30 while True: 31 num += 1 32 if num % 10 == 0: # 剰余で十秒毎を判別 33 34 # 次に表示する画像ファイル 35 filepath = self.nextImageFile() 36 37 # イベント通知する為、引数となるイベントオブジェクトを作成 38 event = UpdateImageEvent(filepath=filepath) 39 40 # 通知 (MainLoopのキューにイベントを入れる) 41 wx.PostEvent(self.win, event) 42 43 del event, filepath 44 time.sleep(1) 45 46 47class MainWindow(wx.Frame): 48 def __init__(self, parent=None, ID=wx.ID_ANY, title="", *args, **kw): 49 super().__init__(parent, ID, title, *args, **kw) 50 self.animeCtrl = AnimationCtrl(self) 51 52 # イベントとイベント通知受信時に呼び出されるコールバック関数の結び付け 53 self.Bind(EVT_UPDATE_IMAGE, self.OnUpdateImage) 54 55 def OnUpdateImage(self, event): 56 # PostEvent での通知により *メインスレッドで* 実行される 57 print("OnUpdateImage", event.filepath) 58 self.SetImageFile(event.filepath) 59 60 def SetImageFile(self, filepath): 61 # 画像・動画を変更し再生する 62 assert os.path.isfile(filepath) 63 self.animeCtrl.SetAnimation(Animation(filepath)) 64 self.animeCtrl.Play() 65 66 67def main(): 68 app = wx.App() 69 win = MainWindow() 70 win.SetSize(400, 400) 71 win.Centre() 72 win.Show() 73 74 thread = CountTimer(win) 75 thread.start() 76 77 app.MainLoop() 78 79 80if __name__ == '__main__': 81 main()
Architectureと発生している問題・エラーメッセージ
wx.Posteventの方法で試した場合、ひとつのeventのみ呼び出されてしまい、レイヤーのように別々に操作することができませんでした。
使用ファイル
以下に、gif動画ひとつと透過pngをgif化したものを配置しました。(透過gifになっていなかったらすみません。)
Google Drive
参考サイト
gif画像を一枚ずつの画像へ分解するサイト
透過画像作成サイト
透過pngをgif動画にするサイト
アニメーションについて調べたサイト
アニメーションについて調べたサイト2
過去teratailでの似ている質問(透過gif)
2つのgifを重ねて一枚一枚保存したものをgifにしてそれを1つのイベントで実行という方法がありますが、
私は、あるイベント発生(クリックなど)によって一枚だけのレイヤーに存在する透過gifを他のものに変えたり最終的にはしたいため、イベント自体を2個同時に実行するのがよいと考えております。そもそもイベントを重ねてgifを表示することじたいが調べているのですがでてこなく、知見ある方何かアドバイス頂けないでしょうか。
よろしくお願い致します。
補足情報(FW/ツールのバージョンなど)
win10
python3.7
wxpython
追記 2020/08/02
以下など試してみました。
《別方法1》
python
1class MainWindow(wx.Frame): 2 def __init__(self, parent=None, ID=wx.ID_ANY, title="", *args, **kw): 3 super().__init__(parent, ID, title, *args, **kw) 4 self.animeCtrl = AnimationCtrl(self) 5 6 # 20200801 add 7 panel1 = wx.Panel(self, wx.ID_ANY) 8 v_layout = wx.BoxSizer(wx.VERTICAL) 9 # ButtonA 10 feature_button = wx.Button(panel1, wx.ID_ANY, "Feature") 11 feature_button.Bind(wx.EVT_BUTTON, self.feature_method) 12 v_layout.Add(feature_button, proportion=0, flag=wx.ALIGN_CENTER_HORIZONTAL) 13 panel1.SetSizer(v_layout) 14 15 def feature_method(self, event): 16 wx.MessageBox('正解です!')
《別方法2》
python
1def main(): 2 app = wx.App() 3 win = MainWindow() 4 win.SetSize(800, 800) 5 win.Centre() 6 win.Show() 7 # 20200801 add 8 win_sub = SubWindow() 9 win_sub.SetSize(800, 800) 10 win_sub.Centre() 11 win_sub.Show()
SubWindowクラスを作るなど試行錯誤しましたが同時に表示はできませんでした。
《別方法3》
python
1import wx 2import wx.adv 3 4class BG(object):#背景の表示 5 def __init__(self, MainPanel,x,y): 6 BGimg =wx.Image("1.png") 7 self.bitmap = BGimg.ConvertToBitmap() 8 wx.StaticBitmap(MainPanel, -1, self.bitmap, (x,y)) 9 10class MyWindow(wx.Frame): 11 def __init__(self, parent=None, id=-1, title=None): 12 wx.Frame.__init__(self, parent, id, title) 13 self.MainPanel = wx.Panel(self, size=(1200, 800))#メイン画面の大きさ 14 self.MainPanel.SetBackgroundColour("Black") 15 self.BackG = BG(self.MainPanel, 0, 0) 16 self.anime = wx.Panel(self.MainPanel, pos=(350, 0), size=(450, 800), 17 style=wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN) 18 self.file = "sakura.gif" 19 self.ani = wx.adv.Animation(self.file) 20 self.ctrl = wx.adv.AnimationCtrl(self.anime, -1, self.ani, pos=(10, 10), style=wx.TRANSPARENT) 21 self.ctrl.Play() 22 self.Fit() 23 24if __name__ == "__main__": 25 app = wx.App() 26 w = MyWindow(title="test") 27 w.Center 28 w.Show() 29 app.MainLoop()
この方法でも重ねることはできませんでした。
《別方法4》
python
1 2import wx 3import wx.adv 4 5GIFNames = [ 6 'sakura.gif' 7 ] 8 9 10class TestPanel(wx.Panel): 11 def __init__(self, parent): 12 13 wx.Panel.__init__(self, parent, -1) 14 15 sizer = wx.FlexGridSizer(2,3,5,5) 16 17 for name in GIFNames: 18 ani = wx.adv.Animation(name) 19 ctrl = wx.adv.AnimationCtrl(self, -1, ani) 20 ctrl.SetBackgroundColour('black') 21 ctrl.Play() 22 23 #sizer.AddF(ctrl, wx.SizerFlags().Border(wx.ALL, 10)) 24 25 border = wx.BoxSizer() 26 #border.AddF(sizer, wx.SizerFlags(1).Expand().Border(wx.ALL, 20)) 27 self.SetSizer(border) 28 29app = wx.App() 30frame = wx.Frame(None) 31panel = TestPanel(frame) 32frame.Show() 33app.MainLoop()
透過はできるようにはなったようなのですが、その背景に別gifを入れること(まずはバックグラウンドを黒)に挑戦していますが、黒背景もまだでませんしもう少しのようです。
そもそも、黒背景ではなく、もう一つの背景gifじたいもユーザーのアクションによって変えたいので端的に背景に挿入しても変更できないのであれば問題ですが…
《別方法5》
python
1import wx 2 3class Mywin(wx.Frame): 4 5 def __init__(self, parent, title): 6 super(Mywin, self).__init__(parent, title = title,size = (500,300)) 7 self.InitUI() 8 9 def InitUI(self): 10 self.Bind(wx.EVT_PAINT, self.OnPaint) 11 self.Centre() 12 self.Show(True) 13 14 def OnPaint(self, e): 15 dc = wx.PaintDC(self) 16 brush = wx.Brush("white") 17 dc.SetBackground(brush) 18 dc.Clear() 19 20 dc.DrawBitmap(wx.Bitmap("1.png"),10,10,True) 21 color = wx.Colour(255,0,0) 22 b = wx.Brush(color) 23 24 dc.DrawBitmap(wx.Bitmap("vqkSsK_Z-0.png"),10,10,True) 25 color = wx.Colour(255,0,0) 26 b = wx.Brush(color) 27 28 dc.SetBrush(b) 29 dc.DrawCircle(300,125,50) 30 dc.SetBrush(wx.Brush(wx.Colour(255,255,255))) 31 dc.DrawCircle(300,125,30) 32 33 font = wx.Font(18, wx.ROMAN, wx.ITALIC, wx.NORMAL) 34 dc.SetFont(font) 35 dc.DrawText("Hello wxPython",200,10) 36 37 pen = wx.Pen(wx.Colour(0,0,255)) 38 dc.SetPen(pen) 39 dc.DrawLine(200,50,350,50) 40 dc.SetBrush(wx.Brush(wx.Colour(0,255,0), wx.CROSS_HATCH)) 41 dc.DrawRectangle(380, 15, 90, 60) 42 43ex = wx.App() 44Mywin(None,'Drawing demo') 45ex.MainLoop()
DrawBitmapというものを使えば重ねて表示ができそうです。ただこの場合ですとgifで対応できないようです。
近づいてはいるとは思いますが、引き続きアドバイスよろしくお願い致します。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/08/02 05:43
2020/08/02 06:36
2020/08/02 12:25
2020/08/02 13:02
2020/08/02 13:24