Pythonで線画ツール その5

アンカーの選択機能をつけます。


まず、オブジェクトの選択方法ですが、利用できそうなCanvasのメソッドとしましては、tag_bind、find_closest、find_overlappingとかですかね。

Canvasのメソッド
http://kansai.anesth.or.jp/gijutu/python/man-gui/man-canvas.php#Canvas-Method

今回はtag_bind使います。他は返すのがidで、アンカーの他に曲線やら補助線やら表示されますから、選択しにくいんじゃないかと思ったからです。

まずはAncクラスに選択できるための準備ですね。

・selectedという変数を追加します。こいつはbooleanで選択状態のときTrueで、非選択状態のときFalseになるようにします。
・selectedを操作するためのメソッドselectも追加します。
・選択状態なのがわかるように、選択状態のアンカーには黄色い円をバックに表示させようと思うので、それの表示用メソッドdrawSelectを追加します。
・アンカー非選択時に、小さなアンカーを選択しやすくするためのセンサー役の透明な円を表示させるメソッドdrawSensorを追加します。
・アンカーも選択円もセンサー円も一くくりに扱いたいので、同じtagを持たすためにtagという変数をもたせます。

そいで、それらを機能させるために__init__をこねくり回したAncクラスがこちら。
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
class Anc:

canvas = None
width = 1.0
selected = False

def __init__(self,x,y):
self.x = x
self.y = y
self.tag = "anc_"+str(id(self))
self.drawSensor()
self.drawAnc()

def select(self,event):
self.selected = True
self.canvas.delete(self.tag)
self.drawSensor()
self.drawSelect()
self.drawAnc()

def drawAnc(self):
self.canvas.create_oval(self.x,self.y,self.x,self.y,
outline="red",tags=self.tag,
width = 5)
def drawSelect(self):
size = 10
self.canvas.create_oval(self.x-size,self.y-size,
self.x+size,self.y+size,
tags=self.tag,fill="yellow",outline="")
def drawSensor(self):
size = 20
self.canvas.create_oval(self.x-size,self.y-size,
self.x+size,self.y+size,
tags=self.tag,fill="",outline="")



タグ名にanc_を付加しないととうまく働かない。参照になってるかと思ってcopyとかつかったけど駄目だった。理由わからん^^

次にバインドさせます。

新しいタグを作ったときにバインドすればよいので、EditMethodのaddにバインドさせてみます。そのためにcanvasも参照しときます。
EditMethod
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
class EditMethod:

def __init__(self,main):
self.ObjList = main.ObjList
self.canvas = main.canvas

def add(self,event):
anc = Anc(event.x,event.y)
self.ObjList[0].AncList.append(anc)
self.canvas.tag_bind(anc.tag,"",anc.select)
self.ObjList[0].repaint()

こんな感じで__init__がどんどん増えていきますw。それなら初めからEditMethod.canvas = MainCanvas.canvasしとくとか、・・・だから、そもそも共有するってことがオブジェクト指向のカプセル化に反しtえsdgはkw@ぺlfkdさ;gh

その後、継承やらMixinやらで構造改革が何度もなされるわけですが、ともあれ、選択機能がついたわけです。ホントに選択だけで、選択解除がないので、Ancクラスをまた変えて、
・非選択用のメソッドdelselectを追加
・選択切り替えようのメソッドselectionを追加
それで、バインドはselectionにするようにします。

Ancクラスのdeselectメソッド
1:
2:
3:
4:
    def deselect(self,event):
self.selected = False
self.canvas.delete(self.tag)
self.drawSensor()
self.drawAnc()


Ancクラスのselectionメソッド
1:
2:
3:
4:
    def selection(self,event):
if self.selected is True:
self.deselect(event)
else:
self.select(event)


EditMethodのaddメソッド
1:
2:
3:
4:
    def add(self,event):
anc = Anc(event.x,event.y)
self.ObjList[0].AncList.append(anc)
self.canvas.tag_bind(anc.tag,"",anc.selection)
self.ObjList[0].repaint()


