2018年3月5日月曜日

wxpythonによるエクスプローラからの画像ファイルのドロップ、お絵かき




wxpythonによるエクスプローラからの画像ファイルのドロップ
と お絵かき
 
各モジュールは単体でも動作する。 飽きてきたので途中まで...
xでdraw関係の動作  g 画像をペン先にしてえがく c 円を描く b ぬりつぶし
yでdrop関係動作  l エクスプローラ表示 そこから画像ファイルをドロップできる。
               ウィンドウ上でも移動できる

参考サイト
#wxPythonで画像表示とかドラッグ移動とか勉強中
#http://blawat2015.no-ip.com/~mieki256/diary/201506251.html
まくまくpythonノート

メインコード
G:\MyBackups\goolgedrive\myprg_main\python_my_prg\wxpython\dc\all2_frame.py

# coding: UTF-8
#wxPythonで画像表示とかドラッグ移動とか勉強中
#http://blawat2015.no-ip.com/~mieki256/diary/201506251.html

"""
#Lきーでファイルダイヤログ呼び出し
#ほか 改変

エクスプローラ上画像ファイルをドラッグアンドドロップしてダブルバッファで
MyFrame上に表示。
MyFrame上でマウスドラッグで画像表示位置を移動
で frame部分のみ取り出す
"""

import wx
import all2_drop_gazou  as drop
import all2_menu                as menu
import all2_mytoolbar        as mytoolbar
from all2_draw          import DrawAction
from all2_bind            import MyBind
#from panel_on_panel            import PanelOnPanel
#panelを2つおいて、一方にこのDrawPanelをおいてもbindがうまく反応しない



"""ダブルバッファで表示するFrame"""
class DrawPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.firstInitBuffer()

        self.child_list = []
        da = DrawAction(self)
        self.child_list.append(da)
        dp = drop.DropAction(self)
        self.child_list.append(dp)

        #bind用クラス(イベント管理)
        #bind用クラスに各作業のクラスのオブジェクトを送って
        #イベントが起きたときのアクションの分岐をさせる。
        MyBind(self, self.child_list)

        # RefreshによってOnPaintがよばれている
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_SIZE, self.OnSize)

        """ペン先に画像を使う"""
        #pensaki.PenGazou(self)

    def OnKeyDownEvent(self, event):
        print "main_OnKeyDownEvent"

    """画面書き換え要求があった時に呼ばれる処理"""
    def OnPaint(self, event=None):
        print "OnPaint"
        dc = wx.BufferedPaintDC(self, self.buffer)


    """ウインドウサイズが変更された時に呼ばれる処理"""
    #かなり複雑になるのでこのイベントやめる
    def OnSize(self, event=None):
        print "OnSize"
        pass


    """初期化"""
    def firstInitBuffer(self):
        #print "InitBuffer"
        self.buffer = wx.EmptyBitmap(1280, 708)
        dc = wx.BufferedDC(None, self.buffer)
        dc.SetBackground(wx.Brush('white'))
        dc.Clear()  # デバイスコンテキストでクリア
        self.Draw(dc)  # 実際の描画処理
        # Falseを指定して背景を消さなくしたら画面のちらつきが出なくなった
        self.Refresh(eraseBackground=False)


    """描画更新"""
    def InitBuffer(self):
        #print "UpdateDrawing"
        #self.buffer = wx.EmptyBitmap(1280, 708)
        dc = wx.BufferedDC(None, self.buffer)
        #dc.SetBackground(wx.Brush('white'))
        #dc.Clear()  # デバイスコンテキストでクリア
        self.Draw(dc)  # 実際の描画処理
        # Falseを指定して背景を消さなくしたら画面のちらつきが出なくなった
        self.Refresh(eraseBackground=False)


    """実際の描画処理"""
    def Draw(self, dc):
        #print "Draw"
        dc.SetBrush(wx.Brush(wx.Colour(128, 255, 128)))
        dc.SetPen(wx.Pen("RED", 3))
        #つまり 輪郭が赤中が黄緑色?になる
        dc.DrawCircle(0, 0, 10)

        #objsで今までドラッグした画像を保存しておいて
        #ドラッグ完了すると、ドラッグ中の画像もふくめて
        #描画している

        """ドラッグした画像すべてを描画する  """
        drop.all_obj_draw(dc)



class MyFrame(wx.Frame):
    #メニューバー 、ステータスバー,ツールバーなどはFrmae上し
    #か置けないため、paelを作成し、そこで描画する
    ## *args 可変長タプル  **kwargs 可変長辞書
    def __init__(self, parent, *args ,**kargs):
        frame = wx.Frame.__init__(self, parent, *args, **kargs)

        #"""メニューバー等をつける menuモジュール利用"""
        menu.myMenuBar(self)

        pal2 = DrawPanel(self)

        #"""ツールバーをつける  mytoolbarモジュール利用"""
        mytoolbar.myToolBar(self)


        #画像、またはエクスプローラ上の画像ファイルをドラッグした時に
        #描画のアップデートをする関数を指定する
        func = pal2.InitBuffer
        #画像のドラッグ機能をMyFrameに組み込む Panelには組み込めない
        #ようだ
        drop.MetaMyFileDropTarget(self, func)
        self.Show()


if __name__ == '__main__':
    app = wx.App(False)
    MyFrame(None, -1, "Draw Test 4", size=(800, 600))
    app.MainLoop()









