Delphi中的组件事件检测

时间:2015-06-16 06:13:59

标签: delphi events components

我正在开发一个DataAware组件并在数据库打开后执行一些代码。

这是我目前的代码:

import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

def _blit_draw(self, artists, bg_cache):
    # Handles blitted drawing, which renders only the artists given instead
    # of the entire figure.
    updated_ax = []
    for a in artists:
        # If we haven't cached the background for this axes object, do
        # so now. This might not always be reliable, but it's an attempt
        # to automate the process.
        if a.axes not in bg_cache:
            # bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.bbox)
            # change here
            bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.figure.bbox)
        a.axes.draw_artist(a)
        updated_ax.append(a.axes)

    # After rendering all the needed artists, blit each axes individually.
    for ax in set(updated_ax):
        # and here
        # ax.figure.canvas.blit(ax.bbox)
        ax.figure.canvas.blit(ax.figure.bbox)

# MONKEY PATCH!!
matplotlib.animation.Animation._blit_draw = _blit_draw

vls = np.linspace(0,2*2*np.pi,100)

fig=plt.figure()
img, = plt.plot(np.sin(vls))
ax = plt.axes()
ax.set_xlim([0,2*2*np.pi])
#ttl = ax.set_title('',animated=True)
ttl = ax.text(.5, 1.05, '', transform = ax.transAxes, va='center')

ax.xaxis.set_animated(True)

def init():
    ttl.set_text('')
    img.set_data([0],[0])
    return img, ttl, ax.xaxis

def func(n):
    ttl.set_text(str(n))
    vls = np.linspace(0.2*n,0.2*n+2*2*np.pi,100)
    img.set_data(vls,np.sin(vls))
    ax.set_xlim(vls[0],vls[-1])
    return img, ttl, ax.xaxis

ani = animation.FuncAnimation(fig,func,init_func=init,frames=60,interval=200,blit=True)

plt.show()

代码正常工作,但链接到组件的数据集的事件AfterOpen不再被触发。  如何确保首先在数据集中然后在我的组件中触发AfterOpen事件?

是否有对数据集中的所有事件有效的解决方案(BeforeOpen,AfterOpen,BeforeCancel,BeforeDelete,AfterCancel,AfterDelete等等)?

3 个答案:

答案 0 :(得分:1)

您可以使用虚拟方法拦截器拦截DoAfterOpen虚拟呼叫

FVirtualIncerceptor := TVirtualMethodInterceptor.Create(TDataSet);
FVirtualIncerceptor.OnBefore := procedure(Instance: TObject; Method: TRttiMethod;
    const Args: TArray<TValue>; out DoInvoke: Boolean; out Result: TValue)
begin
  if Method.Name = 'DoAfterOpen' then
    ToBeExecutedOnAfterOpen(TDataset(Instance));
end;
FVirtualIncerceptor.Proxify(Self.DataSource.DataSet);

有关详情,请参阅此处 http://docwiki.embarcadero.com/CodeExamples/XE8/en/TVirtualMethodInterceptor_(Delphi)

我假设您可以看到如何扩展它以处理其他情况

答案 1 :(得分:0)

您必须在分配时保存旧的DataSet.AfterOpen,并在ToBeExecutedOnAfterOpen中调用该已保存的方法。 但正如阿贝利斯托在评论中已经说过的那样,这不是可行的方法。它不会通过您的要求成为对数据集中的所有事件有效的解决方案&#34;都不是。也许这有助于你:http://delphidabbler.com/tips/194

答案 2 :(得分:0)

您可以查看面向方面编程。就像@Jasper指出的那样......虚拟方法注入...

DSharp可以轻松地设置它。看看DSharp.Aspects.Weaver。您可以轻松地绑定到任何已发布或公开的方法。

-Rick