1

我正在开发具有“图像按钮”的 BlackBerry 应用程序。“图像按钮”可以在每次点击之间从“开”变为“关”,反之亦然。现在我要做的是,当应用程序关闭并再次加载时,这个“图像按钮”应该作为最后一个状态加载。如果“图像按钮”设置为“开”并且应用程序关闭,则在下次加载时它将加载为“开”。创建图像按钮时,如果该值设置为“true”,则图像加载为“ON”,即使它被创建为 off-on。我在构造函数之外创建了 ImageButton:

LabeledSwitch onImg=new LabeledSwitch(off,on,off,on,true); 

然后在构造函数中,我尝试检查最后一个图像状态,并相应地再次创建图像按钮。但是, (boolean)((Boolean) persistentHashtable.get("image")).booleanValue() 会抛出 CastException,即使它编译正常。

persistentObject = PersistentStore.getPersistentObject(KEY);

 if (persistentObject.getContents() == null) 
 {
    persistentHashtable = new Hashtable();
    persistentObject.setContents(persistentHashtable);
 } else {
    persistentHashtable = (Hashtable) persistentObject.getContents();
     }

  if (persistentHashtable.containsKey("image")) 
 {
     boolean booleanVal = (boolean)((Boolean) persistentHashtable.get("image")).booleanValue();
     if (booleanVal==true)
     {
         onImg=new LabeledSwitch(on,off,on,off,true);
     }
     else
     {
         onImg=new LabeledSwitch(off,on,off,on,false);
     }
 }

我在退出时保存图像的状态:

public boolean onClose() 
    {
        int choose=Dialog.ask(Dialog.D_YES_NO, "Are you sure Want to Exit?");
        if(choose==Dialog.YES)
        {
            if(onImg._on)
             persistentHashtable.put("image", Boolean.TRUE);

            else
                persistentHashtable.put("image", Boolean.FALSE); 
            System.exit(0);

        }
        return true;
    }

请指导。作为参考,下面是用于创建图像按钮的 LabeledSwitch 类:

import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;

public class LabeledSwitch extends Field {
    private String _textOn;
    private String _textOff;

    private int _textWidth;
    private int _textHeight;

    private int _totalWidth;
    private int _totalHeight;

    private Bitmap _imageOn;
    private Bitmap _imageOnFocus;
    private Bitmap _imageOff;
    private Bitmap _imageOffFocus;

    public boolean _on; //chngd
    private boolean _selected;

    private Font _labelFont;

    private static MenuItem _changeOptionsItem = new ChangeOptionMenuItem();

    private int _textColour = 0x888888;
    private int _textColourFocus = 0x000000;

    private int _horizontalTextImageGap;

    private Bitmap _switchImage;  
    private String _labelText;  
    int mHeight;
    int mWidth;

    public LabeledSwitch(){}

    public LabeledSwitch( Bitmap imageOn
                , Bitmap imageOff
                , Bitmap imageOnFocus
                , Bitmap imageOffFocus
                , boolean onByDefault ) {
        super( Field.FIELD_VCENTER );

        //_textOn = textOn ="";
        //_textOff = textOff ="";

        _imageOn = imageOn;
        _imageOff = imageOff;
        _imageOnFocus = imageOnFocus;
        _imageOffFocus = imageOffFocus;
        _on = onByDefault; 
        _selected = false;

        _horizontalTextImageGap = _imageOn.getHeight() / 3;

    }

    public void applyFont() {
        _labelFont = getFont().derive( Font.PLAIN, _imageOn.getHeight()  );
    }

    /**
     * Change the state of the switch
     * @param on - if true, the switch will be set to on state
     */
    public void setOn(boolean on) {
        _on = on;
        invalidate();
    }

    public boolean getOnState() {
        return _on;
    }

    public boolean isFocusable() {
        return true;
    }

    public int getPreferredWidth() {
        return _totalWidth;
    }

    public int getPreferredHeight() {
        return _totalHeight;
    }

    protected void layout( int width, int height ) {
        // 
        _textWidth = Math.max( _labelFont.getAdvance( _textOn + "a" ), _labelFont.getAdvance( _textOff + "a" ) )-36;
        _textHeight = _labelFont.getHeight();

        _totalWidth = _imageOn.getWidth() + _horizontalTextImageGap + _textWidth;
        _totalHeight = _imageOn.getHeight();

        mWidth = getPreferredWidth();
        mHeight = getPreferredHeight();
        setExtent(mWidth, mHeight);

       // setExtent( _totalWidth, _totalHeight );
    }

    public void paint( Graphics g ){
        Font oldFont = g.getFont();
        int oldColor = g.getColor();

        try { 

            if( _on ) {
                _switchImage = g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS) ? _imageOnFocus : _imageOn;
            } else {
                _switchImage = g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS) ? _imageOffFocus : _imageOff;
            }