G:\MyBackups\goolgedrive\myprg_main\python_my_prg\wxpython\dc\all2_bind.py
# coding: UTF-8
#wxPythonで画像表示とかドラッグ移動とか勉強中
#http://blawat2015.no-ip.com/~mieki256/diary/201506251.html

"""
bind部分のクラス
"""
import wx

class MyBind():
    def __init__(self, parent, child_list):
        self.key = 0
        self.key2 = 0

        self.parent = parent
        self.draw = child_list[0]
        self.drop = child_list[1]
        print "child_list", child_list
        print

        #画像ドラッグ時 おかしい
        #イベントエラーおこす--------------------------------------------------
        #self.parent.Bind(wx.EVT_MOTION,        self.OnMotionEvent)
        #self.parent.Bind(wx.EVT_LEFT_DOWN, self.OnLeftButtonDownEvent)
        #self.parent.Bind(wx.EVT_LEFT_UP,        self.OnLeftButtonUpEvent)
        #self.parent.Bind(wx.EVT_KEY_DOWN,  self.OnKeyDownEvent)

        #メインbind
        self.parent.Bind(wx.EVT_KEY_DOWN, self.OnKeyDownEvent)   
#        #サブbind
        self.parent.Bind(wx.EVT_LEFT_DOWN, self.OnLeftButtonDownEvent)
        self.parent.Bind(wx.EVT_LEFT_UP,   self.OnLeftButtonUpEvent)
#        #マウスをウィジェット内で動かした
        self.parent.Bind(wx.EVT_MOTION,     self.OnMotionEvent)

    #def setChild(self,child):
    #    self.child = child

    def OnKeyDownEvent2(self, event):
        print "frame_OnKeyDownEvent"
        pass

    def OnKeyDownEvent(self, event):
        print "bind_OnKeyDownEvent"
        #g71 c67 x88  y89
        k = event.GetKeyCode()
        print k
        print
        #drawの作業をする
        #キーxがおされた
        if 88==k:
            self.key = 88
            print "self.key", self.key
        if self.key==88:
            print "draw"
            self.draw.OnKeyDownEvent(event)   
        #drop の作業をする
        #キーyがおされた
        if 89==k:
            self.key = 89
            print "self.key", self.key
        if self.key==89:
            print "drop"
            self.drop.OnKeyDownEvent(event)   


    def OnLeftButtonDownEvent(self, event):
        if self.key == 88:
            self.draw.OnLeftButtonEvent(event)
        if self.key == 89:
            self.drop.OnLeftButtonDownEvent(event)
        else:
            pass
   
    def OnLeftButtonUpEvent(self, event):
        if self.key == 88:
            self.draw.OnLeftButtonEvent(event)
        if self.key == 89:
            self.drop.OnLeftButtonUpEvent(event)
        else:
            pass
   
    def OnMotionEvent(self, event):
        print "bind_OnMotionEvent"
        if self.key == 88:
            self.draw.OnLeftButtonEvent(event)
        if self.key == 89:
            self.drop.OnMotionEvent(event)
        else:
            pass
   

G:\MyBackups\goolgedrive\myprg_main\python_my_prg\wxpython\dc\all2_draw.py
# coding: UTF-8
#wxPythonで画像表示とかドラッグ移動とか勉強中
#http://blawat2015.no-ip.com/~mieki256/diary/201506251.html

"""
all_muse_draw.pyを draw部分を分離
分かりやすくしたつもり
モジュール化できる
"""
import wx
from PIL import Image



#以下でglobalをつけていないのに、使用可能なのはなぜか
#bitmap_brush_image = "daruma.png"
bitmap_brush_image = "ball.png"
#bitmap_brush_image = "trans.png"
#bitmap_brush_image = "original.png"
#bitmap_brush_image = "test.png"

