不用写代码的感觉更爽

3 篇文章 0 订阅

问题是这样的,要在Chart中画一个背景区域。这个很容易,窗口里在Chart的OnBeforeDrawAxes里写下绘制的代码就OK了。

下一步的问题是在不同的步骤可能需要多个背景区域,那么每次都在窗口里拷贝代码明显是不合适的。我准备把绘制工作放到一个专门的类中处理。在类创建的时候把需要绘制的Chart传入并接管它的事件,每次Chart重绘时触发OnBeforeDrawAxes就会调用Area的绘制方法。那么每当需要为某个Chart增加这种背景时只要:
    Area := TArea.Create(Chart);

好了,目前都比较简单,下来我想要能够绘制多个区域,我希望可以这样:
    Area1 := TArea.Create(Chart);
    Area2 := TArea.Create(Chart);
问题来了,Delphi的事件机制是采用函数指针来处理的,也就是Area把自己的函数的地址交给Chart,让它在合适的时候调用,可是现在有两个函数,却只有一个指针。简单的象刚才那样写就只会画出第二个区域。

我想起来原来遇到过这样的问题,当时是这么解决的,在需要处理事件的对象接管之前,保存原有的事件处理函数的指针,并在每次触发后执行原有的事件。代码大概会这样:
    procedure TArea.Create(aChart: TChart);
    begin
      ...
      FOldEventFunc := aChart.OnBeforeDrawAxes; {保留原有处理}
      aChart.OnBeforeDrawAxes := DrawArea;   {接管事件}
    end;  

    procedure TArea.DrawArea(Sender: TObject);
    begin
      ...  {绘制}
      if Assigned(FOldEventFunc) then
        FOldEventFunc(Sender);
    end;
这样,多个处理事件的对象就会象一个链条一样挨个触发一遍。


很不幸的是,我也想起原来使用这个方法的一个问题,如果不小心一个对象接管了两次,那么就会形成一个环,这个事件处理就会死循环了。另一方面,在处理某个具体事件的对象中强制加入这样一个约定,感觉在结构上也不太完善。

这样,我开始考虑更好的方案。可以写一个EventManager来管理Chart的所有事件,对每个事件,EventManager里都有一个事件列表,而每个需要监听事件的对象,都不是直接更改Chart的事件指针,而是通过EventManager的AddXXXEventListener来加入。在每次事件触发的时候,由EventManager来遍历调用列表里的每个监听者的事件处理函数。那么在TArea的构造函数中应该这样:
    EventManager.AddBeforDrawAxesLintener(DrawArea);


考虑到我并不想在创建区域的时候还要自己创建一个EventManager,所以应该有一个全局的工厂类,负责为需要绘制的Chart维持一个EventManager。构造函数中改为这样:
    EMFactory.GetChartEM(aChart).AddBeforDrawAxesLintener(DrawArea);
好了,现在基本上已经有了一个我满意的方案,我已经开始考虑写一个示例用的测试用例,生成一个事件源和两个监听者,表示一下这个结构是如何工作的。

可是……可是,在我正在为测试用例起名字的时候,突然脑子里响起了那句名言:“你不会需要它的。”我真的需要这么复杂的一个东西么?虽然说我相信它足够通用,结构也足够清晰,不过好像还是太复杂了,我不会用到这么复杂的东西,不是么?

回头再看看,我需要绘制多个区域。(但愿我还没忘了要作什么),那么一个绘制对象在一次响应的时候依次绘制不就可以了么。我只需要稍稍调整一下原来设想的使用方法:
    AreaPainter := TAreaPainter.Create(Chart);
    AreaPainter.NewArea;
    ...  {设置区域属性}
    AreaPainter.NewArea;
    ...
这样不就解决了么?而且在真的要画第二块区域前完全不需要实现NewArea方法,那么这个绘制对象,几乎不会比最初设想的Area复杂多少,哈哈,真是自己把自己搞糊涂了。
现在可以不用去理会那个复杂的东西,开始编写简单的实现了,唯一的遗憾是界面绘制不适合采用单元测试。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值