デジタルフォトフレームの動作をソフトウェア的に実装する(2) -wxPythonの出番-

デジタルフォトフレームで実現している自動的な画像切り替えの動作を実装することが目標である。フォトフレームでなくても、スクリーンセーバーなんかでも見られる自動画像切り替えをどう実現するか、を自分のアタマで考えていろいろと試してみたい。
とりあえずは、特定のディレクトリに複数の画像ファイルを用意しておいて、それらを読み込んで連続的に表示させるようにする。前回はPILでテスト的に画像を表示させたので、今回は一歩進んで、wxPythonで作成したフレーム上に画像を表示させてみる。
そこで書いたのが下のコード。画像ファイルの読み込み部分は無限ループにして、動作中に新しい画像ファイルを追加した場合にも、それを読み込んで表示させるようにしている。当該の無限ループはthreadingでバックグランド処理としている。

#!/bin/env python

import os
import wx
import time
import thread

class MainFrame(wx.Frame):
    def __init__(self, id, title):
        width, height = 350, 350
        wx.Frame.__init__(self, id, title="Photo Frame",
        size=wx.Size(width, height))
        pan = wx.Panel(self, -1)

        bmp = wx.EmptyBitmap(350,350)
        self.pc = wx.StaticBitmap(pan, -1, bmp)

        thread.start_new_thread(self.run, ())

    def run(self):
        n = -1
        while True:
            ph = os.path.join(os.getcwd(), 'picts')
            fls = os.listdir(ph)
            n += 1
            if n >= len(fls):
                n = 0
            pname = os.path.join(ph, fls[n])
            if pname.endswith("bmp") or pname.endswith("BMP"):
                pict = wx.Image(pname, wx.BITMAP_TYPE_BMP)
            elif pname.endswith("gif") or pname.endswith("GIF"):
                pict = wx.Image(pname, wx.BITMAP_TYPE_GIF)
            elif pname.endswith("png") or pname.endswith("PNG"):
                pict = wx.Image(pname, wx.BITMAP_TYPE_PNG)
            elif pname.endswith("jpg") or pname.endswith("JPG"):
                pict = wx.Image(pname, wx.BITMAP_TYPE_JPEG)

            bmp = pict.ConvertToBitmap()
            self.pc.SetBitmap(bmp)

            time.sleep(5) # unit in second

class Application(wx.App):
    def OnInit(self):
        frame = MainFrame(None, -1)
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

def main():
    app = Application(0)
    app.MainLoop()

if __name__ == '__main__':
    main()

このコードを実行すると、一枚目の画像は表示してくれる。

(画像の内容は本文とは関係ありません。テスト用の画像です。)

その後、次の画像に切り替わるときにクラッシュしてしまう。クラッシュ時のメッセージが場合により異なる。例えば、

Assertion failed: (req == dpy->xcb->pending_requests), function dequeue_pending_request, file xcb_io.c, line 140.
Abort trap

こんなときもあるし、

The program 'Python' received an X Window System error.
This probably reflects a bug in the program.
The error was 'RenderBadPicture (invalid Picture parameter)'.
  (Details: serial 327 error_code 149 request_code 144 minor_code 8)
  (Note to programmers: normally, X errors are reported asynchronously;
   that is, you will receive the error a while after causing it.
   To debug your program, run it with the --sync command line
   option to change this behavior. You can then get a meaningful
   backtrace from your debugger if you break on the gdk_x_error() function.)

こんなときもある。または、

Python: Fatal IO error 35 (Resource temporarily unavailable) on X server /tmp/launch-ltPXMv/org.macosforge.xquartz:0.

こんなときも。time.sleepの時間を変えるとエラーの内容が変わったりする。
どこのバグかな?、を次に考える。