class DrawPanel(wx.Panel):

    ## *args 可変長タプル  **kwargs 可変長辞書
    #def __init__(self, *args ,**kargs):
    #    wx.Panel.__init__(self, *args, **kargs)
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        #OnSizeが起動時よばれるので初期設定をそこに書いてもいい

        da = DrawAction(self)
        DrawMybind(self, da)

        # 空のビットマップを確保。以後はこれに描画していく
        #空の wx.Bitmap オブジェクトを作成する
        #wx.EmptyBitmap(int width, int height, int depth=-1) -> Bitmap
        #指定したサイズの空の wx.Bitmap オブジェクトを作成しま
        #す。 depth パラメータでは、color depth(色のビット数)を
        #指定することができます。 デフォルトの -1 を指定すると、
        #現在のディスプレイの color depth が使用されます。 1 を指
        #定すると、モノクロ画像になります
        #self.buffer = wx.EmptyBitmap(size[0], size[1])
        #self.buffer = wx.EmptyBitmap(x, y)

        #self.buffer = wx.EmptyBitmap(680,480)
        #self.buffer2 = wx.EmptyBitmap(680,480)

        #self.buttonFlag = False
        #self.key = 0
        #self.key2 = 0

        # RefreshによってOnPaintがよばれている
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        #サイズ変更時
        self.Bind(wx.EVT_SIZE, self.OnSize)

        ## Bind
        #self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftButtonEvent)
        #self.Bind(wx.EVT_LEFT_UP,   self.OnLeftButtonEvent)
        ##マウスをウィジェット内で動かした
        #self.Bind(wx.EVT_MOTION,    self.OnLeftButtonEvent)
        #self.Bind(wx.EVT_KEY_DOWN,  self.OnKeyDownEvent)


    def OnPaint(self, event=None):
        print "OnPaint"
        #オブジェクトが内部的にビットマップを作成するようにするこ
        #とができます(後者の場合、ウィンドウのクライアント部分のサ
        #イズが使用されます)。

        #wx.BUFFER_CLIENT_AREAをスタイルパラメータに
        #wx.BUFFER_CLIENT_AREAて、ウィンドウのクライアント領域だけ
        #がバッファされることを示しますwx.BUFFER_VIRTUAL_AREAは、
        #バッファビットマップが仮想領域をカバーすることを示します
       
        dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)

        #wx.BufferedDC は、あるデバイス・コンテキストへの描画処
        #理をバッファリングし、一度に描画内容を反映するようにしま
        #す。 例えば、wx.ClientDC への連続した描画を
        #wx.BufferedDC でバッファリングすれば、画面上での描画のち
        #らつきを防ぐことができます。

        #EVT_PAINT イベントのハンドラの中で描画処理をバッファリ
        #ングしたい場合は、wx.BufferedDC の代わりに
        #wx.BufferedPaintDC を使用します。

        ##wx.BufferedDC、wx.BufferedPaintDC は内部に描画内容のバッ
        #ファリングのために Bitmap オブジェクトを保持しており、デ
        #バイス・コンテキストがスコープを外れるとき(ガーベジ・コ
        #レクトされるとき)に自動的に内部の Bitmap の内容を
        #Blit() して実際の描画内容を反映するようになっています。


    """ウインドウサイズが変更された時に呼ばれる処理"""
    def OnSize(self, event=None):
        print "OnSize"
        # クライアントのウインドウサイズを取得
        #ClientSize :クライアントサイズは、ウィジェットに属する
        #任意の罫線の内側のウィジェットの領域を表し、EVT_PAINTイ
        #ベントで描画可能な領域です。 ウィジェットに境界線がない
        #場合、クライアントのサイズはそのサイズと同じです
        #ClientSizeは内部で自動的に値が代入されるのか?
        #wx.EVT_SIZEのイベント発生時にか?
        size = self.ClientSize 
        # ウインドウサイズで、空の描画用バッファ(bitmap)を作成
        #ポインタとかおもった。可変長変数。
        #タプルを関数に渡すときに * を付けると、タプルの各要素を
        #関数の引数として展開されて渡される

        #空のビットマップは__init__で定義したほうが気持ちがいいが
        #サイズを変更したら、ビットマップサイズも変更したほうが
        #いい
        self.buffer = wx.EmptyBitmap(*size)

        #print size # (792, 573)
        #self.buffer = wx.EmptyBitmap(680,480)
        #self.UpdateDrawing()  # 描画更新

        self.UpdateDrawing()  # 初期描画


    #表示領域初期化 描画更新
    def UpdateDrawing(self):
        print "UpdateDrawing"
        """ 初期描画 """
        # アンチエイリアスをかける場合は以下のコマンドとなる
        #dc2 = wx.GCDC(dc)
        dc = wx.BufferedDC(None, self.buffer)

        #Clear  現在の背景ブラシを使用してデバイスコンテキストを
        #クリアします
        #これを実行しないと背景が真っ黒になる
        dc.Clear()

        #self.Draw(dc)
        #del コメントアウトしても動作がかわらないが........
        del dc
        #以下のコマンドでOnPaintが呼ばれている
        self.Refresh(False)


class DrawMybind():
    def __init__(self,parent, child):
        # マウスカーソルを動かした時に呼ばれるメソッドを割り当てる
        self.parent = parent
        self.child = child
        #メインイベント
        self.parent.Bind(wx.EVT_KEY_DOWN,  self.child.OnKeyDownEvent)
        #サブイベント
        self.parent.Bind(wx.EVT_LEFT_DOWN, self.child.OnLeftButtonEvent)
        self.parent.Bind(wx.EVT_LEFT_UP,   self.child.OnLeftButtonEvent)
        self.parent.Bind(wx.EVT_MOTION,     self.child.OnLeftButtonEvent)


