目标

实现剪贴板功能
实现
剪贴板完整代码
from collections import OrderedDict
from node_graphics_edge import QDMGraphicsEdge
from node_node import Node
from node_edge import Edge, EDGE_TYPE_BEZIER
DEBUG = False
class SceneClipboard():
def __init__(self,scene):
self.scene = scene
def serializeSelected(self, delete=False):
if DEBUG: print("---复制到剪贴板---")
sel_nodes, sel_edges, sel_sockets = [], [], {}
for item in self.scene.grScene.selectedItems():
if hasattr(item,'node'):
sel_nodes.append(item.node.serialize())
for socket in (item.node.inputs + item.node.outputs):
sel_sockets[socket.id] = socket
elif isinstance(item, QDMGraphicsEdge):
sel_edges.append(item.edge)
if DEBUG:
print(" NODES\n ", sel_nodes)
print(" EDGES\n ", sel_edges)
print(" SOCKETS\n ", sel_sockets)
edges_to_remove = []
for edge in sel_edges:
if edge.start_socket.id in sel_sockets and edge.end_socket.id in sel_sockets:
pass
else:
if DEBUG: print("edge", edge, "它未连接")
edges_to_remove.append(edge)
for edge in edges_to_remove:
sel_edges.remove(edge)
edges_final = []
for edge in sel_edges:
edges_final.append(edge.serialize())
data = OrderedDict([
('nodes', sel_nodes),
('edges', edges_final),
])
if delete:
self.scene.grScene.views()[0].deleteSelected()
self.scene.history.storeHistory("剪切")
return data
def deserializeFromClipboard(self, data):
hashmap = {}
view = self.scene.grScene.views()[0]
mouse_scene_pos = view.last_scene_mouse_position
minx, maxx, miny, maxy = 0,0,0,0
for node_data in data['nodes']:
x, y = node_data['pos_x'], node_data['pos_y']
if x < minx: minx = x
if x > maxx: maxx = x
if y < miny: miny = y
if y > maxy: maxy = y
bbox_center_x = (minx + maxx) / 2
bbox_center_y = (miny + maxy) / 2
offset_x = mouse_scene_pos.x() - bbox_center_x
offset_y = mouse_scene_pos.y() - bbox_center_y
for node_data in data['nodes']:
new_node = Node(self.scene)
new_node.deserialize(node_data, hashmap, restore_id=False)
pos = new_node.pos
new_node.setPos(pos.x() + offset_x, pos.y() + offset_y)
if 'edges' in data:
for edge_data in data['edges']:
new_edge = Edge(self.scene)
new_edge.deserialize(edge_data, hashmap, restore_id=False)
self.scene.history.storeHistory("粘贴")
复制到剪贴板
def serializeSelected(self, delete=False):
if DEBUG: print("---复制到剪贴板---")
sel_nodes, sel_edges, sel_sockets = [], [], {}
for item in self.scene.grScene.selectedItems():
if hasattr(item, 'node'):
sel_nodes.append(item.node.serialize())
for socket in (item.node.inputs + item.node.outputs):
sel_sockets[socket.id] = socket
elif isinstance(item, QDMGraphicsEdge):
sel_edges.append(item.edge)
if DEBUG:
print(" NODES\n ", sel_nodes)
print(" EDGES\n ", sel_edges)
print(" SOCKETS\n ", sel_sockets)
edges_to_remove = []
for edge in sel_edges:
if edge.start_socket.id in sel_sockets and edge.end_socket.id in sel_sockets:
pass
else:
if DEBUG: print("edge", edge, "它未连接")
edges_to_remove.append(edge)
for edge in edges_to_remove:
sel_edges.remove(edge)
edges_final = []
for edge in sel_edges:
edges_final.append(edge.serialize())
data = OrderedDict([
('nodes', sel_nodes),
('edges', edges_final),
])
if delete:
self.scene.grScene.views()[0].deleteSelected()
self.scene.history.storeHistory("剪切")
return data
先通过向sel_nodes, sel_edges, sel_sockets = [], [], {} 这两个数组,一个字典里添加被选中对象以及ID 接着
edges_to_remove = []
for edge in sel_edges:
if edge.start_socket.id in sel_sockets and edge.end_socket.id in sel_sockets:
pass
else:
if DEBUG: print("edge", edge, "它未连接")
edges_to_remove.append(edge)
for edge in edges_to_remove:
sel_edges.remove(edge)
edges_final = []
for edge in sel_edges:
edges_final.append(edge.serialize())
来删除被选中的edge中,有未完全连接上的edge,比如 
接着使用
data = OrderedDict([
('nodes', sel_nodes),
('edges', edges_final),
])
if delete:
self.scene.grScene.views()[0].deleteSelected()
self.scene.history.storeHistory("剪切")
来打包被选中的node和edge,并且通过传入的参数delete 来判断原选择项是否需要被删除
粘贴
完整代码
def deserializeFromClipboard(self, data):
hashmap = {}
view = self.scene.grScene.views()[0]
mouse_scene_pos = view.last_scene_mouse_position
minx, maxx, miny, maxy = 0, 0, 0, 0
for node_data in data['nodes']:
x, y = node_data['pos_x'], node_data['pos_y']
if x < minx: minx = x
if x > maxx: maxx = x
if y < miny: miny = y
if y > maxy: maxy = y
bbox_center_x = (minx + maxx) / 2
bbox_center_y = (miny + maxy) / 2
offset_x = mouse_scene_pos.x() - bbox_center_x
offset_y = mouse_scene_pos.y() - bbox_center_y
for node_data in data['nodes']:
new_node = Node(self.scene)
new_node.deserialize(node_data, hashmap, restore_id=False)
pos = new_node.pos
new_node.setPos(pos.x() + offset_x, pos.y() + offset_y)
if 'edges' in data:
for edge_data in data['edges']:
new_edge = Edge(self.scene)
new_edge.deserialize(edge_data, hashmap, restore_id=False)
self.scene.history.storeHistory("粘贴")
先计算被选中整体的中心坐标 接着计算当前鼠标位置与被选中整体的位置差值 接着使用原坐标+位置差值,即可得使复制项整体的中心坐标落在鼠标位置 并且通过使用 restore_id=False 创建新的对象
修个BUG
将View的鼠标中键释放事件的最后一行进行修改
def middleMouseButtonRelease(self, event):
fakeEvent = QMouseEvent(event.type(), event.localPos(), event.screenPos(),
Qt.LeftButton, event.buttons() | Qt.LeftButton, event.modifiers())
super().mouseReleaseEvent(fakeEvent)
self.setDragMode(QGraphicsView.RubberBandDrag)
原来的代码,在鼠标中键移动后就不能框选
|