20120212 关于gef的part,policy浅析

本文深入探讨了在GEF框架中如何合理地使用Part、Policy和Command,尤其针对初学者在添加Policy时的选择和注意事项。通过分析源码,解释了Policy的作用及获取方式,以拖拽操作为例,演示了如何正确安装Policy以实现复杂操作。文章旨在帮助开发者更好地理解和应用GEF框架。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

随着时间的推移,任务已经完成的差不多了,虽然不是一帆风顺但是遇到的问题还是逐一解决了。因为前一段时间春节放假,年终晚会,等等原因,所以一直没有写开发日志。先说一个题外话就是关于过节,我个人十分的讨厌过节,因为它会影响我的正常生活,比如我正常的生活要写开发日志,要深入的研究gef,要看书但是都因为过节而搁浅了。春节前2天,公司里的人就只剩十几个人了,根本没有心情工作。当然了我说的是长假。2,3天的节假日还是可以的。

废话少说,进入主题。

关于part,policy和command对于初学者来说很头疼,不知道应该在什么样的part中添加什么样的policy是我刚刚开始gef的时候最困惑的事情。而网上说的不是很详细,网友们给我的大夫就只是:看看源码就清楚了。当时对于初学之来讲看懂源码真的是太难了,因为gef的mvc编程模式虽然在编程的时候很好用,但是在看源码的时候没有一定的积累很难看明白。现在我就给大家分析分析分析。

以前看到过一个英文的关于policy的用途的说明,说的很明白,但是找不到了,我就跟大家自述一下:检查接收到的请求(request)是否有相应的操作流程。说白了就是说例如我们对我们已经存在的控件进行了双击,而系统会捕获到这个事件,并发送到part一个位置,在这个位置里part检查是否有相应的处理事件的操作(command),如果有就执行这个操作,如果没有的话就销毁这个请求(request)。

在AbstractEditPart中源码是这样的:

    public Command getCommand(Request request) {
        Command command = null;
        EditPolicyIterator i = getEditPolicyIterator();
        while (i.hasNext()) {
            if (command != null)
                command = command.chain(i.next().getCommand(request));
            else
                command = i.next().getCommand(request);
        }
        return command;
    }

我们的part都要继承AbstractEditPart。而系统把接收到的事件传到这个方法中,然后getCommand方法会遍历所有的安装的policy,并获取并返回command。当然了,如果command为空就撤销request,如果不为空就执行。那么policy是在那里得到的呢?
    @Override
    protected void createEditPolicies() {
        super.createEditPolicies();
        installEditPolicy("myPolicy", new MyAbstractEditPolicy());
    }

在我们新建part的时候都要重写这个方法,而这个installEditPolicy这个方法就把我们的policy安装了进去。所以getEditPolicyIterator就是获得的我们所安装进的policy。然后调用policy的getCommand方法来获取到相应的command。

下面我以拖拽为例给大家举例讲解一下。

首先我们要在我们的part上面添加policy,而这个policy应该添加到那里呢?是应该添加到容器里面呢还是应该添加到容器里的节点上呢?这要看我们具体的做法。我们先分析一下我们要对拖拽进行操作,而最终的做法就是就是改变节点里面的constraint(约束:位置,大小)属性然后再刷新。而要修改的话我们就需要model。

在partfactory中我们通常的做法是这样的
    @Override
    public EditPart createEditPart(EditPart context, Object model) {
        MyEditPartWithListener part = getPartFromElement(model);
        part.setModel(model);
        return part;
    }

就是说在创建part的时候就把model注入了进去,所以要想获取到model的话就要先得到part。而installEditPolicy的做法是这样的

......
        if (editPolicy != null) {
            editPolicy.setHost(this);
            if (isActive())
                editPolicy.activate();
        }

就是说吧part注入到了policy里面。所以说白了就是policy按在了那个part上,就能获取到那个part,就能获取到相应的model。那么我们的操作时要更改model里面的constraint属性所以要获取节点的model,所以要获取节点的part所以我们要把这个policy安装到节点上面。当然了,安装在节点里肯定没有问题,但是我们再想想,如果我们想同时修改多个节点的位置怎么办!在仅有的设计里是实现不了的。gef中把这种设计放到了request里面我们看看需要的ChangeBoundsRequest。在它的父类里有一个list装的是EditPart

而我们再看看我们的policy的父类。刚刚说了,在AbstractEditPart中我们会遍历安装了的policy,然后调用policy的getCommand方法。那我们就看看XYLayoutEditPolicy的getCommand方法:通过调用,我们看一看到:

protected Command getChangeConstraintCommand(ChangeBoundsRequest request) {
        CompoundCommand resize = new CompoundCommand();
        Command c;
        GraphicalEditPart child;
        List children = request.getEditParts();

        for (int i = 0; i < children.size(); i++) {
            child = (GraphicalEditPart) children.get(i);
            c = createChangeConstraintCommand(
                    request,
                    child,
                    translateToModelConstraint(getConstraintFor(request, child)));
            resize.add(c);
        }
        return resize.unwrap();
    }

正是他调用createChangeConstraintCommand(ChangeBoundsRequest request, EditPart child, Object constraint),然后在调用我们需要重写的createChangeConstraintCommand(EditPart child,Object constraint),这里面的part是来自于request的,并不是来自于policy。所以这样,每一个被选中的part都可以得到相应的修改。所以,这个policy安装在节点里或者容器里都可以。如果按在节点里的话那么每一种节点都要安装一遍,所以我们把它安装在容器里面,这样少一些代码。

首先我们继承XYLayoutEditPolicy并重写createChangeConstraintCommand方法,至于command怎么去写不是今天的重点,就不说了。然后把我们的XYLayoutEditPolicy安装到容器的part中就可以了。

至于其他的policy也是同样的道理。大家自己发挥吧。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值