class DrawAction():
    def __init__(self, parent):
        print "DrawAction"
        self.parent = parent

        # ビットマップ設定
        self.parent.brushBitmap = None
        image = wx.Image(bitmap_brush_image)
        self.parent.brushBitmap = image.ConvertToBitmap()

        self.buttonFlag = False
        self.key = 0
        self.key2 = 0


    def mygetcolor(self):
        #ピッカーで塗りつぶりの色を選択
        d = wx.ColourDialog(self.parent)
        d.ShowModal()
        d.Destroy()
        self.color = d.GetColourData().GetColour()


    #以下全てparent.bufferに描きこんでいく
    def myBrush(self, x, y):
        print "myBrush"
        dc = wx.BufferedDC(None, self.parent.buffer)

        c = dc.GetPixel(x, y)
        for i in range(10000):
            c2 = dc.GetPixel(x+i, y)
            if c2 != c:
                break   
        print "GetPixel",c2

        dc.SetBrush(wx.Brush(self.color))
        #x,y の点から、x,yの場所の色でない色(c2)で、囲まれた所(styleの引数)を、
        #Brushの色(self.color)で塗りつぶす
        dc.FloodFill(x, y, c2, style = wx.FLOOD_BORDER)
        print "FloodFill"
        del dc
        self.parent.Refresh(False)


    def Circle(self, x, y):
        dc = wx.BufferedDC(None, self.parent.buffer)
        print "Draw_circle"

        """ なぜか もともとから、初期の段階から(0,0)からx方向"""
        # y方向に黒の線が描画されている。
        # 原因不明にて、対処療法として白でラインを描きく
        # 白は gazouToukaにて透明になる

        #dc.SetBrush(wx.Brush(wx.WHITE))
        #dc.SetPen(wx.Pen("WHITE", 3))
        #dc.DrawRectangle(0,0, 680,480)
        """ なぜか end---------------------------------------"""

        #    円を描画
        # style
        # wx.TRANSPARENT 透明
        # wx.SOLID             通常
        #ブラシは、領域を塗りつぶすための描画ツール
        dc.SetBrush(wx.Brush(wx.Colour(128, 128, 255), style=wx.TRANSPARENT))
        #ペンはアウトラインを描くための描画ツールです。
        #線を描き、矩形、楕円などの輪郭を描くために使用されます。
        #色、幅、スタイルがあります
        dc.SetPen(wx.Pen(self.color, 1))
        #つまり 輪郭が緑中が青っぽい色?になる
        dc.DrawCircle(x, y, 100)


        #dc.SetBrush(wx.Brush(wx.Colour(128, 128, 255)))
        #100,100の点から、GREENで囲まれたところ(styleの引数)を、
        #Brushの色で塗りつぶす
        #dc.FloodFill(100,100, "GREEN", style = wx.FLOOD_BORDER)

        #dc.SetBrush(wx.Brush(wx.Colour(128, 255, 128)))
        #dc.SetPen(wx.Pen("RED", 3))
        ##つまり 輪郭が赤中が黄緑色?になる
        #dc.DrawCircle(300 - 100, 100, 100)
        del dc
        self.parent.Refresh(False)


#bufferをなんとか------------------
    #ブラシ(描くペン先)の選別 決定
    def DrawMiniCircle(self, x, y):
        dc = wx.BufferedDC(None, self.parent.buffer)

        # ビットマップ画像をブラシにして描画
        x -= self.parent.brushBitmap.GetWidth() / 2
        y -= self.parent.brushBitmap.GetHeight() / 2
        dc.DrawBitmap(self.parent.brushBitmap, x, y, True)

        ## 円をブラシにして描画
        #dc.SetBrush(wx.Brush(wx.Colour(192, 192, 255)))
        #dc.SetPen(wx.Pen("BLACK", 0))
        #dc.DrawCircle(nx, ny, 16)

        #del dc
        self.parent.Refresh(False)


    #画像表示領域全てを画像として縮小保存
    def gazouTouka(self):
        # 透過したい画像を読み込み
        org = Image.open( 'test.png' )
        # 同じサイズの画像を作成 黒の完全透過の画像
        trans = Image.new('RGBA', org.size, (0, 0, 0, 0))
       
        flg_white = 1
        width = org.size[0]
        height = org.size[1]
       
        for x in xrange(width):
             for y in xrange(height):
                    pixel = org.getpixel( (x, y) )
                    #if 0==x or 0==y:
                    #    continue
                    # 白なら処理しない
                    if pixel[0] == 255 and pixel[1] == 255 and pixel[2] == 255:
                        continue
                   
                    #画像の周りに白い部分が残るため以下の処理をする。
                    if flg_white < 2000:
                        if (pixel[0] < 255 and pixel[0] > 100) and (pixel[1] < 255 and pixel[1] > 100) and (pixel[2] < 255 and pixel[2] > 100):
                            flg_white += 1
                            continue

                    # 白以外なら、用意した画像にピクセルを書き込み
                    trans.putpixel( (x, y), pixel )
       
        # 透過画像を保存
        #ファイルを縮小する、ファイルのビットサイズもちいさくなる
        #self.parent.brushBitmap.SetSize((100,100)) では画像は小さくな
        #っても, ファイルサイズは小さくならない
        trans_resize = trans.resize((100,100))
        trans_resize.save('test.png')
        return


    def OnKeyDownEvent(self, event):
        print "draw_OnKeyDownEvent"
        #g71 c67
        k = event.GetKeyCode()
        print k
        print

        #キーfがおされた
        if 70==k:
            print "f"
            self.key2 = 70
        if self.key2==70:
            #キーfがおされて s か l が押された
            if 83==k or 76==k:
                self.OnKeyDownEvent_gazou(event, k)
                self.key2 = 0

        #キーgがおされた
        if 71==k:
            print "g"
            self.key = 71
        #キーcがおされた
        if 67==k:
            print "c"
            self.mygetcolor()
            self.key = 67
        #キーbがおされた
        if 66==k:
            print "b"
            self.mygetcolor()
            self.key = 66


    def OnLeftButtonEvent(self, event):
        #print "draw_OnLeftButtonEvent"
        if self.key == 71:
            self.OnLeftButtonEvent_gazou(event)
        if self.key == 67:
            self.OnLeftButtonEvent_circle(event)
        if self.key == 66:
            self.OnLeftButtonEvent_brush(event )

    def OnLeftButtonEvent_gazou(self, event):
        print "draw_OnLeftButtonEvent_gazou"
        pos = event.GetPosition()
        if event.LeftDown():
            # マウスの左ボタンを押した
            self.DrawMiniCircle(pos.x, pos.y)
            self.buttonFlag = True
        elif event.Dragging() and self.buttonFlag:
            # マウスカーソルを動かした
            if self.buttonFlag:
                self.DrawMiniCircle(pos.x, pos.y)
        elif event.LeftUp() and self.buttonFlag:
            # マウスの左ボタンを離した
            self.buttonFlag = False


    def OnLeftButtonEvent_circle(self, event):
        print "draw_OnLeftButtonEvent_circle"
        pos = event.GetPosition()
        if event.LeftDown():
            # マウスの左ボタンを押した
            self.Circle(pos.x, pos.y)
            self.buttonFlag = True
        elif event.Dragging() and self.buttonFlag:
            # マウスカーソルを動かした
            if self.buttonFlag:
                self.Circle(pos.x, pos.y)
        elif event.LeftUp() and self.buttonFlag:
            # マウスの左ボタンを離した
            self.buttonFlag = False


    def OnLeftButtonEvent_brush(self, event):
        print "OnLeftButtonEvent_brush"
        pos = event.GetPosition()
        if event.LeftDown():
            # マウスの左ボタンを押した
            self.myBrush(pos.x, pos.y)
            #self.buttonFlag = True
        #elif event.Dragging() and self.buttonFlag:
        #    # マウスカーソルを動かした
        #    if self.buttonFlag:
        #        self.myBrush(pos.x, pos.y)
        #elif event.LeftUp() and self.buttonFlag:
        #    # マウスの左ボタンを離した
        #    self.buttonFlag = False


    def OnKeyDownEvent_gazou(self, event, k):
        print "OnKeyDownEvent_gazou", k
        # sが押された
        if 83==k:
            print "s"
            #元のビットマップをRectできりとり、筆としている
            self.buffer2 = self.parent.buffer.GetSubBitmap(wx.Rect(0,0,100,100))
            #self.parent.buffer = self.buffer2
            self.buffer2.SaveFile( "test.png", wx.BITMAP_TYPE_PNG )
            #self.parent.buffer.SaveFile( "test.png", wx.BITMAP_TYPE_PNG )
            self.gazouTouka()
        # Lが押された
        if 76==k:
            print "L"
            bitmap_brush_image = "test.png"
            image = wx.Image(bitmap_brush_image)
            self.parent.brushBitmap = image.ConvertToBitmap()
            #self.parent.brushBitmap.SetSize((100,100))



