目标
按住shift键可以进行多选
在背景上按住左键可以框选
shift+框选也能实现多选接力
实现
将setStyleSheet功能从NODE移动到主页
为了方便view里面的控件样式设计,需要将NODE移动到main程序里执行
class NodeEditWind(QMainWindow,Ui_MainWindow):
def __init__(self,parent=None):
super(NodeEditWind,self).__init__(parent)
self.setupUi(self)
self.scene = Scene()
self.grScene = self.scene.grScene
self.addNode()
self.view = QDMGraphicsView(self.grScene,self)
self.Layout_node.addWidget(self.view)
self.stylesheet_filename = 'qss/nodestyle.qss'
self.loadStylesheet(self.stylesheet_filename)
def loadStylesheet(self, filename):
print('STYLE loading', filename)
file = QFile(filename)
file.open(QFile.ReadOnly | QFile.Text)
stylesheet = file.readAll()
QApplication.instance().setStyleSheet(str(stylesheet, encoding='utf-8'))
增加shift多选功能
首先在鼠标左键按下添加新的按下逻辑判断
def leftMouseButtonPress(self, event):
item = self.getItemAtClick(event)
self.last_lmb_click_scene_pos = self.mapToScene(event.pos())
if hasattr(item, "node") or isinstance(item, QDMGraphicsEdge) or item is None:
if event.modifiers() & Qt.ShiftModifier:
event.ignore()
fakeEvent = QMouseEvent(QEvent.MouseButtonPress, event.localPos(), event.screenPos(),
Qt.LeftButton, event.button() | Qt.LeftButton,
event.modifiers() | Qt.ControlModifier)
super().mousePressEvent(fakeEvent)
return
if type(item) is QDMGraphicsSocket:
if self.mode == MODE_NOOP:
self.mode = MODE_EDGE_DRAG
self.edgeDragStart(item)
return
if self.mode == MODE_EDGE_DRAG:
res = self.edgeDragEnd(item)
if res: return
super().mousePressEvent(event)
其中hasattr是判断选中项是否为node,isinstance是判断选中项是否为QDMGraphicsEdge对象,最后一个点空白处框选
Qt.ShiftModifier检测是否按下shift,而众所周知的是,在windows系统下,使用crtl加上鼠标左键可以完成多选,我们需要使用shit来替代ctrl的功能,所以需要设置一个fakeEvent来让鼠标事件变为左键+crtl事件
为了使view能使用框选功能,需要在view的init里增加新的代码
self.setDragMode(QGraphicsView.RubberBandDrag)
当然,为了在不同的操作系统中拥有相同的显示效果,我们需要在QSS做新的定义
QDMNodeContentWidget {background: transparent; }
QDMNodeContentWidget QLabel {color: #e0e0e0;}
QGraphicsView {selection-background-color: rgb(255,255,255);}
接着就是鼠标松开事件 与鼠标左键同理,这里只贴增加的代码
if hasattr(item, "node") or isinstance(item, QDMGraphicsEdge) or item is None:
if event.modifiers() & Qt.ShiftModifier:
event.ignore()
fakeEvent = QMouseEvent(event.type(), event.localPos(), event.screenPos(),
Qt.LeftButton, Qt.NoButton,
event.modifiers() | Qt.ControlModifier)
super().mouseReleaseEvent(fakeEvent)
return
在多选后,用鼠标左键拖动,就可以带动全部节点拖动 但是会发现有的Edge不随NODE移动,这是一个显示BUG,需要修复
显示BUG修复
为什么会有这个BUG,是因为node的刷新机制的问题,要解决这个问题,需要保证每个node移动的时候,edge都进行了刷新 除了这个BUG,还有一个BUG,就是选中标题时会导致多选取消,这是因为标题没有"node"这个属性,我们需要在node_graphics_node.py中的
def initTitle(self):
添加
self.title_item.node = self.node
使其也与本体指向同一个NODE属性
首先需要能保证移动一个node的时候能完成整个node的遍历,于是需要 进入node_graphics_node.py 将鼠标移动代码修改为如下
def mouseMoveEvent(self, event):
super().mouseMoveEvent(event)
# 更新被选择NODE的EAGE
for node in self.scene().scene.nodes:
if node.grNode.isSelected():
node.updateConnectedEdges()
for node in self.scene().scene.nodes: 用于遍历 而if node.grNode.isSelected(): 判断节点是否被选中,选中的更新,没被选中的不更新
|