English 中文(简体)
Is this typically how Java interfaces are used to set up event handlers, and are there hidden drawbacks to this approach?
原标题:

Hey all, I m still relatively new to Java, and looking for a sanity check.

I ve been studying this Java port of Cocos2D and noticed that the CCLayer class has built-in hooks to the Android native touch events. That s great, but what I d really like is for objects like CCSprite to directly respond to touch events without having to listen for those events in the layer and iterate through all the children to find which ones happen to intersect the event s x/y coordinates. So I figured that this would be the perfect chance to test my understanding of how to set up some event handlers and make a subclass of CCSprite that actually listens for touches without needing to go through CCLayer to know about it. Furthermore, I wanted to be able to assign different behaviors to different CCSprite instances on an ad-hoc basis without explicitly subclassing further, much like Android Buttons don t need to be subclassed just to give them a handler for their touch events.

This is what I came up with on a first pass:

// My touch interface for all touchable CCNode objects.

package com.scriptocalypse.cocos2d;

public interface ITouchable {

    boolean onCCTouchesBegan();
    boolean onCCTouchesEnded();
    boolean onCCTouchesMoved();

}

And now the class that uses the ITouchable interface for its callbacks...

public class CCTouchSprite extends CCSprite implements CCTouchDelegateProtocol {

    protected ITouchable mTouchable;

    public void setTouchable(ITouchable pTouchable){
        mTouchable = pTouchable;
        boolean enable = mTouchable != null;
        this.setIsTouchEnabled(enable);
    }

    public void setIsTouchable(boolean pEnabled){
            // code to enable and disable touches snipped...
    }



    /////
    //  And now implementing the CCTouchDelegateProtocol...
    /////
    public boolean ccTouchesBegan(MotionEvent event) {

        Log.d("hi there", "touch me");
        if(mTouchable != null){
        mTouchable.onCCTouchesBegan();
        }
        return CCTouchDispatcher.kEventHandled;  // TODO Auto-generated method stub
    }

    public boolean ccTouchesMoved(MotionEvent event) {

        if(mTouchable != null){
            mTouchable.onCCTouchesMoved();
        }
        return CCTouchDispatcher.kEventIgnored;  // TODO Auto-generated method stub
    }

    public boolean ccTouchesEnded(MotionEvent event) {
        Log.d("hi there", "not touch me");
        if(mTouchable != null){
            mTouchable.onCCTouchesEnded();
        }
        return CCTouchDispatcher.kEventIgnored;  // TODO Auto-generated method stub
    }

}

And finally, instantiate the class and implement the interface...

final CCTouchSprite sprite = new CCTouchSprite(tex);
sprite.setIsTouchEnabled(true);
sprite.setPosition(CGPoint.ccp(160,240));
sprite.setTouchable(new ITouchable(){
    @Override
    public boolean onCCTouchesBegan() {

        Log.d("SWEET SUCCESS", "I got a touch through my interface!");

        return true;
    }

    @Override
    public boolean onCCTouchesEnded() {
        Log.d("SWEET SUCCESS", "You stopped touching my interface!");
        sprite.runAction(CCRotateBy.action(1, 360));
        return false;
    }

    @Override
    public boolean onCCTouchesMoved(){
        Log.d("SWEET SUCCESS", "You moved the touch");
        return false;
    }
});

So all of this works. The subclass does successfully register with the Cocos2D touch dispatcher, which successfully calls those ccTouches functions and pass them MotionEvents, which in turn call my Interface functions if the interface has been instantiated.

Is this the "proper" way to do it (Define "it" as you see fit, ranging from using Interfaces to create event handlers to working with Cocos2D, to writing Java at all)? Are there drawbacks to this that I m not aware of? Is this somehow worse for performance than iterating through all the CCNode objects that are children of CCLayer? If so, how can that possibly be?

最佳回答

I think you have got the basics for setting up a listener right. There are some things I would change though.

First, the setter setIsTouchable. It s weird. You need a listener object to pass touch events to right? So what is this setter going to do when you pass it true (as your example does)? You snipped the code, but setting a boolean field to true does not seem right here as it would put the sprite object in an inconsistent internal state. I would just drop that setter. The getter can just evaluate whether mTouchable is assigned or null.

Second, why limit yourself to one listener? Change mTouchable to mTouchables, being a list of ITouchables. Then change setTouchable to addTouchable and possibly add removeTouchable and clearTouchables methods. This way you can add multiple listeners for different behaviors having to respond to the same events. This is how most other event systems work as well. You then just change isTouchable to check whether the list is empty or not.

问题回答

scriptoclypse... I really am not completely understanding your question, but you have not had any response and yes interfaces and events are very similar. At this level I can only respond in C#.





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签