class MyFrame(wx.Frame):

    #メニューバー 、ステータスバー,ツールバーなどはFrmae上し
    #か置けないため、paelを作成し、そこで描画する
    ## *args 可変長タプル  **kwargs 可変長辞書
    def __init__(self, parent, *args ,**kargs):
        frame = wx.Frame.__init__(self, parent, *args, **kargs)
        pal = DrawPanel(self)
        self.Show()


if __name__ == '__main__':
    app = wx.App(False)
    MyFrame(None, -1, "Draw Test 3", size=(640, 480))
    app.MainLoop()





G:\MyBackups\goolgedrive\myprg_main\python_my_prg\wxpython\dc\all2_drop_gazou.py
# coding: UTF-8
#wxPythonで画像表示とかドラッグ移動とか勉強中
#http://blawat2015.no-ip.com/~mieki256/diary/201506251.html

"""
#Lきーでファイルダイヤログ呼び出し
#ほか 改変

エクスプローラ上画像ファイルをドラッグアンドドロップしてダブルバッファで
MyFrame上に表示。
MyFrame上でマウスドラッグで画像表示位置を移動

で、ドラッグ機能もモジュール化した

単独でも起動できるがこれをモジュールとしてall2_frame.pyにimportすると
機能がふえる
"""

import wx

#ダミーで0を入れる
myobj = [0]
objs  = []
dn = 0


"""マウスドラッグで移動できるオブジェクト用のクラス"""
#そのオブジェクトの描画、座標の管理などをしている
class MyObj():
    def __init__(self, bmp, x=0, y=0):
        self.bmp = bmp  # bitmapを記録
        self.pos = wx.Point(x, y)  # 表示位置を記録
        self.diff_pos = wx.Point(0, 0)

    """与えられた座標とアタリ判定して結果を返す"""
    def HitTest(self, pnt):
        #pntはマウスpos selfはオブジェクト
        #で、オブジェクト内にマウスが入っていればTrue
        rect = self.GetRect()  # 矩形領域を取得
        return rect.InsideXY(pnt.x, pnt.y)  # 座標が矩形内に入ってるか調べる

    """矩形領域を返す"""
    #ここでは矩形を設定してその中にマウスが入れば、画像の位置
    #をかえているだけで、特別なことは何もしていない。
    #ちょとなれないメソッドがでただけで....
    def GetRect(self):
        return wx.Rect(self.pos.x, self.pos.y,
                       self.bmp.GetWidth(), self.bmp.GetHeight())

    """マウス座標と自分の座標の相対値を記録。"""
    def SavePosDiff(self, pnt):
        #pnt:マウス座標
        """
        マウス座標と自分の座標の相対値を記録。
        この情報がないと、画像をドラッグした時の表示位置がしっくりこない
        """
        #自分:クリックしたオブジェクトのことか?
        #self.drag_obj.SavePosDiff(pos) とあるのでyes
        self.diff_pos.x = self.pos.x - pnt.x
        self.diff_pos.y = self.pos.y - pnt.y


    """与えられたDCを使って画像を描画する"""
    def Draw(self, dc):
        print "MyObj Draw"
        if self.bmp.Ok():
            r = self.GetRect()  # 矩形領域を取得
            # ペンを設定しないと何故か描画できない
            # 私の環境ではok
            #dc.SetPen(wx.Pen(wx.BLACK, 4))
            # 画像を描画
            dc.DrawBitmap(self.bmp, r.x, r.y, True) 



