2015/06/24(水) [n年前の日記]
#1 [python] wxPython勉強中
とりあえず、画像をウインドウにドラッグアンドドロップするとダブルバッファで描画するスクリプトを書いてみたり。
実行するとこんな感じに。
後は、マウスカーソルの位置取得、マウスボタンを押した時の状態取得・イベント指定ができれば、画像のドラッグ移動もできるかなと。
 実行するとこんな感じに。
# -*- mode: python; Encoding: utf-8; coding: utf-8 -*-
"""
画像ファイルをドラッグアンドドロップしてダブルバッファで表示してみるテスト
Windows7 x64 + Python 2.7.10 + wxPython 3.0.2.0 で確認。
"""
import wx
USE_BUFFERED_DC = True
class MyFileDropTarget(wx.FileDropTarget):
    """ドラッグアンドドロップ担当クラス"""
    def __init__(self, obj):
        """コンストラクタ"""
        wx.FileDropTarget.__init__(self)
        self.obj = obj  # ファイルのドロップ対象を覚えておく
    def OnDropFiles(self, x, y, filenames):
        """ファイルをドロップした時の処理"""
        self.obj.LoadImage(filenames)  # 親?の画像読み込みメソッドを呼ぶ
class MyFrame(wx.Frame):
    """ダブルバッファで表示するFrame"""
    def __init__(self, parent=None, title=""):
        """コンストラクタ"""
        wx.Frame.__init__(self, parent=parent, title=title, size=(800, 600))
        # PAINTイベント、SIZEイベントで呼ばれるメソッドを割り当てる
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        # 画像格納用リストを初期化
        self.imgs = []
        # 描画用バッファ初期化のために一度 OnSize() を呼ぶ
        self.OnSize()
        # ファイルドロップの対象をフレーム全体に
        self.droptarget = MyFileDropTarget(self)
        # ファイルドロップ受け入れを設定
        self.SetDropTarget(self.droptarget)
    def LoadImage(self, files):
        """D&Dされた画像をロードして描画"""
        for filepath in files:
            b = wx.Bitmap(filepath)
            self.imgs.append(b)
        self.UpdateDrawing()  # 描画更新
    def OnSize(self, event=None):
        """ウインドウサイズが変更された時に呼ばれる処理"""
        size = self.ClientSize  # クライアントのウインドウサイズを取得
        # ウインドウサイズで、空の描画用バッファ(bitmap)を作成
        self._buffer = wx.EmptyBitmap(*size)
        self.UpdateDrawing()  # 描画更新
    def UpdateDrawing(self):
        """描画更新"""
        dc = wx.MemoryDC()
        dc.SelectObject(self._buffer)
        self.Draw(dc)  # 描画
        del dc  # Update()が呼ばれる前に MemoryDC を削除しておく必要がある
        self.Refresh()
        self.Update()
    def OnPaint(self, event=None):
        """画面書き換え要求があった時に呼ばれる処理"""
        if USE_BUFFERED_DC:
            # ダブルバッファを使う場合
            dc = wx.BufferedPaintDC(self, self._buffer)
        else:
            # ダブルバッファを使わない場合
            dc = wx.PaintDC(self)
            dc.DrawBitmap(self._buffer, 0, 0, True)
    def Draw(self, dc):
        """描画処理。デバイスコンテキストを貰ってソレを使って処理"""
        dc.Clear()  # デバイスコンテキストでクリア
        # 画像を描画
        x, y = 0, 0
        for img in self.imgs:
            dc.SetPen(wx.Pen(wx.BLACK, 4))  # ペンを設定しないと描画できない
            dc.DrawBitmap(img, x, y, True) # 画像描画
            # 画像枠を描画
            dc.SetBrush(wx.TRANSPARENT_BRUSH) # 透明塗り潰し
            dc.SetPen(wx.Pen(wx.RED, 2)) # 赤い線を指定
            dc.DrawRectangle(x, y, img.Width, img.Height)
            x += 32
            y += 32
if __name__ == '__main__':
    # メイン処理
    app = wx.App(False)
    frame = MyFrame(None, "DnD Image display use Double Buffer")
    frame.Show()
    app.MainLoop()
後は、マウスカーソルの位置取得、マウスボタンを押した時の状態取得・イベント指定ができれば、画像のドラッグ移動もできるかなと。
[   ツッコむ ]
以上です。