これで選択、非選択の切り替えができるようになったんですが、これ不便ですよね。だって、常に追加選択の状態になってるわけです。やっぱ普通は、クリックしたときはそれだけが選択されて、Shift+クリックで追加選択ですよ。

これじゃいかん! ということで、アンカーの選択続きます^^

目次へ

ここまで
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
import Tkinter as Tk

class MainCanvas:

canvas = None
ObjList = []

def __init__(self, window, width, height):

self.canvas = Tk.Canvas(window, bg="white", width=width, height=height)
self.canvas.pack()
Obj.canvas = self.canvas
Anc.canvas = self.canvas

self.canvas.bind("", self.onLeftPress)

obj = Obj()
self.ObjList.append(obj)

def onLeftPress(self,event):
method = EditMethod(self)
method.add(event)

class EditMethod:

def __init__(self,main):
self.ObjList = main.ObjList
self.canvas = main.canvas

def add(self,event):
anc = Anc(event.x,event.y)
self.ObjList[0].AncList.append(anc)
self.canvas.tag_bind(anc.tag,"",anc.selection)
self.ObjList[0].repaint()

class Obj:

canvas = None
color = "green"
AncList = []

def __init__(self):
return

def repaint(self):
if len(self.AncList) > 1:
self.canvas.delete("obj")
self.drawLine()
self.drawCurve()

def drawCurve(self):
ls = []
for a in self.AncList:
ls.append(a.x)
ls.append(a.y)
self.canvas.create_line(ls,fill=self.color,width=2,
smooth=True,tags="obj")

def drawLine(self):
ls = []
for a in self.AncList:
ls.append(a.x)
ls.append(a.y)
self.canvas.create_line(ls,fill="red",width=1,tags="obj")


class Anc:

canvas = None
width = 1.0
selected = False

def __init__(self,x,y):
self.x = x
self.y = y
self.tag = "anc_"+str(id(self))
self.drawSensor()
self.drawAnc()

def selection(self,event):
if self.selected is True:
self.deselect(event)
else:
self.select(event)

def select(self,event):
self.selected = True
self.canvas.delete(self.tag)
self.drawSensor()
self.drawSelect()
self.drawAnc()

def deselect(self,event):
self.selected = False
self.canvas.delete(self.tag)
self.drawSensor()
self.drawAnc()

def drawAnc(self):
self.canvas.create_oval(self.x,self.y,self.x,self.y,
outline="red",tags=self.tag,
width = 5)
def drawSelect(self):
size = 10
self.canvas.create_oval(self.x-size,self.y-size,
self.x+size,self.y+size,
tags=self.tag,fill="yellow",outline="")
def drawSensor(self):
size = 20
self.canvas.create_oval(self.x-size,self.y-size,
self.x+size,self.y+size,
tags=self.tag,fill="",outline="")

def main():
window = Tk.Tk()
main = MainCanvas(window,400,300)
window.mainloop()


if __name__ == '__main__':
main()


関連記事

コメント

コメントの投稿

非公開コメント

このブログについて
□ ブログ内容
決まった趣旨はありません。
興味を持ったこと・日常で行ったことを何でも書きます。

3DCG・プログラミングなどが多めです。

□ 現在の活動
・ウェブサイト制作
 (http://tiblab.net)
・3Dゲーム制作
 (コックパニック)
検索フォーム
ユーザータグ

Blender キャプチャ blendファイル BGE Python GameEngine ムービー Android CG  Red5 Terragen C# C++ 

カテゴリー
プロフィール

TiBra

Author:TiBra
趣味でCG制作、プログラミング等を行っています。メイカーズに憧れています。

ネットを通じた交流を広げたく思っていますので、コメント・メールはお気軽にどぞー

戯言程度のことは、こちらのブログに投稿しています。基本戯言なので、実質移転しているようなものです。

Mail:tibraあっとlive.jp
HP:TibLabmemocode
動画:VimeoFC2動画ニコニコ
ファイル:SkyDrive
企画:3Dゲーム作業実況

Blogリンク
不都合がございましたらご連絡ください。
当ブログのリンクバナー
FC2 ID
FC2カウンター
RSSフィード+解析コード