"""ドラッグした画像すべてを描画する  """
#objsにはMyObjのobjが入っている
def all_obj_draw(dc):
    for obj in objs:
        obj.Draw(dc)  # オブジェクトを描画


"""マウス座標と重なってるオブジェクトを返す"""
def FindObj( pnt):
    result = None
    for obj in objs:
        #pntマウスの座標と重なっているobjがあればTrue
        if obj.HitTest(pnt):
            result = obj
    return result


"""ドラッグアンドドロップ担当クラス"""
"""あとで、MyFrameに組み込まれる """
class MyFileDropTarget(wx.FileDropTarget):
    def __init__(self, func):
        wx.FileDropTarget.__init__(self)
        self.func = func
        #self.dc = dc

    #この関数どこからもよびだされていない。
    #内部的によびだされいるのだろう
    #ただ単にドロップ時に実行する関数を指定しているだけ
    #自動的にドロップ時のfilenamesを取得している
    """ファイルをドロップした時の処理"""
    def OnDropFiles(self, x, y, filenames):
        print "OnDropFiles"
        #実験したらわかるが以下のfor文をとおさないことには実際の
        #パスが得られない
        for filepath in filenames:
            #ファイルをドロップした時に実行される関数を以下に設定
            self.evt_foo(filepath, self.func) 

    #ファイルをドロップした時に実際に実行される関数
    def evt_foo(self, filepath, func):
        print "evt_foo"
        x, y = 0, 0

        #ファイルパスから直接ビットマップを作成している?
        b = wx.Bitmap(filepath)
        #画像のファイルパスと座標を受け取っている
        myobj[0] = MyObj(b,  x, y)
        objs.append(myobj[0])
        x += 32
        y += 32
        # 描画更新
        print " func(self.dc)"
        func()


#MyFileDropTargetを組み込む関数
def MetaMyFileDropTarget(main_obj, func):
    # ファイルドロップの対象をフレーム全体に
    #MyFrameにドロップされたら...という設定
    main_obj.droptarget = MyFileDropTarget(func)
    # ファイルドロップ受け入れを設定
    main_obj.SetDropTarget(main_obj.droptarget)



class DropMybind():
    def __init__(self,parent, child):
        # マウスカーソルを動かした時に呼ばれるメソッドを割り当てる
        self.parent = parent
        self.child = child
        self.parent.Bind(wx.EVT_MOTION,        self.child.OnMotionEvent)
        self.parent.Bind(wx.EVT_LEFT_DOWN, self.child.OnLeftButtonDownEvent)
        self.parent.Bind(wx.EVT_LEFT_UP,        self.child.OnLeftButtonUpEvent)
        self.parent.Bind(wx.EVT_KEY_DOWN,  self.child.OnKeyDownEvent)


class DropAction():
    def __init__(self, parent):
        print "dropAction"
        # マウスドラッグ処理用の変数を確保
        self.parent = parent
        self.drag_obj = None
        self.drag_start_pos = wx.Point(0, 0)
   
        """マウスの左ボタンが押された時の処理"""
        #MyFrame上のイベントなのにMyFrame以外のマウスイベントを
        #感知できるのか?
        #私の環境では検知できない
        #ほかのウィンドウでドラッグ開始 MyFrameでドラッグ終了
        #しても、MyFrame上のマウス移動 upさえ検知できず。
    def OnLeftButtonDownEvent(self, event):
        print "drop_OnLeftButtonDownEvent"
        # マウス座標を取得
        pos = event.GetPosition() 
        global dn
        dn += 1
        print "mouse down"
        print dn, pos
   
        """マウス座標と重なってるオブジェクトを取得"""
        obj = FindObj(pos) 
   
        #objが空でないなら、何かobjがあったら
        #isのほうが==より処理がはやい
        if obj is not None:
            #ドラッグ移動するオブジェクトを記憶
            self.drag_obj = obj 
            # ドラッグ開始時のマウス座標を記録
            #以下の変数どこにもつかわれていない
            self.drag_start_pos = pos 
            #マウス座標と自分の座標の相対値を記録。"""
            #自分:objのことだろう
            #posでマウスposを引数にしている
            self.drag_obj.SavePosDiff(pos)
   
   
    """マウスの左ボタンが離された時の処理"""
    def OnLeftButtonUpEvent(self, event):
        print "drop_OnLeftButtonUpEvent"
        if self.drag_obj is not None:
            pos = event.GetPosition()
            self.drag_obj.pos.x = pos.x + self.drag_obj.diff_pos.x
            self.drag_obj.pos.y = pos.y + self.drag_obj.diff_pos.y
            print "mouse up"
            print self.drag_obj.pos.x , self.drag_obj.pos.y
   
        self.drag_obj = None
        print "mouse up None"

        """ parentの関数の呼び出し"""   
        self.parent.InitBuffer()
   
   
    "マウスカーソルが動いた時の処理"""
    def OnMotionEvent(self, event):
        print "drop_OnMotionEvent"
        if self.drag_obj is None:
            # ドラッグしてるオブジェクトが無いなら処理しない
            return
       
        # ドラッグしてるオブジェクトの座標値をマウス座標で更新
        pos = event.GetPosition()
        self.drag_obj.pos.x = pos.x + self.drag_obj.diff_pos.x
        self.drag_obj.pos.y = pos.y + self.drag_obj.diff_pos.y

        """ parentの関数の呼び出し"""   
        self.parent.InitBuffer()  # 描画更新


    #Lキーをおしてファイルダイヤログをひらく
    def OnKeyDownEvent(self, event):
        print "drop_OnKeyDownEvent"
        k = event.GetKeyCode()
        print k
        # キーLがおされた
        if 76==k:
            self.openDialog()

    def openDialog(self):
        dp = "E:\MyBackups\goolgedrive\myprg_main\python_my_prg\wxpython\dc\gazou_drop"
        #osのファイルダイヤログをよびだす
        # 引数 dp 開くフォルダ "":デフォルトのファイル名 
        # *.png : pngファイルだけ表示

        """Dialogの親は、parentになる"""   
        d = wx.FileDialog(self.parent, "画像ファイル", dp,"","*.png")
        d.ShowModal()
        d.Destroy()


