2013年05月07日 星期二 14:56
在component中实现了一些事件用来完成图形绘制和操作。
功能已经在component中实验通过了。
但是component中没有提供类似plot中的x,y坐标和grid,的自动重绘。
因此希望将一系列的鼠标、按键事件移植到plot中。
在继承plot中除了normal_mouse_leave()方法之外
没有发现可以覆盖的方法,
在chaco中可以调用Tool实现一些需求,
但是不能完全满足,
所有希望在chaco的plot中添加或者捕获鼠标事件,或者在component中添加类似plot中的x\y坐标,和grid,的重绘功能。
不知道有没有好的办法。
请大家指点指点。
2013年05月08日 星期三 06:40
我觉得应该通过添加Tool实现响应鼠标事件,你可以仿照现有的Tool类,例如那个可以拖动缩放的Tool。
2013年05月12日 星期日 19:11
谢谢若愚哥哥,已经仿造你的书中的二次开发例子完成了同时实现“添删改查”的工具。
# -*- coding:utf-8 -*-
__author__ = 'Administrator'
__time__ = "上午9:55"
import numpy as np
from numpy import sort, array
from numpy.random import random
from traits.api import (HasTraits, Instance, List, Enum,
Float, Color, Tuple, Range, Property, Event, Int)
from traitsui.api import Item, View, HGroup
from chaco.api import Plot, ArrayPlotData, AbstractController
from chaco.api import AbstractOverlay, ScatterInspectorOverlay
###1###
from enable.api import ComponentEditor, Component, Line, Pointer, color_table
from enable.colors import ColorTrait
import copy
import sys
sys.path.append("..")
from Model.Polygon import Polygon
from Model.Point import Point
def convert_color(c):
if c.__class__.__name__ == "QColor":
return (c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0)
else:
return (c[0] / 255.0, c[1] / 255.0, c[2] / 255.0)
class PolygonOverlay(AbstractOverlay):
cur_line = Instance(Line, args=())
metadata = Property(depends_on='component')
line_color = ColorTrait("blueviolet")
polygons = List(Polygon)
move_polygon_points = np.array([])
def _get_metadata(self):
return self.component.index.metadata
def overlay(self, other_component, gc, view_bounds=None, mode="normal"):
if "cur_line" in self.metadata and self.metadata["cur_line"] != []:
self.cur_line.points = copy.copy(self.metadata["cur_line"])
gc.save_state()
self.cur_line.line_color = self.line_color
self.cur_line.vertex_color = self.line_color
self.cur_line._draw(gc)
gc.restore_state()
if "polygons" in self.metadata:
for i in self.metadata["polygons"]:
print i.line.points, "polygons"
self.polygons = self.metadata["polygons"]
gc.save_state()
gc.set_antialias(True)
gc.set_stroke_color(color_table["dodgerblue"])
gc.set_fill_color(color_table["lightskyblue"])
gc.set_alpha(0.4)
gc.set_line_width(2)
gc.set_line_dash(None)
for i in self.polygons:
if [] != i.line.points:
gc.lines(i.get_points())
else:
print 'null'
gc.draw_path()
gc.restore_state()
if self.metadata.has_key("move_polygon") and self.metadata["move_polygon"] is not None:
print self.metadata["move_polygon"], "move_polygon"
self.move_polygon_points = copy.copy(self.metadata["move_polygon"])
gc.save_state()
gc.set_antialias(True)
#gc.set_stroke_color(convert_color(self.polygon_color) + (0.8,))
#gc.set_fill_color(convert_color(self.polygon_color) + (0.4,))
gc.set_stroke_color(color_table["dodgerblue"])
gc.set_fill_color(color_table["lightskyblue"])
gc.set_alpha(0.4)
gc.set_line_width(2)
gc.set_line_dash(None)
gc.lines(self.move_polygon_points)
gc.draw_path()
gc.restore_state()
class PolygonController(AbstractController):
metadata = Property(depends_on='component')
def _get_metadata(self):
return self.component.index.metadata
polygons = List(Polygon)
moving_x = Float
moving_y = Float
index = Int
moving_polygon = Instance(Polygon)
temp_polygon = Instance(Polygon)
polygon_color = Color((0, 0, 0))
#画线参数
draw_polygon = Instance(Polygon)
points = List()
draw_point = (0, 0)
line_color = ColorTrait("blueviolet")
cur_line = Instance(Line, args=())
#cur_line.line_color = ColorTrait("blueviolet")
event_state = Enum("Normal", "Draw", "Drawing", "Move", "Moving", "Removeing", "Exchange", "Dragging")
cur_line_update = Event
moving_polygon_update = Event
_removeing_polygon_updata = Event
_normal_flush_updata = Event
_ecchange_polygon_updata = Event
#类参数
distans_point = Int(4)
# Cursor shape for non-tool use.
original_cursor = Pointer("arrow")
# Cursor shape for drawing.
normal_cursor = Pointer("pencil")
# Cursor shape for deleting points.
delete_cursor = Pointer("bullseye")
# Cursor shape for moving points.
move_cursor = Pointer("sizing")
def __init__(self, component, *args, **kw):
super(PolygonController, self).__init__(component, *args, **kw)
self.metadata["line_color"] = copy.copy(self.line_color)
self.metadata["fuck"] = random(20)
print self.metadata["fuck"], "fuck"
self.draw_polygon = Polygon()
self.event_state = "Normal"
def Find_Polygon(self, x, y):
from kiva.agg import points_in_polygon
for polygon in self.polygons[::-1]:
if polygon is not None:
self.temp_polygon = polygon
self.index = self.polygons.index(polygon)
if points_in_polygon((x, y), polygon.get_points()):
print "find it"
return polygon
print "find Nothing"
return None
def Move_right_down(self, event):
polygon = self.Find_Polygon(event.x, event.y)
if polygon is not None:
self.moving_x = event.x
self.moving_y = event.y
self.moving_polygon = copy.copy(polygon)
self.event_state = "Moving"
#self._update_cur_line()
self.Moving_mouse_move(event)
def Moving_mouse_move(self, event):
print event.x, event.y, self.moving_x, self.moving_y, "x,y"
self.moving_polygon.update_x_y(event.x - self.moving_x, event.y - self.moving_y)
self.moving_x = event.x
self.moving_y = event.y
print self.moving_polygon.line.points, 'moving_mouse'
self._update_move_polygon()
def Moving_right_up(self, event):
"""
移动操作结束,回到normal状态
"""
self.event_state = "Normal"
#self.polygons[self.moving_polygon]=self.moving_polygon
print self.index, "index"
self.polygons.remove(self.temp_polygon)
#self.polygons[self.index].line.points = copy.copy(self.moving_polygon.line.points)
self.polygons.append(self.moving_polygon)
for i in self.metadata["polygons"]:
print i.line.points, "polygons_move"
self._update_move_polygon()
self._re_set_MoveTool()
def _re_set_MoveTool(self):
#self.moving_polygon.line.points = []
#self.index = 0
self.metadata["move_polygon"] = None
def Draw_left_down(self, event):
over = self._over_point(event)
if over is not None:
if event.control_down:
# Delete the point
self.points.pop(over)
#self.cur_line.points = list(self.component.map_screen(array(self.points)))
self.cur_line.points = copy.copy(self.points)
self._update_cur_line()
else:
self.event_state = "Dragging"
self._dragged = over
self._drag_new_point = False
self.Dragging_mouse_move(event)
else:
self.points.append((event.x, event.y))
#print self.points[0].x,self.points[0].y
print len(self.points)
self.event_state = "Drawing"
self.Drawing_mouse_move(event)
return
def Dragging_left_up(self, event):
self.event_state = "Draw"
def Dragging_mouse_move(self, event):
""" Handles the user moving the mouse while in the 'dragging' state.
The screen is updated to show the new mouse position as the end of the
line segment being drawn.
"""
#mouse_position = self._map_data((event.x, event.y))
mouse_position = [event.x, event.y]
self.points[self._dragged] = mouse_position
#self.line.points = list(self.component.map_screen(array(self.points)))
self.cur_line.points = copy.copy(self.points)
self._update_cur_line()
def Draw_mouse_move(self, event):
over = self._over_point(event)
if over is not None:
if event.control_down:
event.window.set_pointer(self.delete_cursor)
else:
event.window.set_pointer(self.move_cursor)
else:
event.handled = False
event.window.set_pointer(self.normal_cursor)
self._update_cur_line()
return
def Drawing_mouse_move(self, event):
print self.points[-1]
self.points[-1] = [event.x, event.y]
self.cur_line.points = copy.copy(self.points)
self._update_cur_line()
def Drawing_left_up(self, event):
self.event_state = "Draw"
#self.request_redraw()
self._update_cur_line()
def _update_cur_line(self):
self.metadata["cur_line"] = copy.copy(self.cur_line.points)
self.cur_line_update = True
def _update_move_polygon(self):
self.metadata["polygons"] = copy.copy(self.polygons)
print self.moving_polygon.line.points, "abck"
self.metadata["move_polygon"] = copy.copy(self.moving_polygon.line.points)
self.moving_polygon_update = True
def _is_near_point(self, point, event):
""" Determines if the pointer is near a specified point.
"""
event_point = (event.x, event.y)
return ((abs(point[0] - event_point[0]) + \
abs(point[1] - event_point[1])) <= self.distans_point)
def _over_point(self, event):
""" Return the index of a point in *points* that *event* is 'over'.
Returns None if there is no such point.
"""
for i, point in enumerate(self.cur_line.points):
if self._is_near_point(point, event):
result = i
break
else:
result = None
return result
def Draw_key_pressed(self, event):
#print event.character
if "Enter" == event.character:
self.draw_polygon.line = copy.copy(self.cur_line)
self.polygons.append(self.draw_polygon)
self._re_set_Draw_Tool()
self.metadata["polygons"] = copy.copy(self.polygons)
self._update_cur_line()
self.event_state = "Normal"
def _re_set_Draw_Tool(self):
self.draw_polygon = Polygon()
self.points = []
self.draw_point = [0, 0]
self.line_color = "blueviolet"
self.cur_line = Line()
def Normal_key_pressed(self, event):
print event.character
if "m" == event.character:
self.event_state = "Move"
if "d" == event.character:
self.event_state = "Draw"
if "r" == event.character:
self.event_state = "Removeing"
if "e" == event.character:
self.event_state = "Exchange"
# Removeing Function
self.metadata["fuck"] = random(20)
print self.metadata["fuck"]
def Removeing_left_down(self, event):
polygon = self.Find_Polygon(event.x, event.y)
if polygon is not None:
self.polygons.remove(polygon)
self._updata_removeing_polygon()
self.event_state = "Normal"
def _updata_removeing_polygon(self):
self.metadata["polygons"] = copy.copy(self.polygons)
self._updata_removeing_polygon = True
def _updata_normal_flush(self):
self._normal_flush_updata = True
def _event_state_changed(self):
if self.event_state == "Normal":
self._updata_normal_flush()
#编辑状态
def Exchange_left_down(self, event):
polygon = self.Find_Polygon(event.x, event.y)
print polygon.line.points, "exchange"
if polygon is not None:
self.draw_polygon = copy.copy(polygon)
self.cur_line = copy.copy(self.draw_polygon.line)
self.points = copy.copy(self.cur_line.points)
self.polygons.remove(polygon)
self.event_state = "Draw"
self._updata_exchange_polygon()
self._update_cur_line()
def _updata_exchange_polygon(self):
self.metadata["polygons"] = copy.copy(self.polygons)
self._exchange_polygon_updata = True
2013年05月12日 星期日 19:17
不过在里面又遇到了新的问题,
上下有两个plot,
按照设计:
plot_top中显示
plot_bottom中绘图,
问题在于,plot_bottom中的数据存放于scatter.index.metatdata["data"]中
希望在plot_bottom更新界面的时候,将数据提供给plot_top绘图
我是通过在:
def __init__(self, datasource, **traits):
super(PlotForm, self).__init__(**traits)
self.datasource = datasource
。。。。。。
self.data= self.scatter.index.metadata
print self.data["data"]
def _data_changed(self,old,new):
print self.temp_fuck["data"],"print data"
但是我没办法捕获到data的变化,
我在操作绘图中,metadata中的data确实已经更新了的。
请在看一下。谢谢。
2013年05月12日 星期日 22:20
结合了若愚大哥书中的chaco_tools_lasso_selection.py
在初始化函数中添加了如下:
self.polygonController.on_trait_change(self._data_changed, "_update_move_polygon")
实时更新完成了。
Zeuux © 2024
京ICP备05028076号