wxpython マウスを筆にして絵を描くhttps://hannsihannsyou.blogspot.com/2020/03/wxpython.html
上をdc描画動作、マウス動作を親クラスにしてコードを書き直した。wxpython/お絵かき5/paintBuffer4.py
1 # coding: UTF-8
2
3 #@@@ draw_hinagata.pyのモジュール化をしたが、使いにくいのでクラス
4 #@@@ にしてその機能を子クラスとして使う事にする
5 #@@@ PaintBuffer4.py dc描画イベント マウスイベント を受け持つ
6
7
8 #参考サイト
9 #まくまくpythonノート
10 #https://maku77.github.io/python/wxpython/graphics.html
11
12
13 import wx
14
15 # wx.Panelとwx.Windowの違いがわからない。
16 # 別に変えても
17 #class PaintBuffer(wx.Panel):
18 class PaintBuffer(wx.Window):
19 def __init__(self, parent):
20 wx.Window.__init__(self, parent, -1)
21 #wx.Panel.__init__(self, parent, -1)
22
23 self.color = "Green"
24 self.thickness = 10
25
26 #创建一个画笔
27 self.pen = wx.Pen(self.color, self.thickness, wx.SOLID)
28 self.bf_size1 = None
29 self.lines = []
30 self.curLine = []
31 self.pos = (0, 0)
32 self.InitBuffer()
33 self.buffer = None
34 #イベント
35 self.Bind(wx.EVT_PAINT, self.OnPaint)
36 self.Bind(wx.EVT_SIZE, self.OnSize)
37 self.Bind(wx.EVT_IDLE, self.OnIdle)
38 self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
39 self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
40 self.Bind(wx.EVT_MOTION, self.OnMotion)
41
42
43 """初期化"""
44 def InitBuffer(self):
45 print "InitBuffer"
46 self.bf_size2 = self.GetClientSize()
47
48 # ウインドウサイズで、空の描画用バッファ(bitmap)を作成
49 #ポインタとかおもった。可変長変数。
50 #タプルを関数に渡すときに * を付けると、タプルの各要素を
51 #関数の引数として展開されて渡される
52 self.buffer = wx.EmptyBitmap(*self.bf_size2)
53 dc = wx.BufferedDC(None, self.buffer)
54 self.w_size2 = dc.GetSize()
55 dc.SetBackground(wx.Brush('white'))
56 # デバイスコンテキストでクリア、これがないと画面が真っ暗になる
57 dc.Clear()
58 #self.Draw(dc) # 実際の描画処理
59 # Falseを指定して背景を消さなくしたら画面のちらつきが出なくなった
60 #self.Refresh(eraseBackground=False)
61 self.DrawToBuffer(dc)
62 self.reInitBuffer = False
63
64
65 #EVT_PAINT イベントのハンドラの中で描画処理をバッファリングしたい場合
66 #は、wx.BufferedDC の代わりに wx.BufferedPaintDC を使用します。
67 def OnPaint(self, evt):
68 print "OnPaint"
69 dc = wx.BufferedPaintDC(self, self.buffer)
70
71 """ウインドウサイズが変更された時に呼ばれる処理"""
72 def OnSize(self, evt):
73 print "OnSize"
74 self.InitBuffer()
75
76 #アイドル時に実行
77 #reInitBufferのフラグによって無制限にアイドル時の実行を
78 #さける
79 def OnIdle(self, event):
80 print "OnIdle"
81 if self.reInitBuffer:
82 self.InitBuffer()
83
84 def OnLeftDown(self, event):
85 print "OnLeftDown"
86 self.curLine = []
87
88 #获取鼠标位置
89 self.pos = event.GetPositionTuple()
90
91 #https://uyamae.hatenadiary.org/entry/20090319/1237437401
92 #前回やったラバーバンド処理は、マウスがウィンドウの外に出ると
93 #挙動がおかしくなってしまいます。ウィンドウズのプログラミング
94 #ではこういう場合にはマウスキャプチャーを使います。マウスカー
95 #ソルが画面外に出てもマウスのイベントを受け取り続けると言うも
96 #のです。
97 #CaptureMouse()を呼び出してキャプチャー開始, ReleaseMouse()
98 #を呼び出してキャプチャー終了です。
99 self.CaptureMouse()
100
101 def OnLeftUp(self, event):
102 if self.HasCapture():
103 self.lines.append((self.color, self.thickness,
104 self.curLine, self.w_size1))
105 self.curLine = []
106 self.ReleaseMouse()
107
108 def OnMotion(self, event):
109 #下一行ウィンドウのサイズを得ようと思っただけで特にいらない
110 self.bf_size1 = self.GetClientSize()
111 if event.Dragging() and event.LeftIsDown():
112 dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
113 self.w_size1 = dc.GetSize()
114 self.drawMotion(dc, event)
115 event.Skip()
116
117 #マウスdownからupまでMotionしたところまで線をひく
118 #そのデータを配列に記録する
119 def drawMotion(self, dc, event):
120 dc.SetPen(self.pen)
121 newPos = event.GetPositionTuple()
122 #2要素のタプル同士を足すと4要素のタプルになる
123 coords = self.pos + newPos
124 dc.DrawLine(*coords)
125 self.curLine.append(coords)
126 self.pos = newPos
127
128
129 #描画
130 #wx.BufferedDC は、あるデバイス・コンテキストへの描画処 理をバッファ
131 #リングし、一度に描画内容を反映するようにしま す。 例えば、
132 #wx.ClientDC への連続した描画を wx.BufferedDC でバッファリングすれ
133 #ば、画面上での描画のち らつきを防ぐことができます。
134 def DrawToBuffer(self, dc):
135 print "DrawToBuffer"
136 pass
137
138
~
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 #@@@ペンでマウスの動きに沿って線を描く
5 #@@@ paintBuffer4.pyはdcの描画に関するイベントを全て引き受ける
6 #@@@ マウスイベントも引き受ける
7
8
wxpython/お絵かき5/pen_draw4.py
9 #参考サイト
10 #wxPython: 简单的绘图例子
11 # http://www.jeepxie.net/article/761366.html
12
13 from paintBuffer4 import PaintBuffer
14 import wx
15
16
17 class MyFrame(wx.Frame):
18 def __init__(self):
19 wx.Frame.__init__(self, None, -1, "Panit Frame",
20 size = (800, 600))
21 PaintWindow(self)
22 self.Show()
23
24 class PaintWindow(PaintBuffer):
25 def __init__(self, parent):
26 PaintBuffer.__init__(self, parent)
27 print "PaintWindow"
28
29 #初期時、アイドル時 InitBuffer()から以下が実行される
30 def DrawToBuffer(self, dc):
31 print "DrawToBuffer"
32 #ウィンドウの大きさが変わってもその相対位置にびょうが
33 #しようとしたができない
34 #floatをいれないと計算が0となっていた。ロス時間3h
35 for colour, thickness, line, w_size1 in self.lines:
36 pen = wx.Pen(colour, thickness, wx.SOLID)
37 dc.SetPen(pen)
38 w1, h1 = w_size1
39 w2, h2 = self.w_size2
40 for coords in line:
41 x1, y1, x2, y2 = coords
42 x1 = float(x1)
43 y1 = float(y1)
44 x2 = float(x2)
45 y2 = float(y2)
46 x1 = x1/w1*w2
47 x2 = x2/w1*w2
48 y1 = y1/h1*h2
49 y2 = y2/h1*h2
50 dc.DrawLine(x1, y1, x2, y2)
51 #dc.DrawLine(*coords)
52
53 #testコード
54 def DrawLines2(self, dc):
55 #dc.SetBackground(wx.Brush('white'))
56
57 #Clear 現在の背景ブラシを使用してデバイスコンテキストを
58 #クリアします
59 #これを実行しないと背景が真っ黒になる
60 #dc.Clear()
61
62 dc.SetPen(wx.Pen('blue', 3))
63 dc.DrawText('Hoge hoge', 10, 10)
64 dc.DrawLine(10, 10, 200, 10)
65 dw, dh = dc.GetSize()
66 dc.SetPen(wx.Pen('blue', 3))
67 dc.DrawCircle(dw/2, dh/2, 50)
68 #以下のコードがないと最大化した時元の位置に円が描画したままと
69 #なる
70 #self.Refresh(False)
71
72 # #使われていない
73 # def SetColor(self, color):
74 # self.color = color
75 # self.pen = wx.Pen(self.color, self.thickness, wx.SOLID)
76 #
77 # #使われていない
78 # def SetThickness(self, num):
79 # self.thickness = num
80 # self.pen = wx.Pen(self.color, self.thickness, wx.SOLID)
81
82
83 if __name__ == '__main__':
84 app = wx.App()
85 MyFrame()
86 app.MainLoop()
~
~
~
~
:
0 件のコメント:
コメントを投稿