我已经为类似图形的EMF模型实现了一个GEF编辑器,并为图中的某种类型的节点提供了删除命令。我想我已经完成了所有必要的步骤,以便使这个设置工作(vainolo'blog对我有很大的帮助。)
但是,当我删除模型元素时,视图不会刷新,即模型元素的图形不会从编辑器视图中删除,我没有想法为什么。如果有人可以查看我的资料并指出任何问题(以及可能的解决方案:),我将非常感激。非常感谢提前!
以下是我认为这个问题的重要类。如果我添加更多代码/编辑代码等,请告诉我。(我遗漏了我认为无效的代码,例如,getters和setter,类变量)。谢谢!的
的DiagramEditPart
public class DiagramEditPart extends AbstractGraphicalEditPart {
public DiagramEditPart(Diagram model) {
this.setModel(model);
adapter = new DiagramAdapter();
}
@Override protected IFigure createFigure() {
Figure figure = new FreeformLayer();
return figure;
}
@Override protected void createEditPolicies() {
installEditPolicy(EditPolicy.LAYOUT_ROLE, new DiagramXYLayoutPolicy());
}
@Override protected List<EObject> getModelChildren() {
List<EObject> allModelObjects = new ArrayList<EObject>();
if (((Diagram) getModel()).getMyNodes() != null)
allModelObjects.addAll(((Diagram) getModel()).getMyNodes());
return allModelObjects;
}
@Override public void activate() {
if(!isActive()) {
((Diagram) getModel()).eAdapters().add(adapter);
}
super.activate();
}
@Override public void deactivate() {
if(isActive()) {
((Diagram) getModel()).eAdapters().remove(adapter);
}
super.deactivate();
}
public class DiagramAdapter implements Adapter {
@Override public void notifyChanged(Notification notification) {
switch (notification.getEventType()) {
case Notification.REMOVE: refreshChildren();
break;
default:
break;
}
}
@Override public Notifier getTarget() {
return (Diagram) getModel();
}
@Override public void setTarget(Notifier newTarget) {
// Do nothing.
}
@Override public boolean isAdapterForType(Object type) {
return type.equals(Diagram.class);
}
}
}
MyNodeEditPart
public class MyNodeEditPart extends AbstractGraphicalEditPart {
public MyNodeEditPart(MyNode model) {
this.setModel(model);
adapter = new MyNodeAdapter();
}
@Override protected IFigure createFigure() {
return new MyNodeFigure();
}
@Override protected void createEditPolicies() {
installEditPolicy(EditPolicy.COMPONENT_ROLE, new MyNodeComponentEditPolicy());
}
@Override protected void refreshVisuals() {
MyNodeFigure figure = (MyNodeFigure) getFigure();
DiagramEditPart parent = (DiagramEditPart) getParent();
Dimension labelSize = figure.getLabel().getPreferredSize();
Rectangle layout = new Rectangle((getParent().getChildren().indexOf(this) * 50),
(getParent().getChildren().indexOf(this) * 50), (labelSize.width + 20),
(labelSize.height + 20));
parent.setLayoutConstraint(this, figure, layout);
}
public List<Edge> getModelSourceConnections() {
if ((MyNode) getModel() != null && ((MyNode) getModel()).getDiagram() != null) {
ArrayList<Edge> sourceConnections = new ArrayList<Edge>();
for (Edge edge : ((MyNode) getModel()).getDiagram().getOutEdges(((MyNode) getModel()).getId())) {
sourceConnections.add(edge);
}
return sourceConnections;
}
return null;
}
// + the same method for targetconnections
@Override public void activate() {
if (!isActive()) {
((MyNode) getModel()).eAdapters().add(adapter);
}
super.activate();
}
@Override public void deactivate() {
if (isActive()) {
((MyNode) getModel()).eAdapters().remove(adapter);
}
super.deactivate();
}
public class MyNodeAdapter implements Adapter {
@Override
public void notifyChanged(Notification notification) {
refreshVisuals();
}
@Override
public Notifier getTarget() {
return (MyNode) getModel();
}
@Override
public void setTarget(Notifier newTarget) {
// Do nothing
}
@Override
public boolean isAdapterForType(Object type) {
return type.equals(MyNode.class);
}
}
}
MyNodeComponentEditPolicy
public class MyNodeComponentEditPolicy extends ComponentEditPolicy {
@Override
protected Command createDeleteCommand(GroupRequest deleteRequest) {
DeleteMyNodeCommand nodeDeleteCommand = new DeleteMyNodeCommand((MyNode) getHost().getModel());
return nodeDeleteCommand;
}
}
DeleteMyNodeCommand
public class DeleteMyNodeCommand extends Command {
public DeleteMyNodeCommand(MyNode model) {
this.node = model;
this.graph = node.getDiagram();
}
@Override public void execute() {
getMyNode().setDiagram(null);
System.out.println("Is the model still present in the graph? " + getGraph().getMyNodes().contains(getMyNode()));
// Returns false, i.e., graph doesn't contain model object at this point!
}
@Override public void undo() {
getMyNode().setDiagram(getGraph());
}
}
Re execc的评论:是的,正在调用refreshChildren()
。我通过覆盖它并添加一条简单的System.err
行测试了这一点,该行在删除节点时显示在控制台上:
@Override
public void refreshChildren() {
super.refreshChildren();
System.err.println("refreshChildren() IS being called!");
}
有趣(好......)的事情是,当我关闭编辑器并保持模型,然后重新打开同一个文件时,节点不再被绘制,并且不存在于模型中。但是,这是什么意思?我是在做一个陈旧的模特吗?或者刷新/让模特儿童不能正常工作?
我刚刚发现了一件奇怪的事情,可能解释我所拥有的这些东西?在getModelChildren()
方法中,我呼叫allModelObjects.addAll(((Diagram) getModel()).getMyNodes());
,getMyNodes()
返回不可修改的 EList
。当我尝试在删除命令中沿着((Diagram) getModel()).getMyNodes().remove(getMyNode())
行执行某些操作时,我发现了它,并且它抛出了UnsupportedOperationException
... Hm。
呃,somebody kill me please?
我已经仔细检查过我是否一直在处理相同的Diagram
对象,而在这样做时我偶然发现了一个非常令人尴尬的的事情:
上一版本getModelChildren()
中的DiagramEditPart
方法读取约。像这样:
@Override protected List<EObject> getModelChildren() {
List<EObject> allModelObjects = new ArrayList<EObject>();
EList<MyNode> nodes = ((Diagram) getModel()).getMyNodes();
for (MyNode node : nodes) {
if (node.getDiagram() != null); // ### D'Uh! ###
allModelObjects.add(node);
}
return allModelObjects;
}
我想为偷走每个人的时间而道歉!您的建议非常有用,确实帮助我最终找到了错误!
我还学到了很多课程,其中包括:始终粘贴原始代码,过度简化可能会掩盖你的错误!我学到了很多关于EMF,Adapter
和GEF的知识。仍然:
答案 0 :(得分:0)
在代码的以下部分的第5行中有一个分号过多,即在if语句之后:if (node.getDiagram() != null);
:
1 @Override protected List<EObject> getModelChildren() {
2 List<EObject> allModelObjects = new ArrayList<EObject>();
3 EList<MyNode> nodes = ((Diagram) getModel()).getMyNodes();
4 for (MyNode node : nodes) {
5 if (node.getDiagram() != null);
6 allModelObjects.add(node);
7 }
8 return allModelObjects;
9 }