"""ダブルバッファで表示するFrame"""
class DrawPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.InitBuffer()

        da = DropAction(self)
        DropMybind(self, da)

        # RefreshによってOnPaintがよばれている
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_SIZE, self.OnSize)

        """ペン先に画像を使う"""
        #pensaki.PenGazou(self)



    """画面書き換え要求があった時に呼ばれる処理"""
    def OnPaint(self, event=None):
        print "OnPaint"
        dc = wx.BufferedPaintDC(self, self.buffer)


    """ウインドウサイズが変更された時に呼ばれる処理"""
    #かなり複雑になるのでこのイベントやめる
    def OnSize(self, event=None):
        print "OnSize"
        pass


    """描画更新"""
    def InitBuffer(self):
        #print "UpdateDrawing"
        self.buffer = wx.EmptyBitmap(1280, 708)
        dc = wx.BufferedDC(None, self.buffer)
        dc.SetBackground(wx.Brush('white'))
        dc.Clear()  # デバイスコンテキストでクリア
        self.Draw(dc)  # 実際の描画処理
        # Falseを指定して背景を消さなくしたら画面のちらつきが出なくなった
        self.Refresh(eraseBackground=False)


    """実際の描画処理"""
    def Draw(self, dc):
        #print "Draw"

        dc.SetBrush(wx.Brush(wx.Colour(128, 255, 128)))
        dc.SetPen(wx.Pen("RED", 3))
        #つまり 輪郭が赤中が黄緑色?になる
        dc.DrawCircle(0, 0, 10)


        #objsで今までドラッグした画像を保存しておいて
        #ドラッグ完了すると、ドラッグ中の画像もふくめて
        #描画している

        """ドラッグした画像すべてを描画する  """
        all_obj_draw(dc)



class MyFrame(wx.Frame):
    #メニューバー 、ステータスバー,ツールバーなどはFrmae上し
    #か置けないため、paelを作成し、そこで描画する
    ## *args 可変長タプル  **kwargs 可変長辞書
    def __init__(self, parent, *args ,**kargs):
        frame = wx.Frame.__init__(self, parent, *args, **kargs)

        pal = DrawPanel(self)

        #画像、またはエクスプローラ上の画像ファイルをドラッグした時に
        #描画のアップデートをする関数を指定する
        func = pal.InitBuffer
        #画像のドラッグ機能をMyFrameに組み込む Panelには組み込めない
        #ようだ
        MetaMyFileDropTarget(self, func)
        self.Show()


if __name__ == '__main__':
    app = wx.App(False)
    MyFrame(None, -1, "Draw Test 4", size=(800, 600))
    app.MainLoop()



G:\MyBackups\goolgedrive\myprg_main\python_my_prg\wxpython\dc\all2_mytoolbar.py
# coding: UTF-8

import wx

class MyFrame(wx.Frame):
    #メニューバー 、ステータスバー,ツールバーなどはFrmae上し
    #か置けないため、paelを作成し、そこで描画する
    ## *args 可変長タプル  **kwargs 可変長辞書
    def __init__(self, parent, *args ,**kargs):
        frame = wx.Frame.__init__(self, parent, *args, **kargs)
        pnl = wx.Panel(self)
        myToolBar(self)   
        self.Show()


def myToolBar(obj):
    toolbar = obj.CreateToolBar(wx.TB_LEFT)

    #以下のように画像ファイルを読み込んで SetSizeでサイズを変更しようと
    #したら、切り取られた形でサイズが変更された。Resize か Rescaleのコマ
    #ンドが Bitmapにはない。
    # で Image を使って画像表示 Rescaleをする。
    #bm1 = wx.Bitmap('./move.jpg')
    #bm1.SetSize((20,20))

    bm1_image = "move.jpg"
    image1 = wx.Image(bm1_image)
    image1.Rescale(20,20)
    bm1 = image1.ConvertToBitmap()

    bm2_image = "pen.jpg"
    image2 = wx.Image(bm2_image)
    image2.Rescale(20,20)
    bm2 = image2.ConvertToBitmap()

    toolbar.AddLabelTool(wx.ID_ANY, '移動', bm1)
    toolbar.AddLabelTool(wx.ID_ANY, '描画', bm2)

    toolbar.Realize()


