0

当我在 C# 中编程时,我经常使用事件。现在我想在 Java 中实现类似的东西。我知道这两种语言是不同的,并且在实现这种机制方面存在一些差异。好吧,为了提供更好的图片,也许我会描述一下我想要得到的东西,因为我可能会混淆一些术语:

MyClass包含处理启动MyEvent的代码和在某些情况下启动该事件的一些代码。

MyEventArgs是从MyClass传输数据并与事件启动一起发送的类,因此处理MyEvent的函数具有有关MyClass实例状态的一些附加信息。

并且有一个MyApp类,在 main 方法中包含MyClass的实例和处理MyEvent的代码,当在MyClass内引发事件时,某些操作在侦听MyEvent的代码中执行。

如果仍然不清楚,我的意思是实现就像按钮单击背后的 c# 机制一样,只是没有按钮,而是有我的类,有我的事件参数而不是鼠标事件参数,并且有我设计的行为而不是单击.

我试图用谷歌搜索我的问题的一些答案,例如我发现了以下网站:

http://javarevisited.blogspot.com/2011/12/observer-design-pattern-java-example.html http://www.javaworld.com/javaworld/javaqa/2002-03/01-qa-0315-happyevent .html

或者我只是迷路了,我正在寻找不好的地方/使用错误的关键字,或者更有可能我无法理解这些示例中的任何内容/我无法将它们转换为我需要的工作方式。

我要求的是一些示例,或者至少是一些使用MyClass、 MyEvent、 MyEventArgs、名称、指向代码来处理这种机制的代码草案,我应该在我的类中使用来引发事件以及类的一些示例使用和事件处理在 Main 方法中,所以它可以帮助我解决这个问题。

==========编辑========

也许有一些类似的东西可供android开发人员使用?因为我的目标是在我尘封 java 之后进入移动应用程序开发。

==========编辑========

如果有人仍然感兴趣,这里是一些示例代码,它不使用我提到的名称,只是一般显示我在寻找什么:

并且没有确切的解决方案,也许有人会提出类似于我正在寻找的东西的建议?

frmTest.cs

namespace SampleApp
{
    public partial class frmTest : Form
    {
        CountdownTimer ctmrTest;

        public frmTest()
        {
            InitializeComponent();
            ctmrTest = new CountdownTimer(100);
            ctmrTest.CountdownTimerTick += new CountdownTimer.CountdownTimerTickEventHandler(ctmrTest_CountdownTimerTick); 
        }

        void ctmrTest_CountdownTimerTick(object sender, CountdownTimerEventArgs ea)
        {
            lblTimer.Text = ea.timeString;
            if (ea.countdownFinished) countdownEnd();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            ctmrTest.Reset();
            ctmrTest.Start();
        }

        void countdownEnd()
        {
            MessageBox.Show("Finish");
        }
    }
}

倒计时计时器.cs

namespace SampleApp
{
    public class CountdownTimer
    {
        Timer tmrTicks = new Timer();
        int secondsLeft = 0;
        int numberOfSecondsToCountdown = 0;

        public bool IsWorking
        {
            get { return tmrTicks.Enabled; }
        }

        public CountdownTimer(int seconds)
        {
            ...
        }

        void tmrTicks_Tick(object sender, EventArgs e)
        {
            ...
            WhenCountdownTimerTick(new CountdownTimerEventArgs(secondsLeft, numberOfSecondsToCountdown, true));
        }

        public void Reset()
        {
            ...
            WhenCountdownTimerTick(new CountdownTimerEventArgs(secondsLeft, numberOfSecondsToCountdown, false));
        }

        public void Stop()
        {
            tmrTicks.Enabled = false;
        }

        public void Start()
        {
            ,,,
        }

        public delegate void CountdownTimerTickEventHandler(object sender, CountdownTimerEventArgs ea);

        public event CountdownTimerTickEventHandler CountdownTimerTick;

        protected virtual void WhenCountdownTimerTick(CountdownTimerEventArgs ea)
        {
            if (CountdownTimerTick != null)
            {
                CountdownTimerTick(this, ea);
            }
        }
    }
}

CountdownTimerEventArgs.cs

namespace SampleApp
{
    public class CountdownTimerEventArgs : EventArgs
    {
        public string timeString = "";
        public bool countdownFinished = false;

        public CountdownTimerEventArgs(int secondsLeft, int SecondsToCountdown, bool isfinished)
        {
            countdownFinished = isfinished;
            timeString = string.Format("{0:00}:{1:00}", secondsLeft / 60, secondsLeft % 60);
        }
    }
}
4

2 回答 2

3