            g.setFont( _labelFont );

            // Determine Label Colour
            g.setColor( g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS) ? _textColourFocus : _textColour );

            // Label
            g.drawText( _on ? _textOn : _textOff, 0, ( getHeight() - _textHeight ) / 2, DrawStyle.RIGHT, _textWidth ); 

            // Image
            //g.drawBitmap( _textWidth + _horizontalTextImageGap, 0, _switchImage.getWidth(), _switchImage.getHeight(), _switchImage, 0, 0 );
            g.drawBitmap(0, 5, mWidth, mHeight, _switchImage, 0, 0);
        } finally {
            g.setFont( oldFont );
            g.setColor( oldColor );
        }
    }

    public void paintBackground( Graphics g ) {}

    protected void drawFocus( Graphics g, boolean on ){
        // Paint() handles it all
        g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
        paint( g );
    }

    protected boolean keyChar( char key, int status, int time ){
        if( key == Characters.SPACE || key == Characters.ENTER ) {
            toggle();            
            return true;
        }
        return false;
    }

    protected boolean navigationClick(int status, int time){
        toggle();            
        return true;    
    }

    protected boolean invokeAction(int action){
        switch( action ) {
            case ACTION_INVOKE: {
                toggle(); 
                return true;
            }
        }
        return super.invokeAction( action );
    }

    protected boolean trackwheelClick( int status, int time ){        
        if( isEditable() ) {
            toggle();            
            return true;
        }
        return super.trackwheelClick(status, time);
    }

    /**
     * Toggles the state of the switch
     */
    private void toggle(){
        _on = !_on;
        invalidate();
        fieldChangeNotify( 0 );
    }

    public void setDirty( boolean dirty ){
        // We never want to be dirty or muddy
    }

    public void setMuddy( boolean muddy ){
        // We never want to be dirty or muddy
    }    

    protected void makeContextMenu(ContextMenu contextMenu){
        super.makeContextMenu(contextMenu);
        if((Ui.getMode() < Ui.MODE_ADVANCED) && isEditable()) {
            contextMenu.addItem(_changeOptionsItem);
        }
    }

    /**
     * @category Internal InnerClass
     */
    static class ChangeOptionMenuItem extends MenuItem {
        ChangeOptionMenuItem() {
            super("Toggle", 30270, 10);
        }

        ChangeOptionMenuItem(String text) {
            super(text, 30270, 10);
        }

        public void run() {
            LabeledSwitch theSwitch = (LabeledSwitch)getTarget();
            theSwitch.toggle();
        }

        public int getPriority() {
            return 100 + (getTarget().isMuddy() ? 1000 : 0);
        }
    };
}
4

2 回答 2

3

所以,我认为这里可能存在多个问题。我确实认为 Eugen 对这个commit()电话的看法是正确的。

但是,我认为LabeledSwitch该类的使用不正确。我猜你没有写那门课?我之所以这么说,是因为我在这一类中看到了多种编码约定。

看过多个这样的自定义 BlackBerry UI 类后,我相信这是该类应该工作的方式:

  1. 该类可以在两种视觉状态之间切换,您可以通过向该类传递一个表示开启状态和关闭状态的 PNG 图像来定义这种状态。

  2. 可以通过调用setOn()方法在这些状态之间切换类,参数为 atruefalse值。该参数的值将决定在类的自定义paint()方法中绘制哪个 PNG 文件

  3. 该类的原作者打算让您使用setOn()getOnState()方法来修改和访问开关的当前状态。你应该改变这个

public boolean _on;

对此:

private boolean _on;

如果您想知道开关是否打开,请询问onImg.getOnState()

顺便说一句,我会为您的交换机推荐一个不同于onImg. 这是一个非常混乱的名字。如果开关用于关闭和打开名为foo的东西,它应该类似于onOffSwitch, or toggleSwitch, or 。在成员变量的上下文中命名它是令人困惑的,它应该始终表示在开关打开时显示的图像fooSwitchonImg_imageOn

所以,总结一下,而不是这样:

 if (booleanVal==true)
 {
     onImg=new LabeledSwitch(on,off,on,off,true);
 }
 else
 {
     onImg=new LabeledSwitch(off,on,off,on,false);
 }

使用这样的东西:

 onOffSwitch = new LabeledSwitch(on, off, on, off, true);
 onOffSwitch.setOn(booleanValue);        

或者

 onOffSwitch = new LabeledSwitch(on, off, on, off, booleanValue);
于 2012-11-28T08:28:31.380 回答
1

首先,我没有看到存储持久对象所需的以下代码:

persistentObject.commit();

我希望这只是您代码中的几个额外内容,否则您总是在阅读之前重写值,这可能不是预期的。所以'读'代码不应该留在'写'之后,因为它没有任何意义。

于 2012-11-28T06:58:36.207 回答