if __name__ == '__main__':
    app = wx.App(False)
    MyFrame(None, -1, "Draw Test 4", size=(800, 600))
    app.MainLoop()


G:\MyBackups\goolgedrive\myprg_main\python_my_prg\wxpython\dc\all2_menu.py
# coding: UTF-8

import wx

class MenuFrame(wx.Frame):
    #メニューバー 、ステータスバー,ツールバーなどはFrmae上し
    #か置けないため、paelを作成し、そこで描画する
    ## *args 可変長タプル  **kwargs 可変長辞書
    def __init__(self, parent, *args ,**kargs):
        frame = wx.Frame.__init__(self, parent, *args, **kargs)
        myMenuBar(self)
        self.Show()

""" 以下のコードを myMenuBar で置き換える"""
    #menuBar = wx.MenuBar()
    #self.SetMenuBar(menuBar)
    #menu1 = wx.Menu()
    #menu2 = wx.Menu()
    #menu3 = wx.Menu()
    #menuBar.Append(menu1, 'Menu1')
    #menuBar.Append(menu2, 'Menu2')
    #menuBar.Append(menu3, 'Menu3')

    #menuItem11 = wx.MenuItem(menu1, wx.ID_ANY, 'MenuItem11')
    #menuItem12 = wx.MenuItem(menu1, wx.ID_ANY, 'MenuItem12')
    #menuItem13 = wx.MenuItem(menu1, wx.ID_ANY, 'MenuItem13')
    #menu1.AppendItem(menuItem11)
    #menu1.AppendItem(menuItem12)
    #menu1.AppendItem(menuItem13)

    #menuItem21 = wx.MenuItem(menu2, wx.ID_ANY, 'MenuItem21')
    #menuItem22 = wx.MenuItem(menu2, wx.ID_ANY, 'MenuItem22')
    #menuItem23 = wx.MenuItem(menu2, wx.ID_ANY, 'MenuItem23')
    #menu2.AppendItem(menuItem21)
    #menu2.AppendItem(menuItem22)
    #menu2.AppendItem(menuItem23)

    #menuItem31 = wx.MenuItem(menu3, wx.ID_ANY, 'MenuItem31')
    #menuItem32 = wx.MenuItem(menu3, wx.ID_ANY, 'MenuItem32')
    #menuItem33 = wx.MenuItem(menu3, wx.ID_ANY, 'MenuItem33')
    #menu3.AppendItem(menuItem31)
    #menu3.AppendItem(menuItem32)
    #menu3.AppendItem(menuItem33)
""" end ------------------------------- """


#menu_s にメニューバーに加えたいメニューを入れる
#menu_item_s に 各メニューに加えたいアイテムをいれる
def myMenuBar(parent):
    menuBar = wx.MenuBar()
    parent.SetMenuBar(menuBar)

    menu_s = 'Menu1, Menu2, Menu3'
    # , を区切り文字として menu_s のリストが出来る
    # ['Menu1','Menu2','Menu3'] とこんな感じになる
    # はじめから上の形式でコードを書いておけばいいが、入力時にいちいち
    # ’’で区切りのが面倒なので....
    menu_name = menu_s.split(',')
    menu_num = len(menu_name)
    menu = []

    menu_item_s = []
    menu_item_s.append('menutem11, menutem12, menutem13')
    menu_item_s.append('menutem21, menutem22, menutem23')
    #menu_item_s.append('')
    menu_item_s.append('menutem31, menutem32, menutem33')
    menu_item_name = []

    # menu_item = [[], [], [] ]  menu_num が3つだとこうなる
    menu_item = [[] for i in range(menu_num)]

    for h in range(menu_num):
        menu_item_name.append( menu_item_s[h].split(',') )

    for i in range(menu_num):
        menu.append( wx.Menu() )
        menuBar.Append(menu[i], menu_name[i])

        for j in range(len(menu_item_name[i])):
            if menu_item_name[i] == ['']:
                # メニューアイテムがもしなかったら、なにもしない
                pass
            else:
                menu_item[i].append( wx.MenuItem(menu[i], wx.ID_ANY, menu_item_name [i] [j]) )
                menu[i].AppendItem(menu_item[i][j])


        #メニューバー、メニュー、メニューアイテム、の通常の作成手順は
        #以下のとおり
        #menuBar = wx.MenuBar()
        #self.SetMenuBar(menuBar)
       
        #menu1 = wx.Menu()
        #menuBar.Append(menu1, 'Menu1')

        #menuItem11 = wx.MenuItem(menu1, wx.ID_ANY, 'MenuItem11')
        #menu1.AppendItem(menuItem11)


if __name__ == '__main__':
    app = wx.App(False)
    MenuFrame(None, -1, "Draw Test 4", size=(800, 600))
    app.MainLoop()








0 件のコメント:

コメントを投稿

About

参加ユーザー

連絡フォーム

名前

メール *

メッセージ *

ページ

Featured Posts