如果我理解正确(我刚刚开始学习 C#),那么在 Java 中执行此操作的正常方法是使用观察者模式(侦听器模式):

您创建一个侦听器接口,其中包含在事件发生时要调用的方法。如果您愿意,该方法可以将一些事件参数和发送者作为参数。例如:

public interface MyListener { // This is probably your MyEvent
    void myEventFired(Object sender, MyEventArgs eventArgs);
}

public class MyEventArgs {
    ...something...
}

一个响应你的事件的类,需要实现上述接口。(见下面的一个例子(MyListeningClass))

好的,那么您需要一个触发您的事件的类(或更多类):MyClass。通常MyClass有一些方法让其他想要响应MyClass事件的类向MyClass注册自己。(或者更准确地说,使用MyClass的特定对象注册自己)。这允许MyClass -object 知道它应该在事件发生时通知哪些其他对象。

这通常通过在触发事件的类中创建一个名为“add[ListenerName]”的方法来完成 - 在本例中为MyClass中的“ addMyListener ” 。为了使这个例子更简单,我们假设只能有一个监听器,所以我们将它命名为“ setMyListener ”:

public class MyClass {

    private MyListener listener = null;

    // This is a method which sometimes fires an event, by calling the fireEvent() method below
    public void doSomething() {
        ...
        if (something) {
            // Let's say the event happens if "something" is true. 
            // So now we "fire the event". What "firing the event" means, 
            // is just to call the "myEventFired" method in the listener.
            fireEvent();
        }
        ...

    }

    // this is called from the method above to fire the event - i.e. to tell the listener that the event has happened
    protected void fireEvent() {
        if (listener != null) {
            Object sender = this; 
            MyEventArgs eventArgs = new MyEventArgs(...something...);
            listener.myEventFired(sender, eventArgs);
        }
    }

    // This method is called by the listener, to register itself as listener on this object.
    // MyClass remembers the listener in the "listener" instance variable, so that 
    // when the event happens at some later point in time, it knows which object it  
    // has to tell it to.
    public void setMyListener(MyListener listener) {
        this.listener = listener;
    }
}

(要支持多个监听器,只需有一个监听器列表List<MyListener> listeners而不是MyListener listener实例变量,并创建一个 addListener 和 removeListener 方法而不是 setListener 方法。在 Android API 中,它们通常只允许一个监听器,所以我想我会显示那个版本)

所以现在我们只需要想要监听事件的类。即实现MyListener接口的类。(因此这个类是一个监听器)。一个简单的例子:

public class MyListeningClass implements MyListener {

    public MyListeningClass() {
        MyClass myClass = ...get the MyClass object from somewhere...;
        myClass.setMyListener(this);
    }

    // this is called by MyClass when the event occurs
    public void myEventFired(Object sender, MyEventArgs eventArgs) {
        System.out.println("EVENT HAPPENED!");
        System.out.println("Sender is: "+sender);
        System.out.println("MyEventArgs are: "+eventArgs);
    }    
}

(当然,如果您不想创建接口,则实际上不必创建接口。您当然可以在 MyClass 中硬编码 MyListeningClass,但使用接口更好的样式,将 MyClass 和 MyListeningClass 彼此分离。以后它也将更加可扩展,以允许除 MyListeningClass 之外的其他类也可以监听事件。)

Java API 中有很多这样的例子。例如 SWING 大量使用侦听器 - 例如您提到的按钮点击。当然还有 Android API。

我会看看我以后能不能找到一些这样的例子,但是已经很晚了,我很累,所以也许明天:D(并修复任何拼写错误:D)。希望它有所帮助。

回顾一下:

  • MyClass(产生事件的类)需要某种方式来告诉其他类该事件已经发生,事件何时发生。它通过在事件发生时调用这些类中的方法来做到这一点。

  • 为了让MyClass能够调用这些其他类中的方法,它们必须实现一些接口。

  • 想要在事件发生时被告知的类,需要一种方法来告诉MyClass他们想要被告知它。这就是我们需要MyClass.setMyListener方法的原因。 (或者如果我们允许多个侦听器:MyClass.addMyListener方法)

(所以这并没有什么神奇之处。它只是简单的方法调用。)




(请注意,侦听器接口通常命名为“[事件名称]Listener”。因此,根据命名约定,如果我们说事件被称为“ MyEvent”。但是对于这篇文章,我认为它看起来太长而且不太简单。更新:现在我想起来了,实际上你通常会从名称中省略“Event”,所以“MyListener”是正确的。例如,如果你有一个事件你调用“OnClickEvent”,你调用接口“OnClickListener”。)

于 2012-11-07T04:04:52.007 回答
0

您最好的选择可能是使用Google Web Toolkit (GWT). GWT Widgets您可以使用与使用 Visual Studio/C# 相同的方式定义事件处理程序。

Eclipse 甚至有一个内置的窗口构建器插件。

于 2012-11-07T03:33:11.687 回答